added numeric nonce calculator

This commit is contained in:
sergeych committed 2024-06-14 11:47:12 +07:00
1 parent 77911867a1
commit 9027bb0e88
9 files changed
+94 -18

No files matched your search

@@ -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)
@@ -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)
@@ -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