added numeric nonce calculator
This commit is contained in:
parent
77911867a1
commit
9027bb0e88
@ -23,7 +23,7 @@ kotlin {
|
||||
// linuxArm64()
|
||||
|
||||
// macosX64()
|
||||
// macosArm64()
|
||||
// macosArm64() ?: break
|
||||
// iosX64()
|
||||
// iosArm64()
|
||||
// iosSimulatorArm64()
|
||||
|
@ -105,7 +105,7 @@ object Asymmetric {
|
||||
return KeyPair(SecretKey(p.secretKey, pk), pk)
|
||||
}
|
||||
|
||||
private fun randomNonce(): UByteArray = randomBytes(crypto_box_NONCEBYTES)
|
||||
private fun randomNonce(): UByteArray = randomUBytes(crypto_box_NONCEBYTES)
|
||||
|
||||
/**
|
||||
* The public key used as the recipient for [Message] (see [SecretKey.encrypt], etc.). It also
|
||||
|
@ -4,4 +4,4 @@ interface NonceBased {
|
||||
val nonceBytesLength: Int
|
||||
}
|
||||
|
||||
fun NonceBased.randomNonce(): UByteArray = randomBytes(nonceBytesLength)
|
||||
fun NonceBased.randomNonce(): UByteArray = randomUBytes(nonceBytesLength)
|
||||
|
60
src/commonMain/kotlin/net/sergeych/crypto2/NumericNonce.kt
Normal file
60
src/commonMain/kotlin/net/sergeych/crypto2/NumericNonce.kt
Normal file
@ -0,0 +1,60 @@
|
||||
package net.sergeych.crypto2
|
||||
|
||||
/**
|
||||
* Numeric nonce is most often used to compress nonce data up to several bytes long counter,
|
||||
* or even recalculate counter on both sides synchronously. This class combines (XORs) a number
|
||||
* with a byte-array nonce specified on creation. This "extends" number to the desired size.
|
||||
*/
|
||||
class NumericNonce(val base: UByteArray) {
|
||||
|
||||
/**
|
||||
* Combines [base] by XORing its byte representation with a [base]
|
||||
* @throws NonceOutOfBoundsException if the argument is too big to be kept in the nonce. For example,
|
||||
* nonce of 4 bytes [base] can't be combined with a number > 2^32, etc.
|
||||
*/
|
||||
fun withULong(numericNonce: ULong): UByteArray {
|
||||
val result = base.copyOf()
|
||||
var x = numericNonce
|
||||
var i = 0
|
||||
while (x > 0u) {
|
||||
result[i] = result[i] xor (x and 0xFFu).toUByte()
|
||||
x = x shr 8
|
||||
if( i++ >= base.size)
|
||||
throw NonceOutOfBoundsException("this nonce has only ${base.size} bytes length and can hold nonce $numericNonce")
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines [base] by XORing its byte representation with a [base], see [withULong]
|
||||
*/
|
||||
@Suppress("unused")
|
||||
fun withLong(intNonce: Long): UByteArray {
|
||||
require( intNonce >= 0 )
|
||||
return withULong(intNonce.toULong())
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines [base] by XORing its byte representation with a [base], see [withULong]
|
||||
*/
|
||||
fun withInt(intNonce: Int): UByteArray {
|
||||
require( intNonce >= 0 )
|
||||
return withULong(intNonce.toULong())
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Combines [base] by XORing its byte representation with a [base], see [withULong]
|
||||
*/
|
||||
@Suppress("unused")
|
||||
fun withUInt(intNonce: UInt): UByteArray {
|
||||
return withULong(intNonce.toULong())
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Create a random numeric nonce with a specified size.
|
||||
*/
|
||||
fun random(size: Int) = NumericNonce(randomUBytes(size))
|
||||
}
|
||||
}
|
@ -136,7 +136,7 @@ class Seal(
|
||||
expiresAt: Instant? = null,
|
||||
nonDeterministic: Boolean = false
|
||||
): Seal {
|
||||
val nonce = if( nonDeterministic ) randomBytes(32) else null
|
||||
val nonce = if( nonDeterministic ) randomUBytes(32) else null
|
||||
val data = BipackEncoder.encode(SealedData(message, nonce, createdAt, expiresAt)).toUByteArray()
|
||||
return Seal(key.publicKey, key.sign(data), nonce, createdAt, expiresAt)
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ class SymmetricKey(
|
||||
|
||||
val fill = randomFill?.let {
|
||||
require(it.start >= 0)
|
||||
randomBytes(randomInt(it))
|
||||
randomUBytes(randomInt(it))
|
||||
}
|
||||
val filled = BipackEncoder.encode(WithFill(plainData, fill))
|
||||
return SecretBox.easy(filled.toUByteArray(), nonce, keyBytes)
|
||||
|
11
src/commonMain/kotlin/net/sergeych/crypto2/exceptions.kt
Normal file
11
src/commonMain/kotlin/net/sergeych/crypto2/exceptions.kt
Normal file
@ -0,0 +1,11 @@
|
||||
package net.sergeych.crypto2
|
||||
|
||||
/**
|
||||
* Any exception initiated by crypto2 library has this base class
|
||||
*/
|
||||
open class Crypto2Exception(text: String,cause: Throwable?=null): RuntimeException(text, cause)
|
||||
|
||||
class DecryptionFailedException(text: String="can't decrypt: wrong key or tampered message",
|
||||
cause: Throwable?=null): Crypto2Exception(text,cause)
|
||||
|
||||
class NonceOutOfBoundsException(text: String): Crypto2Exception(text)
|
@ -8,10 +8,6 @@ import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.channels.ReceiveChannel
|
||||
import net.sergeych.bintools.DataSource
|
||||
|
||||
class DecryptionFailedException(text: String="can't decrypt: wrong key or tampered message",
|
||||
cause: Throwable?=null) : RuntimeException(text, cause) {
|
||||
}
|
||||
|
||||
|
||||
suspend fun readVarUnsigned(input: ReceiveChannel<UByte>): UInt {
|
||||
var result = 0u
|
||||
@ -38,9 +34,9 @@ fun encodeVarUnsigned(value: UInt): UByteArray {
|
||||
}
|
||||
|
||||
|
||||
fun randomBytes(n: Int): UByteArray = if (n > 0) LibsodiumRandom.buf(n) else ubyteArrayOf()
|
||||
fun randomUBytes(n: Int): UByteArray = if (n > 0) LibsodiumRandom.buf(n) else ubyteArrayOf()
|
||||
|
||||
fun randomBytes(n: UInt): UByteArray = if (n > 0u) LibsodiumRandom.buf(n.toInt()) else ubyteArrayOf()
|
||||
fun randomUBytes(n: UInt): UByteArray = if (n > 0u) LibsodiumRandom.buf(n.toInt()) else ubyteArrayOf()
|
||||
|
||||
/**
|
||||
* Uniform random in `0 ..< max` range
|
||||
|
@ -1,11 +1,6 @@
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import net.sergeych.crypto2.createContrail
|
||||
import net.sergeych.crypto2.initCrypto
|
||||
import net.sergeych.crypto2.isValidContrail
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
import net.sergeych.crypto2.*
|
||||
import kotlin.test.*
|
||||
|
||||
class ToolsTest {
|
||||
@Test
|
||||
@ -17,4 +12,18 @@ class ToolsTest {
|
||||
c[2] = 11u
|
||||
assertFalse { isValidContrail(c) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun numericNonceTest() = runTest{
|
||||
initCrypto()
|
||||
val nn = NumericNonce.random(32)
|
||||
val counter = 1031
|
||||
val x1 = nn.withInt(0)
|
||||
val x2 = nn.withInt(counter)
|
||||
println(x1.toDump())
|
||||
println(x2.toDump())
|
||||
val t = (x1[0] xor x2[0]).toInt() + ((x1[1] xor x2[1]).toInt() shl 8)
|
||||
assertEquals(counter, t)
|
||||
assertContentEquals(x1.drop(2), x2.drop(2))
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user