Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
![badge-support-js-ir]
![badge-support-linux-arm]

A Kotlin Multiplatform library for obtaining cryptographically secure random data.
A Kotlin Multiplatform library for procuring cryptographically secure random data.

The Linux/AndroidNative implementation was heavily inspired by [rust-random/getrandom][url-rust-random].

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ public abstract class CryptoRand @DelicateCryptoRandApi protected constructor()
* - Node: [Crypto.randomFillSync()](https://nodejs.org/api/crypto.html#cryptorandomfillsyncbuffer-offset-size)
* - WasmWasi: [random_get](https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#random_get)
* - Native:
* - Android Native targets: [getrandom(2)](https://www.man7.org/linux/man-pages/man2/getrandom.2.html). If unavailable, `/dev/urandom` is used.
* - Linux targets: [getrandom(2)](https://www.man7.org/linux/man-pages/man2/getrandom.2.html). If unavailable, `/dev/urandom` is used.
* - Apple targets: [SecRandomCopyBytes](https://developer.apple.com/documentation/security/1399291-secrandomcopybytes)
* - Linux & Android Native targets: [getrandom(2)](https://www.man7.org/linux/man-pages/man2/getrandom.2.html)
* when available (GLIBC 2.25+ & Android API 23+), with a fallback to reading from `/dev/urandom` after polling
* `/dev/random` once (per process lifetime) to ensure appropriate levels of system entropy are had.
* - Apple targets: [CCRandomGenerateBytes](https://github.com/apple-oss-distributions/CommonCrypto/blob/main/include/CommonRandom.h)
* - Windows targets: [BCryptGenRandom](https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom)
* */
public companion object Default: CryptoRand() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,33 @@ open class CryptoRandUnitTest {

protected open val cryptoRand: CryptoRand = CryptoRand.Default

private companion object {
private const val LIMIT_LINUX = 256
private const val LIMIT_WEB = 65536
}

// https://github.com/briansmith/ring/blob/main/tests/rand_tests.rs
@Test
fun givenArray_whenNextBytes_thenIsFilledWithData() {
val linuxLimit = 256
val webLimit = 65536

listOf(
1,
2,
3,
96,
linuxLimit - 1,
linuxLimit,
linuxLimit + 1,
linuxLimit * 2,
LIMIT_LINUX - 1,
LIMIT_LINUX,
LIMIT_LINUX + 1,
LIMIT_LINUX * 2,
511,
512,
513,
4096,
webLimit - 1,
webLimit,
webLimit + 1,
webLimit * 2,
LIMIT_WEB - 1,
LIMIT_WEB,
LIMIT_WEB + 1,
LIMIT_WEB * 2,
// To ensure remainder logic is working properly for JS/WasmJS
(webLimit * 2) + 6_000,
(LIMIT_WEB * 2) + 6_000,
).forEach { size ->
val zeroCount = cryptoRand.nextBytes(buf = ByteArray(size)).count { it == 0.toByte() }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,17 @@
package org.kotlincrypto.random.internal

import kotlinx.cinterop.*
import platform.Security.SecRandomCopyBytes
import platform.Security.kSecRandomDefault
import org.kotlincrypto.random.RandomnessProcurementException
import platform.CoreCrypto.CCRandomGenerateBytes
import platform.CoreCrypto.kCCSuccess

@Throws(RandomnessProcurementException::class)
internal actual fun ByteArray.cryptoRandFill() {
@OptIn(ExperimentalForeignApi::class, UnsafeNumber::class)
val status = usePinned { pinned ->
// kSecRandomDefault is synonymous to NULL
SecRandomCopyBytes(kSecRandomDefault, size.toUInt().convert(), pinned.addressOf(0))
CCRandomGenerateBytes(pinned.addressOf(0), size.toUInt().convert())
}

if (status == 0) return
throw RandomnessProcurementException("Failed to obtain bytes from [SecRandomCopyBytes]. Code: $status")
if (status == kCCSuccess) return
throw RandomnessProcurementException("Failed to obtain bytes from [CCRandomGenerateBytes]. kCCStatus: $status")
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ private inline fun getrandom2(buf: CPointer<ByteVar>, buflen: size_t, flags: u_i
return syscall(SYS_getrandom.convert(), buf, buflen, flags).convert()
}

// getrandom(2) available on Linux LIBC 3.17+, and Android Native API 28+
// getrandom(2) available for Linux Kernel 3.17+ (Android API 23+)
@OptIn(ExperimentalForeignApi::class, UnsafeNumber::class)
internal val HAS_GET_RANDOM: Boolean by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
val buf = ByteArray(1)
Expand Down