forked from sergeych/crypto2
refactored keys, unversal keys and ring
This commit is contained in:
parent
7eeb780bdb
commit
ede55650f4
@ -109,7 +109,7 @@ object Asymmetric {
|
|||||||
|
|
||||||
private fun randomNonce(): UByteArray = randomUBytes(crypto_box_NONCEBYTES)
|
private fun randomNonce(): UByteArray = randomUBytes(crypto_box_NONCEBYTES)
|
||||||
|
|
||||||
fun randomSecretKey(): SecretKey = generateKeys().secretKey
|
fun new(): SecretKey = generateKeys().secretKey
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val nonceBytesLength = crypto_box_NONCEBYTES
|
val nonceBytesLength = crypto_box_NONCEBYTES
|
||||||
@ -121,22 +121,9 @@ object Asymmetric {
|
|||||||
* Anonymous encryption is very slow in comparison.
|
* Anonymous encryption is very slow in comparison.
|
||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
class PublicKey(val keyBytes: UByteArray) {
|
class PublicKey(override val keyBytes: UByteArray) : BinaryKeyBase() {
|
||||||
|
|
||||||
val tag: KeyId by lazy {
|
override val magick: KeysMagickNumber = KeysMagickNumber.defaultAssymmetric
|
||||||
KeyId(KeysMagickNumbers.defaultAssymmetric, blake2b(keyBytes))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (this === other) return true
|
|
||||||
if (other !is PublicKey) return false
|
|
||||||
|
|
||||||
return keyBytes contentEquals other.keyBytes
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
return keyBytes.contentHashCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an anonymous message that could be decrypted only with the [SecretKey] that corresponds this.
|
* Create an anonymous message that could be decrypted only with the [SecretKey] that corresponds this.
|
||||||
@ -171,7 +158,7 @@ object Asymmetric {
|
|||||||
fun encryptMessage(
|
fun encryptMessage(
|
||||||
plainData: UByteArray,
|
plainData: UByteArray,
|
||||||
nonce: UByteArray = randomNonce(),
|
nonce: UByteArray = randomNonce(),
|
||||||
senderKey: SecretKey = randomSecretKey(),
|
senderKey: SecretKey = new(),
|
||||||
randomFill: IntRange? = null,
|
randomFill: IntRange? = null,
|
||||||
) = createMessage(senderKey, this, WithFill.encode(plainData, randomFill), nonce)
|
) = createMessage(senderKey, this, WithFill.encode(plainData, randomFill), nonce)
|
||||||
|
|
||||||
@ -192,10 +179,10 @@ object Asymmetric {
|
|||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
class SecretKey(
|
class SecretKey(
|
||||||
val keyBytes: UByteArray,
|
override val keyBytes: UByteArray,
|
||||||
@Transient
|
@Transient
|
||||||
val _cachedPublicKey: PublicKey? = null,
|
val _cachedPublicKey: PublicKey? = null,
|
||||||
) : DecryptingKey {
|
) : DecryptingKey, BinaryKeyBase() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypt with authentication checks the message which must have [Message.senderPublicKey] set.
|
* Decrypt with authentication checks the message which must have [Message.senderPublicKey] set.
|
||||||
@ -226,17 +213,6 @@ object Asymmetric {
|
|||||||
.also { cachedPublicKey = it }
|
.also { cachedPublicKey = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (this === other) return true
|
|
||||||
if (other !is SecretKey) return false
|
|
||||||
|
|
||||||
return keyBytes contentEquals other.keyBytes
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
return keyBytes.contentHashCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Nonce-based decryption is impossible, it is already included in message
|
* Nonce-based decryption is impossible, it is already included in message
|
||||||
*/
|
*/
|
||||||
@ -250,7 +226,8 @@ object Asymmetric {
|
|||||||
return message.decrypt(this)
|
return message.decrypt(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val id: KeyId by lazy { publicKey.tag }
|
override val magick: KeysMagickNumber = KeysMagickNumber.defaultAssymmetric
|
||||||
|
override val id: KeyId by lazy { publicKey.id }
|
||||||
|
|
||||||
override val nonceBytesLength: Int
|
override val nonceBytesLength: Int
|
||||||
get() = 0
|
get() = 0
|
||||||
|
47
src/commonMain/kotlin/net/sergeych/crypto2/BinaryKeyBase.kt
Normal file
47
src/commonMain/kotlin/net/sergeych/crypto2/BinaryKeyBase.kt
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package net.sergeych.crypto2
|
||||||
|
|
||||||
|
import kotlinx.datetime.Instant
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
interface VerifyingKey {
|
||||||
|
val id: KeyId
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the signature and return true if it is correct.
|
||||||
|
*/
|
||||||
|
fun verify(signature: UByteArray, message: UByteArray): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SigningKey {
|
||||||
|
val verifyingKey: SigningPublicKey
|
||||||
|
fun sign(message: UByteArray): UByteArray
|
||||||
|
fun seal(message: UByteArray, expiresAt: Instant? = null): Seal
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
abstract class BinaryKeyBase() {
|
||||||
|
|
||||||
|
abstract val keyBytes: UByteArray
|
||||||
|
abstract val magick: KeysMagickNumber
|
||||||
|
|
||||||
|
open val id by lazy { KeyId(magick, keyBytes) }
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
return other is BinaryKeyBase && other.keyBytes contentEquals keyBytes
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return keyBytes.contentHashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = keyBytes.encodeToBase64Url()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class IllegalSignatureException(text: String = "signed data is tampered or signature is corrupted") :
|
||||||
|
IllegalStateException(text)
|
||||||
|
|
||||||
|
class ExpiredSignatureException(text: String) : IllegalSignatureException(text)
|
@ -232,10 +232,10 @@ sealed class Container {
|
|||||||
|
|
||||||
constructor(sender: Asymmetric.SecretKey?, recipient: Asymmetric.PublicKey, encodeMainKey: UByteArray) :
|
constructor(sender: Asymmetric.SecretKey?, recipient: Asymmetric.PublicKey, encodeMainKey: UByteArray) :
|
||||||
this(
|
this(
|
||||||
recipient.tag,
|
recipient.id,
|
||||||
recipient.encryptMessage(
|
recipient.encryptMessage(
|
||||||
encodeMainKey,
|
encodeMainKey,
|
||||||
senderKey = sender ?: Asymmetric.randomSecretKey(),
|
senderKey = sender ?: Asymmetric.new(),
|
||||||
).encoded
|
).encoded
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -375,7 +375,7 @@ sealed class Container {
|
|||||||
mainKey = p.mainKey ?: throw IllegalStateException("parent container must be decrypted")
|
mainKey = p.mainKey ?: throw IllegalStateException("parent container must be decrypted")
|
||||||
} else {
|
} else {
|
||||||
eks = mutableListOf<Multi.EncryptedKey>()
|
eks = mutableListOf<Multi.EncryptedKey>()
|
||||||
mainKey = SymmetricKey.random()
|
mainKey = SymmetricKey.new()
|
||||||
}
|
}
|
||||||
val encodedMainKey = BipackEncoder.encode(mainKey).toUByteArray()
|
val encodedMainKey = BipackEncoder.encode(mainKey).toUByteArray()
|
||||||
createMulti(eks, encodedMainKey, mainKey)
|
createMulti(eks, encodedMainKey, mainKey)
|
||||||
@ -389,9 +389,9 @@ sealed class Container {
|
|||||||
val pair = keyPairs.first()
|
val pair = keyPairs.first()
|
||||||
val (sk, pk) = pair
|
val (sk, pk) = pair
|
||||||
Single(
|
Single(
|
||||||
pk.tag, pk.encryptMessage(
|
pk.id, pk.encryptMessage(
|
||||||
plainData,
|
plainData,
|
||||||
senderKey = sk ?: Asymmetric.randomSecretKey(),
|
senderKey = sk ?: Asymmetric.new(),
|
||||||
randomFill = fillRange
|
randomFill = fillRange
|
||||||
).encoded,
|
).encoded,
|
||||||
plainData,
|
plainData,
|
||||||
|
@ -23,6 +23,6 @@ data class KeyId(val id: BinaryId, val kdp: KeyDerivationParams?=null ) {
|
|||||||
|
|
||||||
override fun toString() = id.toString()
|
override fun toString() = id.toString()
|
||||||
|
|
||||||
constructor(magickNumber: KeysMagickNumbers, data: UByteArray,kdp: KeyDerivationParams?=null)
|
constructor(magickNumber: KeysMagickNumber, data: UByteArray, kdp: KeyDerivationParams?=null)
|
||||||
: this(BinaryId.createFromUBytes(magickNumber.number, data), kdp)
|
: this(BinaryId.createFromUBytes(magickNumber.number, data), kdp)
|
||||||
}
|
}
|
@ -1,10 +1,11 @@
|
|||||||
package net.sergeych.crypto2
|
package net.sergeych.crypto2
|
||||||
|
|
||||||
enum class KeysMagickNumbers(val number: Int) {
|
enum class KeysMagickNumber(val number: Int) {
|
||||||
defaultAssymmetric(0),
|
defaultAssymmetric(0),
|
||||||
defaultSymmetric(1),
|
defaultSymmetric(1),
|
||||||
defaultSession(2),
|
defaultSession(2),
|
||||||
defaultSigning(3),
|
defaultSigning(3),
|
||||||
|
defaultVerifying(4),
|
||||||
;
|
;
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -12,6 +13,6 @@ enum class KeysMagickNumbers(val number: Int) {
|
|||||||
val forNumber = entries.map { it.number to it }.toMap()
|
val forNumber = entries.map { it.number to it }.toMap()
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
fun findFor(binaryId: BinaryId): KeysMagickNumbers? = forNumber[binaryId.magick]
|
fun findFor(binaryId: BinaryId): KeysMagickNumber? = forNumber[binaryId.magick]
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -23,7 +23,7 @@ import net.sergeych.utools.now
|
|||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
class Seal(
|
class Seal(
|
||||||
val publicKey: Signing.PublicKey,
|
val publicKey: SigningPublicKey,
|
||||||
val signature: UByteArray,
|
val signature: UByteArray,
|
||||||
val nonce: UByteArray?,
|
val nonce: UByteArray?,
|
||||||
val createdAt: Instant,
|
val createdAt: Instant,
|
||||||
@ -95,7 +95,7 @@ class Seal(
|
|||||||
* Seal [message] with a [key].
|
* Seal [message] with a [key].
|
||||||
*
|
*
|
||||||
* Seals are kotlinx-serializable and can be used
|
* Seals are kotlinx-serializable and can be used
|
||||||
* to check the authenticity of the arbitrary [message] using a public key, [Signing.PublicKey]
|
* to check the authenticity of the arbitrary [message] using a public key, [SigningPublicKey]
|
||||||
* instance, using public-key signing algorithms.
|
* instance, using public-key signing algorithms.
|
||||||
*
|
*
|
||||||
* Unlike a regular binary signature, Seal contains the signer's [publicKey], and also
|
* Unlike a regular binary signature, Seal contains the signer's [publicKey], and also
|
||||||
@ -130,7 +130,7 @@ class Seal(
|
|||||||
* rare case so default os false.
|
* rare case so default os false.
|
||||||
*/
|
*/
|
||||||
fun create(
|
fun create(
|
||||||
key: Signing.SecretKey,
|
key: SigningSecretKey,
|
||||||
message: UByteArray,
|
message: UByteArray,
|
||||||
createdAt: Instant = now(),
|
createdAt: Instant = now(),
|
||||||
expiresAt: Instant? = null,
|
expiresAt: Instant? = null,
|
||||||
@ -138,7 +138,7 @@ class Seal(
|
|||||||
): Seal {
|
): Seal {
|
||||||
val nonce = if( nonDeterministic ) randomUBytes(32) else null
|
val nonce = if( nonDeterministic ) randomUBytes(32) else null
|
||||||
val data = BipackEncoder.encode(SealedData(message, nonce, createdAt, expiresAt)).toUByteArray()
|
val data = BipackEncoder.encode(SealedData(message, nonce, createdAt, expiresAt)).toUByteArray()
|
||||||
return Seal(key.publicKey, key.sign(data), nonce, createdAt, expiresAt)
|
return Seal(key.verifyingKey, key.sign(data), nonce, createdAt, expiresAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,7 +30,7 @@ class SealedBox(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
constructor(message: UByteArray, vararg keys: Signing.SecretKey) :
|
constructor(message: UByteArray, vararg keys: SigningSecretKey) :
|
||||||
this(message, keys.map { it.seal(message) } )
|
this(message, keys.map { it.seal(message) } )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,23 +38,23 @@ class SealedBox(
|
|||||||
* key, or return unchanged (same) object if it is already signed by this key; you
|
* key, or return unchanged (same) object if it is already signed by this key; you
|
||||||
* _can't assume it always returns a copied object!_
|
* _can't assume it always returns a copied object!_
|
||||||
*/
|
*/
|
||||||
operator fun plus(key: Signing.SecretKey): SealedBox =
|
operator fun plus(key: SigningSecretKey): SealedBox =
|
||||||
if (key.publicKey in this) this
|
if (key.verifyingKey in this) this
|
||||||
else SealedBox(message, seals + key.seal(message),false)
|
else SealedBox(message, seals + key.seal(message),false)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add expiring seal, otherwise use [plus]. Overrides exising seal for [key]
|
* Add expiring seal, otherwise use [plus]. Overrides exising seal for [key]
|
||||||
* if present:
|
* if present:
|
||||||
*/
|
*/
|
||||||
fun addSeal(key: Signing.SecretKey, expresAt: Instant): SealedBox {
|
fun addSeal(key: SigningSecretKey, expresAt: Instant): SealedBox {
|
||||||
val filtered = seals.filter { it.publicKey != key.publicKey }
|
val filtered = seals.filter { it.publicKey != key.verifyingKey }
|
||||||
return SealedBox(message, filtered + key.seal(message, expresAt), false)
|
return SealedBox(message, filtered + key.seal(message, expresAt), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that it is signed with a specified key.
|
* Check that it is signed with a specified key.
|
||||||
*/
|
*/
|
||||||
operator fun contains(publicKey: Signing.PublicKey): Boolean {
|
operator fun contains(publicKey: SigningPublicKey): Boolean {
|
||||||
return seals.any { it.publicKey == publicKey }
|
return seals.any { it.publicKey == publicKey }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ class SealedBox(
|
|||||||
* @param keys a list of keys to sign with, should be at least one key.
|
* @param keys a list of keys to sign with, should be at least one key.
|
||||||
* @throws IllegalArgumentException if keys are not specified.
|
* @throws IllegalArgumentException if keys are not specified.
|
||||||
*/
|
*/
|
||||||
fun create(data: UByteArray, vararg keys: Signing.SecretKey): SealedBox {
|
fun create(data: UByteArray, vararg keys: SigningSecretKey): SealedBox {
|
||||||
return SealedBox(data, keys.map { it.seal(data) }, false)
|
return SealedBox(data, keys.map { it.seal(data) }, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,107 +0,0 @@
|
|||||||
package net.sergeych.crypto2
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.signature.InvalidSignatureException
|
|
||||||
import com.ionspin.kotlin.crypto.signature.Signature
|
|
||||||
import kotlinx.datetime.Instant
|
|
||||||
import kotlinx.serialization.SerialName
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
import net.sergeych.crypto2.Signing.Companion.pair
|
|
||||||
import net.sergeych.utools.now
|
|
||||||
|
|
||||||
interface VerifyingKey {
|
|
||||||
val id: KeyId
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify the signature and return true if it is correct.
|
|
||||||
*/
|
|
||||||
fun verify(signature: UByteArray, message: UByteArray): Boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SigningKey {
|
|
||||||
val publicKey: Signing.PublicKey
|
|
||||||
fun sign(message: UByteArray): UByteArray
|
|
||||||
fun seal(message: UByteArray, expiresAt: Instant? = null): Seal
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Keys in general: public, secret and later symmetric too.
|
|
||||||
* Keys could be compared to each other for equality and used
|
|
||||||
* as a Map keys (not sure about js).
|
|
||||||
*
|
|
||||||
* Use [pair] to create new keys.
|
|
||||||
*/
|
|
||||||
@Serializable
|
|
||||||
sealed class Signing {
|
|
||||||
abstract val id: KeyId
|
|
||||||
|
|
||||||
abstract val packed: UByteArray
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
return other is Signing && other.packed contentEquals packed
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
return packed.contentHashCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String = packed.encodeToBase64Url()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Public key to verify signatures only
|
|
||||||
*/
|
|
||||||
@Serializable
|
|
||||||
@SerialName("p")
|
|
||||||
class PublicKey(override val packed: UByteArray) : Signing(), VerifyingKey {
|
|
||||||
/**
|
|
||||||
* Verify the signature and return true if it is correct.
|
|
||||||
*/
|
|
||||||
override fun verify(signature: UByteArray, message: UByteArray): Boolean = try {
|
|
||||||
Signature.verifyDetached(signature, message, packed)
|
|
||||||
true
|
|
||||||
} catch (_: InvalidSignatureException) {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String = "Pub:${super.toString()}"
|
|
||||||
|
|
||||||
override val id: KeyId by lazy {
|
|
||||||
KeyId(KeysMagickNumbers.defaultSigning, packed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Secret key to sign only
|
|
||||||
*/
|
|
||||||
@Serializable
|
|
||||||
@SerialName("s")
|
|
||||||
class SecretKey(override val packed: UByteArray) : Signing(), SigningKey {
|
|
||||||
|
|
||||||
override val publicKey: PublicKey by lazy {
|
|
||||||
PublicKey(Signature.ed25519SkToPk(packed))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun sign(message: UByteArray): UByteArray = Signature.detached(message, packed)
|
|
||||||
|
|
||||||
override fun seal(message: UByteArray, expiresAt: Instant?): Seal =
|
|
||||||
Seal.create(this, message, now(), expiresAt)
|
|
||||||
|
|
||||||
override fun toString(): String = "Sct:${super.toString()}"
|
|
||||||
|
|
||||||
override val id: KeyId
|
|
||||||
get() = publicKey.id
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
data class Pair(val secretKey: SecretKey, val publicKey: PublicKey)
|
|
||||||
|
|
||||||
fun pair(): Pair {
|
|
||||||
val p = Signature.keypair()
|
|
||||||
return Pair(SecretKey(p.secretKey), PublicKey(p.publicKey))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
open class IllegalSignatureException(text: String="signed data is tampered or signature is corrupted")
|
|
||||||
: IllegalStateException(text)
|
|
||||||
|
|
||||||
class ExpiredSignatureException(text: String): IllegalSignatureException(text)
|
|
@ -0,0 +1,27 @@
|
|||||||
|
package net.sergeych.crypto2
|
||||||
|
|
||||||
|
import com.ionspin.kotlin.crypto.signature.InvalidSignatureException
|
||||||
|
import com.ionspin.kotlin.crypto.signature.Signature
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.Transient
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public key to verify signatures only
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
class SigningPublicKey(override val keyBytes: UByteArray) : BinaryKeyBase(), VerifyingKey {
|
||||||
|
/**
|
||||||
|
* Verify the signature and return true if it is correct.
|
||||||
|
*/
|
||||||
|
override fun verify(signature: UByteArray, message: UByteArray): Boolean = try {
|
||||||
|
Signature.verifyDetached(signature, message, keyBytes)
|
||||||
|
true
|
||||||
|
} catch (_: InvalidSignatureException) {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = "Pub:${super.toString()}"
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
override val magick: KeysMagickNumber = KeysMagickNumber.defaultVerifying
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package net.sergeych.crypto2
|
||||||
|
|
||||||
|
import com.ionspin.kotlin.crypto.signature.Signature
|
||||||
|
import kotlinx.datetime.Instant
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.Transient
|
||||||
|
import net.sergeych.utools.now
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Secret key to sign only
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
class SigningSecretKey(
|
||||||
|
override val keyBytes: UByteArray,
|
||||||
|
@Transient
|
||||||
|
private var cachedPublicKey: SigningPublicKey?=null
|
||||||
|
) : BinaryKeyBase(), SigningKey {
|
||||||
|
|
||||||
|
override val verifyingKey: SigningPublicKey by lazy {
|
||||||
|
cachedPublicKey ?:
|
||||||
|
SigningPublicKey(Signature.ed25519SkToPk(keyBytes)).also { cachedPublicKey = it }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun sign(message: UByteArray): UByteArray = Signature.detached(message, keyBytes)
|
||||||
|
|
||||||
|
override fun seal(message: UByteArray, expiresAt: Instant?): Seal =
|
||||||
|
Seal.create(this, message, now(), expiresAt)
|
||||||
|
|
||||||
|
override fun toString(): String = "Sct:${super.toString()}"
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
override val magick = KeysMagickNumber.defaultSigning
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
data class SigningKeyPair(val secretKey: SigningSecretKey, val publicKey: SigningPublicKey)
|
||||||
|
|
||||||
|
fun generatePair(): SigningKeyPair {
|
||||||
|
val p = Signature.keypair()
|
||||||
|
val publicKey = SigningPublicKey(p.publicKey)
|
||||||
|
return SigningKeyPair(SigningSecretKey(p.secretKey, publicKey), publicKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun new(): SigningSecretKey = generatePair().secretKey
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -37,7 +37,7 @@ class SymmetricKey(
|
|||||||
|
|
||||||
override val nonceBytesLength: Int = nonceByteLength
|
override val nonceBytesLength: Int = nonceByteLength
|
||||||
|
|
||||||
override val id by lazy { KeyId(KeysMagickNumbers.defaultSymmetric,blake2b3l(keyBytes)) }
|
override val id by lazy { KeyId(KeysMagickNumber.defaultSymmetric,blake2b3l(keyBytes)) }
|
||||||
|
|
||||||
override fun decryptWithNonce(cipherData: UByteArray, nonce: UByteArray): UByteArray =
|
override fun decryptWithNonce(cipherData: UByteArray, nonce: UByteArray): UByteArray =
|
||||||
protectDecryption {
|
protectDecryption {
|
||||||
@ -60,7 +60,7 @@ class SymmetricKey(
|
|||||||
/**
|
/**
|
||||||
* Create a secure random symmetric key.
|
* Create a secure random symmetric key.
|
||||||
*/
|
*/
|
||||||
fun random() = SymmetricKey(SecretBox.keygen())
|
fun new() = SymmetricKey(SecretBox.keygen())
|
||||||
|
|
||||||
val nonceByteLength = crypto_secretbox_NONCEBYTES
|
val nonceByteLength = crypto_secretbox_NONCEBYTES
|
||||||
}
|
}
|
||||||
|
@ -7,14 +7,6 @@ import kotlinx.serialization.Transient
|
|||||||
@Serializable
|
@Serializable
|
||||||
sealed class UniversalKey {
|
sealed class UniversalKey {
|
||||||
abstract val id: KeyId
|
abstract val id: KeyId
|
||||||
@Transient
|
|
||||||
open val canEncrypt = false
|
|
||||||
@Transient
|
|
||||||
open val canDecrypt = false
|
|
||||||
@Transient
|
|
||||||
open val canSign = false
|
|
||||||
@Transient
|
|
||||||
open val canVerify = false
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("sym")
|
@SerialName("sym")
|
||||||
@ -26,11 +18,6 @@ sealed class UniversalKey {
|
|||||||
override val nonceBytesLength: Int = key.nonceBytesLength
|
override val nonceBytesLength: Int = key.nonceBytesLength
|
||||||
|
|
||||||
override fun toString() = "U.Sym:$id"
|
override fun toString() = "U.Sym:$id"
|
||||||
|
|
||||||
@Transient
|
|
||||||
override val canDecrypt: Boolean = true
|
|
||||||
@Transient
|
|
||||||
override val canEncrypt: Boolean = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -41,37 +28,55 @@ sealed class UniversalKey {
|
|||||||
override val id: KeyId = key.id
|
override val id: KeyId = key.id
|
||||||
@Transient
|
@Transient
|
||||||
override val nonceBytesLength: Int = key.nonceBytesLength
|
override val nonceBytesLength: Int = key.nonceBytesLength
|
||||||
@Transient
|
|
||||||
override val canDecrypt: Boolean = true
|
|
||||||
@Transient
|
|
||||||
override val canEncrypt: Boolean = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("sec")
|
@SerialName("sec")
|
||||||
data class Secret(val key: Asymmetric.SecretKey) : UniversalKey(), DecryptingKey by key {
|
data class Secret(val key: Asymmetric.SecretKey) : UniversalKey(), DecryptingKey by key {
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
val publicKey: Public = Public(key.publicKey)
|
||||||
|
|
||||||
override val id: KeyId by lazy { key.id }
|
override val id: KeyId by lazy { key.id }
|
||||||
override fun toString() = "U.Sec:$id"
|
override fun toString() = "U.Sec:$id"
|
||||||
@Transient
|
}
|
||||||
override val canDecrypt: Boolean = true
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("pub")
|
||||||
|
data class Public(val key: Asymmetric.PublicKey) : UniversalKey(), EncryptingKey {
|
||||||
|
|
||||||
|
override val id: KeyId by lazy { key.id }
|
||||||
|
|
||||||
|
override fun encryptWithNonce(plainData: UByteArray, nonce: UByteArray, randomFill: IntRange?): UByteArray =
|
||||||
|
key.encryptMessage(plainData, nonce, randomFill= randomFill).encoded
|
||||||
|
|
||||||
|
override fun encrypt(plainData: UByteArray, randomFill: IntRange?): UByteArray =
|
||||||
|
key.encryptMessage(plainData, randomFill=randomFill).encoded
|
||||||
|
|
||||||
|
override val nonceBytesLength: Int
|
||||||
|
get() = Asymmetric.nonceBytesLength
|
||||||
|
|
||||||
|
override fun toString() = "U.Sec:$id"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("sig")
|
@SerialName("sig")
|
||||||
data class Signing(val key: net.sergeych.crypto2.Signing.SecretKey) : UniversalKey() {
|
data class Signing(val key: SigningSecretKey) : UniversalKey(), SigningKey by key {
|
||||||
override val id: KeyId by lazy { key.id }
|
override val id: KeyId by lazy { key.id }
|
||||||
override fun toString() = "U.Sig:$id"
|
override fun toString() = "U.Sig:$id"
|
||||||
@Transient
|
|
||||||
override val canDecrypt: Boolean = true
|
/**
|
||||||
|
* [Verifying] key, e.g. [verifyingKey] wrapped in the [UniversalKey] variant.
|
||||||
|
*/
|
||||||
|
val publicKey by lazy { Verifying(verifyingKey) }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("ver")
|
@SerialName("ver")
|
||||||
data class Verifying(val key: net.sergeych.crypto2.Signing.PublicKey) : UniversalKey() {
|
data class Verifying(val key: SigningPublicKey) : UniversalKey(), VerifyingKey by key {
|
||||||
override val id: KeyId by lazy { key.id }
|
override val id: KeyId by lazy { key.id }
|
||||||
override fun toString() = "U.Sig:$id"
|
override fun toString() = "U.Sig:$id"
|
||||||
@Transient
|
|
||||||
override val canDecrypt: Boolean = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -85,6 +90,14 @@ sealed class UniversalKey {
|
|||||||
is SafeKeyExchange.SessionKey -> Session(key)
|
is SafeKeyExchange.SessionKey -> Session(key)
|
||||||
else -> throw UnsupportedOperationException("can't create universal key from ${key::class.simpleName}")
|
else -> throw UnsupportedOperationException("can't create universal key from ${key::class.simpleName}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun newSecretKey(): Secret =
|
||||||
|
Secret(Asymmetric.new())
|
||||||
|
fun newSigningKey(): Signing =
|
||||||
|
Signing(SigningSecretKey.new())
|
||||||
|
@Suppress("unused")
|
||||||
|
fun newSymmetricKey(): Symmetric =
|
||||||
|
Symmetric(SymmetricKey.new())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,27 +4,37 @@ import kotlinx.serialization.Serializable
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class UniversalRing(
|
class UniversalRing(
|
||||||
private val keyWithTags: Map<UniversalKey,Set<String>>
|
val keyWithTags: Map<UniversalKey,Set<String>>
|
||||||
) {
|
) {
|
||||||
val decryptingKeys: Set<DecryptingKey> by lazy {
|
|
||||||
keyWithTags.keys.mapNotNull { it as? DecryptingKey }.toSet()
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(vararg keys: UniversalKey) : this(keys.associateWith { setOf() })
|
constructor(vararg keys: UniversalKey) : this(keys.associateWith { setOf() })
|
||||||
constructor(vararg keys: DecryptingKey) : this(keys.associate { UniversalKey.from(it) to setOf<String>() })
|
constructor(vararg keys: DecryptingKey) : this(keys.associate { UniversalKey.from(it) to setOf<String>() })
|
||||||
constructor(vararg keyTags: Pair<UniversalKey, String>)
|
constructor(vararg keyTags: Pair<UniversalKey, String>)
|
||||||
: this(keyTags.associate { it.first to setOf(it.second) })
|
: this(keyTags.associate { it.first to setOf(it.second) })
|
||||||
|
|
||||||
private val byId by lazy { keyWithTags.keys.associateBy { it.id } }
|
val decryptingKeys: Set<DecryptingKey> by lazy { keys<DecryptingKey>() }
|
||||||
private val byIdWithTags by lazy { keyWithTags.entries.associate { it.key.id to (it.key to it.value) } }
|
|
||||||
|
|
||||||
operator fun get(keyId: KeyId): UniversalKey? = byId[keyId]
|
inline fun <reified T>keys(): Set<T> =
|
||||||
|
keyWithTags.keys.mapNotNull { it as? T }.toSet()
|
||||||
|
|
||||||
|
inline fun <reified T>findKey(id: KeyId): UniversalKey? =
|
||||||
|
keyWithTags.keys.find { it is T && it.id == id }
|
||||||
|
|
||||||
|
fun allByAnyOfTags(vararg tags: String) = sequence {
|
||||||
|
for( e in keyWithTags.entries) {
|
||||||
|
if( tags.any { it in e.value }) yield(e.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T>keyByTag(tag: String) = allByAnyOfTags(tag).first { it is T }
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
inline fun <reified T>keyByAnyTag(vararg tags: String) = allByAnyOfTags(*tags).first { it is T }
|
||||||
|
|
||||||
|
operator fun get(keyId: KeyId): Collection<UniversalKey> = keyWithTags.keys.filter { it.id == keyId }
|
||||||
|
|
||||||
fun getTags(key: UniversalKey): Set<String>? = keyWithTags[key]
|
fun getTags(key: UniversalKey): Set<String>? = keyWithTags[key]
|
||||||
|
|
||||||
fun keyWithTags(keyId: KeyId?): Pair<UniversalKey,Set<String>>? = byIdWithTags[keyId]
|
operator fun contains(element: UniversalKey): Boolean = element in keyWithTags
|
||||||
|
|
||||||
operator fun contains(element: UniversalKey): Boolean = byId.containsKey(element.id)
|
|
||||||
|
|
||||||
operator fun plus(key: UniversalKey): UniversalRing =
|
operator fun plus(key: UniversalKey): UniversalRing =
|
||||||
if( key in this ) this else UniversalRing(keyWithTags + (key to setOf()) )
|
if( key in this ) this else UniversalRing(keyWithTags + (key to setOf()) )
|
||||||
@ -56,9 +66,6 @@ class UniversalRing(
|
|||||||
operator fun minus(key: UniversalKey): UniversalRing =
|
operator fun minus(key: UniversalKey): UniversalRing =
|
||||||
if( key in this ) UniversalRing(keyWithTags.filter { it.key != key }) else this
|
if( key in this ) UniversalRing(keyWithTags.filter { it.key != key }) else this
|
||||||
|
|
||||||
operator fun minus(keyId: KeyId): UniversalRing =
|
|
||||||
if( keyId in byId ) UniversalRing(keyWithTags.filter { it.key.id != keyId }) else this
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (other !is UniversalRing) return false
|
if (other !is UniversalRing) return false
|
||||||
|
@ -9,8 +9,8 @@ class ContainerTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testSingle() = runTest {
|
fun testSingle() = runTest {
|
||||||
initCrypto()
|
initCrypto()
|
||||||
val syk1 = SymmetricKey.random()
|
val syk1 = SymmetricKey.new()
|
||||||
val syk2 = SymmetricKey.random()
|
val syk2 = SymmetricKey.new()
|
||||||
val data = "sergeych, ohm many.".encodeToUByteArray()
|
val data = "sergeych, ohm many.".encodeToUByteArray()
|
||||||
|
|
||||||
val c = Container.createWith(data, syk1)
|
val c = Container.createWith(data, syk1)
|
||||||
@ -87,9 +87,9 @@ class ContainerTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testMultipleSymmetric() = runTest {
|
fun testMultipleSymmetric() = runTest {
|
||||||
initCrypto()
|
initCrypto()
|
||||||
val syk1 = SymmetricKey.random()
|
val syk1 = SymmetricKey.new()
|
||||||
val syk2 = SymmetricKey.random()
|
val syk2 = SymmetricKey.new()
|
||||||
val syk3 = SymmetricKey.random()
|
val syk3 = SymmetricKey.new()
|
||||||
val p1 = Asymmetric.generateKeys()
|
val p1 = Asymmetric.generateKeys()
|
||||||
val p2 = Asymmetric.generateKeys()
|
val p2 = Asymmetric.generateKeys()
|
||||||
val p3 = Asymmetric.generateKeys()
|
val p3 = Asymmetric.generateKeys()
|
||||||
@ -131,9 +131,9 @@ class ContainerTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testSingleGrowSymmetric() = runTest {
|
fun testSingleGrowSymmetric() = runTest {
|
||||||
initCrypto()
|
initCrypto()
|
||||||
val syk1 = SymmetricKey.random()
|
val syk1 = SymmetricKey.new()
|
||||||
val syk2 = SymmetricKey.random()
|
val syk2 = SymmetricKey.new()
|
||||||
val syk3 = SymmetricKey.random()
|
val syk3 = SymmetricKey.new()
|
||||||
val p1 = Asymmetric.generateKeys()
|
val p1 = Asymmetric.generateKeys()
|
||||||
val p3 = Asymmetric.generateKeys()
|
val p3 = Asymmetric.generateKeys()
|
||||||
val p4 = Asymmetric.generateKeys()
|
val p4 = Asymmetric.generateKeys()
|
||||||
@ -193,8 +193,8 @@ class ContainerTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testSingleGrowAsymmetric() = runTest {
|
fun testSingleGrowAsymmetric() = runTest {
|
||||||
initCrypto()
|
initCrypto()
|
||||||
val syk1 = SymmetricKey.random()
|
val syk1 = SymmetricKey.new()
|
||||||
val syk2 = SymmetricKey.random()
|
val syk2 = SymmetricKey.new()
|
||||||
val p1 = Asymmetric.generateKeys()
|
val p1 = Asymmetric.generateKeys()
|
||||||
val p3 = Asymmetric.generateKeys()
|
val p3 = Asymmetric.generateKeys()
|
||||||
val data = "Translating the name 'Sergey Chernov' from Russian to archaic Sanskrit would be 'Ramo Krishna'"
|
val data = "Translating the name 'Sergey Chernov' from Russian to archaic Sanskrit would be 'Ramo Krishna'"
|
||||||
@ -226,9 +226,9 @@ class ContainerTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testMixedOps1() = runTest {
|
fun testMixedOps1() = runTest {
|
||||||
initCrypto()
|
initCrypto()
|
||||||
val syk1 = SymmetricKey.random()
|
val syk1 = SymmetricKey.new()
|
||||||
val syk2 = SymmetricKey.random()
|
val syk2 = SymmetricKey.new()
|
||||||
val syk3 = SymmetricKey.random()
|
val syk3 = SymmetricKey.new()
|
||||||
val p1 = Asymmetric.generateKeys()
|
val p1 = Asymmetric.generateKeys()
|
||||||
val p2 = Asymmetric.generateKeys()
|
val p2 = Asymmetric.generateKeys()
|
||||||
val p3 = Asymmetric.generateKeys()
|
val p3 = Asymmetric.generateKeys()
|
||||||
@ -263,9 +263,9 @@ class ContainerTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testMixedOps2() = runTest {
|
fun testMixedOps2() = runTest {
|
||||||
initCrypto()
|
initCrypto()
|
||||||
val syk1 = SymmetricKey.random()
|
val syk1 = SymmetricKey.new()
|
||||||
val syk2 = SymmetricKey.random()
|
val syk2 = SymmetricKey.new()
|
||||||
val syk3 = SymmetricKey.random()
|
val syk3 = SymmetricKey.new()
|
||||||
val p1 = Asymmetric.generateKeys()
|
val p1 = Asymmetric.generateKeys()
|
||||||
val p2 = Asymmetric.generateKeys()
|
val p2 = Asymmetric.generateKeys()
|
||||||
val p3 = Asymmetric.generateKeys()
|
val p3 = Asymmetric.generateKeys()
|
||||||
|
@ -13,11 +13,11 @@ class KeysTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testSigningCreationAndMap() = runTest {
|
fun testSigningCreationAndMap() = runTest {
|
||||||
initCrypto()
|
initCrypto()
|
||||||
val (stk,pbk) = Signing.pair()
|
val (stk,pbk) = SigningSecretKey.generatePair()
|
||||||
|
|
||||||
val x = mapOf( stk to "STK!", pbk to "PBK!")
|
val x = mapOf( stk to "STK!", pbk to "PBK!")
|
||||||
assertEquals("STK!", x[stk])
|
assertEquals("STK!", x[stk])
|
||||||
val s1 = Signing.SecretKey(stk.packed)
|
val s1 = SigningSecretKey(stk.keyBytes)
|
||||||
assertEquals(stk, s1)
|
assertEquals(stk, s1)
|
||||||
assertEquals("STK!", x[s1])
|
assertEquals("STK!", x[s1])
|
||||||
assertEquals("PBK!", x[pbk])
|
assertEquals("PBK!", x[pbk])
|
||||||
@ -29,8 +29,8 @@ class KeysTest {
|
|||||||
|
|
||||||
data1[0] = 0x01u
|
data1[0] = 0x01u
|
||||||
assertFalse(s.isValid(data1))
|
assertFalse(s.isValid(data1))
|
||||||
val p2 = Signing.pair()
|
val p2 = SigningSecretKey.generatePair()
|
||||||
val p3 = Signing.pair()
|
val p3 = SigningSecretKey.generatePair()
|
||||||
|
|
||||||
val ms = SealedBox.create(data, s1) + p2.secretKey
|
val ms = SealedBox.create(data, s1) + p2.secretKey
|
||||||
|
|
||||||
@ -49,8 +49,8 @@ class KeysTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testNonDeterministicSeals() = runTest {
|
fun testNonDeterministicSeals() = runTest {
|
||||||
initCrypto()
|
initCrypto()
|
||||||
val data = "Welcome to the Miami, bitch!".encodeToUByteArray()
|
val data = "Welcome to the crazy new world!".encodeToUByteArray()
|
||||||
val (sk,_) = Signing.pair()
|
val (sk,_) = SigningSecretKey.generatePair()
|
||||||
val t = now()
|
val t = now()
|
||||||
val s1 = Seal.create(sk, data, createdAt = t)
|
val s1 = Seal.create(sk, data, createdAt = t)
|
||||||
val s2 = Seal.create(sk, data, createdAt = t)
|
val s2 = Seal.create(sk, data, createdAt = t)
|
||||||
@ -72,8 +72,8 @@ class KeysTest {
|
|||||||
@Test
|
@Test
|
||||||
fun secretEncryptTest() = runTest {
|
fun secretEncryptTest() = runTest {
|
||||||
initCrypto()
|
initCrypto()
|
||||||
val key = SymmetricKey.random()
|
val key = SymmetricKey.new()
|
||||||
val key1 = SymmetricKey.random()
|
val key1 = SymmetricKey.new()
|
||||||
assertEquals("hello", key.decrypt(key.encrypt("hello".encodeToUByteArray())).decodeFromUByteArray())
|
assertEquals("hello", key.decrypt(key.encrypt("hello".encodeToUByteArray())).decodeFromUByteArray())
|
||||||
assertEquals("hello", key.decryptString(key.encrypt("hello")))
|
assertEquals("hello", key.decryptString(key.encrypt("hello")))
|
||||||
assertEquals("hello", key.decryptObject(key.encryptObject("hello")))
|
assertEquals("hello", key.decryptObject(key.encryptObject("hello")))
|
||||||
@ -88,7 +88,7 @@ class KeysTest {
|
|||||||
@Test
|
@Test
|
||||||
fun symmetricKeyTest() = runTest {
|
fun symmetricKeyTest() = runTest {
|
||||||
initCrypto()
|
initCrypto()
|
||||||
val k1 = SymmetricKey.random()
|
val k1 = SymmetricKey.new()
|
||||||
val src = "Buena Vista".encodeToUByteArray()
|
val src = "Buena Vista".encodeToUByteArray()
|
||||||
val nonce = k1.randomNonce()
|
val nonce = k1.randomNonce()
|
||||||
|
|
||||||
@ -176,9 +176,9 @@ class KeysTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testUniKeys() = runTest {
|
fun testUniKeys() = runTest {
|
||||||
initCrypto()
|
initCrypto()
|
||||||
val sy1 = SymmetricKey.random()
|
val sy1 = SymmetricKey.new()
|
||||||
val sy2 = SymmetricKey(sy1.keyBytes)
|
val sy2 = SymmetricKey(sy1.keyBytes)
|
||||||
val sy3 = SymmetricKey.random()
|
val sy3 = SymmetricKey.new()
|
||||||
|
|
||||||
assertEquals(sy1, sy2)
|
assertEquals(sy1, sy2)
|
||||||
assertEquals(sy2, sy1)
|
assertEquals(sy2, sy1)
|
||||||
@ -195,9 +195,9 @@ class KeysTest {
|
|||||||
assertEquals(usy2, usy1)
|
assertEquals(usy2, usy1)
|
||||||
assertFalse { usy1 == usy3 }
|
assertFalse { usy1 == usy3 }
|
||||||
|
|
||||||
val sk1 = Asymmetric.randomSecretKey()
|
val sk1 = Asymmetric.new()
|
||||||
val sk2 = Asymmetric.SecretKey(sk1.keyBytes)
|
val sk2 = Asymmetric.SecretKey(sk1.keyBytes)
|
||||||
val sk3 = Asymmetric.randomSecretKey()
|
val sk3 = Asymmetric.new()
|
||||||
|
|
||||||
assertEquals(sk1, sk2)
|
assertEquals(sk1, sk2)
|
||||||
assertEquals(sk2, sk1)
|
assertEquals(sk2, sk1)
|
||||||
|
@ -16,7 +16,7 @@ class RingTest {
|
|||||||
val y2 = SymmetricKey("1234567890Hello,dolly.here-we-go".encodeToUByteArray())
|
val y2 = SymmetricKey("1234567890Hello,dolly.here-we-go".encodeToUByteArray())
|
||||||
assertEquals(y1, y2)
|
assertEquals(y1, y2)
|
||||||
|
|
||||||
val e1 = Asymmetric.randomSecretKey()
|
val e1 = Asymmetric.new()
|
||||||
val e2: Asymmetric.SecretKey = BipackDecoder.decode(BipackEncoder.encode(e1))
|
val e2: Asymmetric.SecretKey = BipackDecoder.decode(BipackEncoder.encode(e1))
|
||||||
assertEquals(e1, e2)
|
assertEquals(e1, e2)
|
||||||
|
|
||||||
@ -26,8 +26,8 @@ class RingTest {
|
|||||||
assertEquals(k1, k11)
|
assertEquals(k1, k11)
|
||||||
|
|
||||||
|
|
||||||
val k2 = UniversalKey.from(Asymmetric.randomSecretKey())
|
val k2 = UniversalKey.from(Asymmetric.new())
|
||||||
val k3 = UniversalKey.from(Asymmetric.randomSecretKey())
|
val k3 = UniversalKey.from(Asymmetric.new())
|
||||||
//
|
//
|
||||||
val r = UniversalRing(k1, k2)
|
val r = UniversalRing(k1, k2)
|
||||||
// val r = UniversalRing(k1)
|
// val r = UniversalRing(k1)
|
||||||
@ -35,8 +35,8 @@ class RingTest {
|
|||||||
assertTrue(k1 in r)
|
assertTrue(k1 in r)
|
||||||
assertFalse { k3 in r }
|
assertFalse { k3 in r }
|
||||||
|
|
||||||
println(Asymmetric.randomSecretKey().keyBytes.size)
|
println(Asymmetric.new().keyBytes.size)
|
||||||
println(BipackEncoder.encode(Asymmetric.randomSecretKey()).size)
|
println(BipackEncoder.encode(Asymmetric.new()).size)
|
||||||
val encoded = BipackEncoder.encode(r)
|
val encoded = BipackEncoder.encode(r)
|
||||||
println(encoded.toDump())
|
println(encoded.toDump())
|
||||||
println(encoded.size)
|
println(encoded.size)
|
||||||
@ -60,16 +60,8 @@ class RingTest {
|
|||||||
fun testTags() = runTest {
|
fun testTags() = runTest {
|
||||||
initCrypto()
|
initCrypto()
|
||||||
|
|
||||||
val y1 = SymmetricKey("1234567890Hello,dolly.here-we-go".encodeToUByteArray())
|
|
||||||
val y2 = SymmetricKey("1234567890Hello,dolly.here-we-go".encodeToUByteArray())
|
|
||||||
|
|
||||||
val e1 = Asymmetric.randomSecretKey()
|
|
||||||
val e2: Asymmetric.SecretKey = BipackDecoder.decode(BipackEncoder.encode(e1))
|
|
||||||
|
|
||||||
val k1 = UniversalKey.from(SymmetricKey("1234567890Hello,dolly.here-we-go".encodeToUByteArray()))
|
val k1 = UniversalKey.from(SymmetricKey("1234567890Hello,dolly.here-we-go".encodeToUByteArray()))
|
||||||
val k11 = UniversalKey.from(SymmetricKey("1234567890Hello,dolly.here-we-go".encodeToUByteArray()))
|
val k2 = UniversalKey.from(Asymmetric.new())
|
||||||
val k2 = UniversalKey.from(Asymmetric.randomSecretKey())
|
|
||||||
val k3 = UniversalKey.from(Asymmetric.randomSecretKey())
|
|
||||||
|
|
||||||
val r1 = UniversalRing(k1, k2)
|
val r1 = UniversalRing(k1, k2)
|
||||||
var r2 = UniversalRing(deepCopy(k1), deepCopy(k2))
|
var r2 = UniversalRing(deepCopy(k1), deepCopy(k2))
|
||||||
@ -91,6 +83,35 @@ class RingTest {
|
|||||||
assertEquals(r2, r3)
|
assertEquals(r2, r3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAsymmetricEncryption() = runTest {
|
||||||
|
initCrypto()
|
||||||
|
|
||||||
|
val sk1 = UniversalKey.newSecretKey()
|
||||||
|
val sk2 = UniversalKey.newSecretKey()
|
||||||
|
val sk3 = UniversalKey.newSecretKey()
|
||||||
|
// val sk4 = UniversalKey.newSecretKey()
|
||||||
|
val sik1 = UniversalKey.newSigningKey()
|
||||||
|
// val sik2 = UniversalKey.newSigningKey()
|
||||||
|
val sik3 = UniversalKey.newSigningKey()
|
||||||
|
|
||||||
|
val data = "Mendeleev' table".encodeToUByteArray()
|
||||||
|
|
||||||
|
val r = UniversalRing(sk2, sk3, sk1.publicKey, sk3.publicKey, sik3.publicKey, sik1)
|
||||||
|
|
||||||
|
r.addTags(sik1, "SECRET_SIGN")
|
||||||
|
|
||||||
|
val box = deepCopy(Container.create(data) { key(sk3.publicKey) })
|
||||||
|
assertContentEquals(data, box.decryptWith(r))
|
||||||
|
|
||||||
|
assertEquals(sk3.publicKey, r.findKey<EncryptingKey>(sk3.id))
|
||||||
|
assertTrue { sik3.publicKey in r }
|
||||||
|
assertEquals(sik1, r.findKey<EncryptingKey>(sik1.publicKey.id))
|
||||||
|
|
||||||
|
assertEquals(sik1, r.keyByTag<SigningKey>("SECRET_SIGN"))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSize() = runTest {
|
fun testSize() = runTest {
|
||||||
// val sy1 = SymmetricKey.random().toUniversal()
|
// val sy1 = SymmetricKey.random().toUniversal()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user