forked from sergeych/crypto2
added numeric nonce calculator
This commit is contained in:
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
|
||||
|
||||
Reference in new issue
Block a user