Compare commits

...

8 Commits

Author SHA1 Message Date
d9454fcdb2 Merge pull request '1.3.1 Release' (#5) from develop into main
All checks were successful
/ publish (push) Successful in 3m6s
Reviewed-on: Infendro/prng-kt#5
2026-03-12 10:34:32 +00:00
06d86a6679 Bump version to 1.3.1
All checks were successful
/ test (pull_request) Successful in 25s
2026-03-12 11:33:28 +01:00
a28cb7d2f9 Upgrade dependencies 2026-03-12 11:32:31 +01:00
8fab26a476 Fix algorithm name in README 2026-02-19 12:57:36 +01:00
3465a60cb1 Merge pull request '1.3.0 release' (#4) from develop into main
All checks were successful
/ publish (push) Successful in 1m50s
Reviewed-on: Infendro/prng-kt#4
2026-02-19 11:56:22 +00:00
2aed836e67 Upgrade dependencies
All checks were successful
/ test (pull_request) Successful in 32s
2026-02-19 12:46:41 +01:00
2ae6fda70e implement xoshiro256++ and xoshiro256**
All checks were successful
/ test (pull_request) Successful in 38s
2026-01-30 15:16:48 +01:00
2c6fe0a7d9 further optimize HMAC-DRBG 2026-01-30 15:10:04 +01:00
7 changed files with 96 additions and 19 deletions

View File

@@ -4,6 +4,8 @@
Supported [PRNG](https://en.wikipedia.org/wiki/Pseudorandom_number_generator) algorithms:
- LCG
- xoshiro256++
- xoshiro256**
Supported [CSPRNG](https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator) algorithms:
- HMAC-DRBG
@@ -18,7 +20,7 @@ repositories {
}
dependencies {
implementation("com.infendro:prng:1.3.0")
implementation("com.infendro:prng:1.3.1")
}
```
@@ -27,7 +29,7 @@ dependencies {
```kotlin
fun main() {
// create PRNG instance
val rng = CSPRNG.HMAC(`SHA-256`)
val rng = CSPRNG.HMAC(`SHA-256`())
// seed PRNG to receive deterministic numbers
rng.seed(/* seed */)

View File

@@ -5,7 +5,7 @@ import com.infendro.plugin.token
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
group = "com.infendro"
version = "1.3.0"
version = "1.3.1"
plugins {
alias(libs.plugins.infendro)
@@ -31,9 +31,9 @@ kotlin {
sourceSets {
commonMain.dependencies {
implementation(libs.bytes)
implementation(libs.hash)
implementation(libs.mac)
implementation(libs.bytes)
}
}
}

View File

@@ -1,15 +1,15 @@
[versions]
infendro = "1.1.0"
kotlin = "2.3.0"
mac = "1.3.0"
hash = "1.5.1"
bytes = "1.3.3"
bytes = "1.4.2"
hash = "1.7.0"
mac = "1.5.0"
[plugins]
infendro = { id = "com.infendro.plugin", version.ref = "infendro" }
multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
[libraries]
mac = { module = "com.infendro:mac", version.ref = "mac" }
hash = { module = "com.infendro:hash", version.ref = "hash" }
bytes = { module = "com.infendro:bytes", version.ref = "bytes" }
hash = { module = "com.infendro:hash", version.ref = "hash" }
mac = { module = "com.infendro:mac", version.ref = "mac" }

View File

@@ -6,7 +6,7 @@ import com.infendro.mac.HMAC
import com.infendro.random.CSPRNG
import kotlin.properties.Delegates.notNull
class `HMAC-DRBG` internal constructor(
class `HMAC-DRBG`(
private val function: HashFunction,
) : CSPRNG() {
private val hmac = HMAC(function)
@@ -14,6 +14,8 @@ class `HMAC-DRBG` internal constructor(
private var k: ByteArray by notNull()
private var v: ByteArray by notNull()
private val buffer = ByteArray(function.bytes + 1)
override fun seed(seed: ByteArray) {
k = ByteArray(function.bytes) { 0x00 }
v = ByteArray(function.bytes) { 0x01 }
@@ -21,17 +23,28 @@ class `HMAC-DRBG` internal constructor(
}
override fun reseed(entropy: ByteArray) {
k = hmac.hash(k, v + byteArrayOf(0x00) + entropy)
v = hmac.hash(k, v)
k = hmac.hash(k, v + byteArrayOf(0x01) + entropy)
v = hmac.hash(k, v)
val value = ByteArray(v.size + 1 + entropy.size)
v.copyInto(value)
value[v.size] = 0x00
entropy.copyInto(value, v.size + 1)
hmac.hashInto(k, value, k)
hmac.hashInto(k, v, v)
value[v.size] = 0x01
hmac.hashInto(k, value, k)
hmac.hashInto(k, v, v)
}
override fun generate(): Int {
v = hmac.hash(k, v)
hmac.hashInto(k, v, v)
val result = v.toInt()
k = hmac.hash(k, v + byteArrayOf(0x00))
v = hmac.hash(k, v)
v.copyInto(buffer)
buffer[v.size] = 0x00
hmac.hashInto(k, buffer, k)
hmac.hashInto(k, v, v)
return result
}
}

View File

@@ -5,7 +5,9 @@ import com.infendro.hash.sha2.`SHA-256`
import com.infendro.random.PRNG
import kotlin.properties.Delegates.notNull
class LCG internal constructor() : PRNG() {
class LCG : PRNG() {
private val function = `SHA-256`()
private val a: Long = 25214903917L
private val c: Long = 11L
private val mask: Long = (1L shl 48) - 1
@@ -13,7 +15,7 @@ class LCG internal constructor() : PRNG() {
private var x: Long by notNull()
override fun seed(seed: ByteArray) {
x = `SHA-256`.hash(seed).toLong() and mask
x = function.hash(seed).toLong() and mask
}
override fun generate(): Int {

View File

@@ -0,0 +1,30 @@
package com.infendro.random.prng
import com.infendro.bytes.bytearray.toLongArray
import com.infendro.hash.sha2.`SHA-256`
import com.infendro.random.PRNG
import kotlin.properties.Delegates.notNull
class Xoshiro256pp : PRNG() {
private val function = `SHA-256`()
private var s: LongArray by notNull()
override fun seed(seed: ByteArray) {
s = function.hash(seed).toLongArray()
}
override fun generate(): Int {
val result = (s[0] + s[3]).rotateLeft(23) + s[0]
val t = s[1] shl 17
s[2] = s[2] xor s[0]
s[3] = s[3] xor s[1]
s[1] = s[1] xor s[2]
s[0] = s[0] xor s[3]
s[2] = s[2] xor t
s[3] = s[3].rotateLeft(45)
return (result ushr 32).toInt()
}
}

View File

@@ -0,0 +1,30 @@
package com.infendro.random.prng
import com.infendro.bytes.bytearray.toLongArray
import com.infendro.hash.sha2.`SHA-256`
import com.infendro.random.PRNG
import kotlin.properties.Delegates.notNull
class Xoshiro256ss : PRNG() {
private val function = `SHA-256`()
private var s: LongArray by notNull()
override fun seed(seed: ByteArray) {
s = function.hash(seed).toLongArray()
}
override fun generate(): Int {
val result = (s[1] * 5).rotateLeft(7) * 9
val t = s[1] shl 17
s[2] = s[2] xor s[0]
s[3] = s[3] xor s[1]
s[1] = s[1] xor s[2]
s[0] = s[0] xor s[3]
s[2] = s[2] xor t
s[3] = s[3].rotateLeft(45)
return (result ushr 32).toInt()
}
}