New
wasm()
target is highly experimental and lacks documentation. But in case you want to try it, you can use
@JsFun
to call JS functions. Sharing
ByteArray
with JavaScript is not supported at the moment, so your best bet would be returning random
Int
multiple times and unpack them into bytes:
@JsFun("""() => {
var array = new Uint32Array(1);
globalThis.crypto.getRandomValues(array);
return array[0];
}""")
external fun secureNextRandomInt(): Int
In upcoming 1.8.20 you’ll be able to use WebAssembly linear memory to reduce number of calls to JavaScript:
@JsFun("""(memoryAddress, sizeInBytes) => {
var array = new Uint8Array(wasmExports.memory.buffer, memoryAddress, sizeInBytes)
globalThis.crypto.getRandomValues(array);
}""")
external fun fillLinearMemoryWithSecureRandomData(memoryAddress: Int, sizeInBytes: Int)
@OptIn(UnsafeWasmMemoryApi::class)
fun fillByteArrayWithSecureRandomData(array: ByteArray) {
withScopedMemoryAllocator { allocator ->
val ptr = allocator.allocate(array.size)
fillLinearMemoryWithSecureRandomData(ptr.address.toInt(), array.size)
for (i in array.indices) {
array[i] = (ptr + i).loadByte()
}
}
}
Running Kotlin in a WASI environment is even more experimental, but in case you are interested, you can find
experiments with secure random generation in kowasm project