keys refactoring: removed separate UniversalKey, it is now a direct base of any real keys instead of deleted KeyInstance

This commit is contained in:
Sergey Chernov 2024-06-24 15:44:35 +07:00
parent 5c97e857fc
commit 46a8b5bc06
12 changed files with 103 additions and 184 deletions

View File

@ -4,6 +4,7 @@ import com.ionspin.kotlin.crypto.box.Box
import com.ionspin.kotlin.crypto.box.BoxCorruptedOrTamperedDataException import com.ionspin.kotlin.crypto.box.BoxCorruptedOrTamperedDataException
import com.ionspin.kotlin.crypto.box.crypto_box_NONCEBYTES import com.ionspin.kotlin.crypto.box.crypto_box_NONCEBYTES
import com.ionspin.kotlin.crypto.scalarmult.ScalarMultiplication import com.ionspin.kotlin.crypto.scalarmult.ScalarMultiplication
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient import kotlinx.serialization.Transient
import net.sergeych.bipack.BipackDecoder import net.sergeych.bipack.BipackDecoder
@ -121,7 +122,8 @@ object Asymmetric {
* Anonymous encryption is very slow in comparison. * Anonymous encryption is very slow in comparison.
*/ */
@Serializable @Serializable
class PublicKey(override val keyBytes: UByteArray) : BinaryKeyBase(), KeyInstance { @SerialName("encp")
class PublicKey(override val keyBytes: UByteArray) : UniversalKey(), EncryptingKey {
override val magick: KeysMagickNumber = KeysMagickNumber.defaultAssymmetric override val magick: KeysMagickNumber = KeysMagickNumber.defaultAssymmetric
@ -143,9 +145,14 @@ object Asymmetric {
* Anonymous encryption, see [encryptAnonymousMessage], to binary data. Sender could not be identified. * Anonymous encryption, see [encryptAnonymousMessage], to binary data. Sender could not be identified.
*/ */
@Suppress("unused") @Suppress("unused")
fun encrypt(plainData: UByteArray, randomFill: IntRange? = null): UByteArray = override fun encrypt(plainData: UByteArray, randomFill: IntRange?): UByteArray =
encryptMessage(plainData, randomFill = randomFill).encoded encryptMessage(plainData, randomFill = randomFill).encoded
override fun encryptWithNonce(plainData: UByteArray, nonce: UByteArray, randomFill: IntRange?): UByteArray =
encryptMessage(plainData, nonce = nonce, randomFill = randomFill).encoded
override val nonceBytesLength: Int = Asymmetric.nonceBytesLength
/** /**
* Universal public-key encryption. Note that message authenticity is guaranteed if the decryption is successful * Universal public-key encryption. Note that message authenticity is guaranteed if the decryption is successful
* whether [senderKey] is provider, the latter only allow to positively identify the sender. * whether [senderKey] is provider, the latter only allow to positively identify the sender.
@ -173,19 +180,18 @@ object Asymmetric {
randomFill: IntRange? = null, randomFill: IntRange? = null,
): Message = ): Message =
createMessage(senderKey, this, WithFill.encode(plainData, randomFill)) createMessage(senderKey, this, WithFill.encode(plainData, randomFill))
fun toUniversalKey(): UniversalKey.Public = UniversalKey.Public(this)
} }
/** /**
* The secret key * The secret key
*/ */
@Serializable @Serializable
@SerialName("encs")
class SecretKey( class SecretKey(
override val keyBytes: UByteArray, override val keyBytes: UByteArray,
@Transient @Transient
val _cachedPublicKey: PublicKey? = null, val _cachedPublicKey: PublicKey? = null,
) : DecryptingKey, BinaryKeyBase() { ) : DecryptingKey, UniversalKey() {
/** /**
* Decrypt with authentication checks the message which must have [Message.senderPublicKey] set. * Decrypt with authentication checks the message which must have [Message.senderPublicKey] set.

View File

@ -1,31 +0,0 @@
package net.sergeych.crypto2
import kotlinx.serialization.Serializable
@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)

View File

@ -191,10 +191,6 @@ sealed class Container {
key(k) key(k)
} }
is UniversalKey.Secret -> {
key(k.key.publicKey)
}
else -> { else -> {
throw IllegalStateException("unknown key type to convert container: ${k::class.simpleName}") throw IllegalStateException("unknown key type to convert container: ${k::class.simpleName}")
} }

View File

@ -1,14 +1,12 @@
package net.sergeych.crypto2 package net.sergeych.crypto2
/**
* Marker interface: anything that is a key of some sort and can be identified
* with [KeyId].
*
* Note that to be keyring-capable it should inherit from [UniversalKey]
*/
interface KeyInstance { interface KeyInstance {
val id: KeyId val id: KeyId
} }
/**
* Create a new instance of the corresponding key.
*/
@Suppress("unused")
fun KeyInstance.toUniversalKey(): UniversalKey {
if (this is UniversalKey) return this
return UniversalKey.from(this)
}

View File

@ -2,6 +2,7 @@ package net.sergeych.crypto2
import com.ionspin.kotlin.crypto.signature.InvalidSignatureException import com.ionspin.kotlin.crypto.signature.InvalidSignatureException
import com.ionspin.kotlin.crypto.signature.Signature import com.ionspin.kotlin.crypto.signature.Signature
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient import kotlinx.serialization.Transient
@ -9,7 +10,8 @@ import kotlinx.serialization.Transient
* Public key to verify signatures only * Public key to verify signatures only
*/ */
@Serializable @Serializable
class SigningPublicKey(override val keyBytes: UByteArray) : BinaryKeyBase(), VerifyingKey { @SerialName("sigb")
class SigningPublicKey(override val keyBytes: UByteArray) : UniversalKey(), VerifyingKey {
/** /**
* Verify the signature and return true if it is correct. * Verify the signature and return true if it is correct.
*/ */

View File

@ -2,6 +2,7 @@ package net.sergeych.crypto2
import com.ionspin.kotlin.crypto.signature.Signature import com.ionspin.kotlin.crypto.signature.Signature
import kotlinx.datetime.Instant import kotlinx.datetime.Instant
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient import kotlinx.serialization.Transient
import net.sergeych.utools.now import net.sergeych.utools.now
@ -10,11 +11,12 @@ import net.sergeych.utools.now
* Secret key to sign only * Secret key to sign only
*/ */
@Serializable @Serializable
@SerialName("sigs")
class SigningSecretKey( class SigningSecretKey(
override val keyBytes: UByteArray, override val keyBytes: UByteArray,
@Transient @Transient
private var cachedPublicKey: SigningPublicKey?=null private var cachedPublicKey: SigningPublicKey?=null
) : BinaryKeyBase(), SigningKey { ) : UniversalKey(), SigningKey {
override val verifyingKey: SigningPublicKey by lazy { override val verifyingKey: SigningPublicKey by lazy {
cachedPublicKey ?: cachedPublicKey ?:

View File

@ -3,6 +3,7 @@ package net.sergeych.crypto2
import com.ionspin.kotlin.crypto.secretbox.SecretBox import com.ionspin.kotlin.crypto.secretbox.SecretBox
import com.ionspin.kotlin.crypto.secretbox.crypto_secretbox_KEYBYTES import com.ionspin.kotlin.crypto.secretbox.crypto_secretbox_KEYBYTES
import com.ionspin.kotlin.crypto.secretbox.crypto_secretbox_NONCEBYTES import com.ionspin.kotlin.crypto.secretbox.crypto_secretbox_NONCEBYTES
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient import kotlinx.serialization.Transient
@ -18,11 +19,14 @@ import kotlinx.serialization.Transient
* - Authentication: Poly1305 MAC * - Authentication: Poly1305 MAC
*/ */
@Serializable @Serializable
@SerialName("sym")
class SymmetricKey( class SymmetricKey(
val keyBytes: UByteArray, override val keyBytes: UByteArray,
@Transient @Transient
val pbkdfParams: PBKD.Params?=null val pbkdfParams: PBKD.Params?=null
) : EncryptingKey, DecryptingKey { ) : EncryptingKey, DecryptingKey, UniversalKey() {
override val magick: KeysMagickNumber = KeysMagickNumber.defaultSymmetric
/** /**
* @suppress * @suppress

View File

@ -1,116 +1,35 @@
package net.sergeych.crypto2 package net.sergeych.crypto2
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
/**
* Serializable implementation of the _any key_ conception. Allows serializing collections
* of different keys with arbitrary types, such as [UniversalRing].
*
* To create an `UniversalKey` instance use [UniversalKey.from] or [KeyInstance]
*/
@Serializable @Serializable
sealed class UniversalKey { sealed class UniversalKey: KeyInstance {
/**
* Propagate real ley instance. Base class itself can't be a key instance, but
* has the same id. This allows requiring key instances in [UniversalRing].
*/
abstract val id: KeyId
@Serializable abstract val keyBytes: UByteArray
@SerialName("sym") abstract val magick: KeysMagickNumber
data class Symmetric(val key: SymmetricKey) : UniversalKey(), EncryptingKey by key, DecryptingKey by key {
@Transient
override val id: KeyId = key.id
@Transient override val id by lazy { KeyId(magick, keyBytes) }
override val nonceBytesLength: Int = key.nonceBytesLength
override fun toString() = "U.Sym:$id" override fun equals(other: Any?): Boolean {
return other is UniversalKey && other.keyBytes contentEquals keyBytes
} }
@Serializable override fun hashCode(): Int {
@SerialName("ssn") return keyBytes.contentHashCode()
data class Session(val key: SafeKeyExchange.SessionKey) : UniversalKey(), EncryptingKey by key,
DecryptingKey by key {
@Transient
override val id: KeyId = key.id
@Transient
override val nonceBytesLength: Int = key.nonceBytesLength
override fun toString() = "U.Ssn:$id"
} }
@Serializable override fun toString(): String = keyBytes.encodeToBase64Url()
@SerialName("sec")
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 fun toString() = "U.Sec:$id"
}
@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.Pub:$id"
}
@Serializable
@SerialName("sig")
data class Signing(val key: SigningSecretKey) : UniversalKey(), SigningKey by key {
override val id: KeyId by lazy { key.id }
override fun toString() = "U.Sig:$id"
/**
* [Verifying] key, e.g. [verifyingKey] wrapped in the [UniversalKey] variant.
*/
val publicKey by lazy { Verifying(verifyingKey) }
}
@Serializable
@SerialName("ver")
data class Verifying(val key: SigningPublicKey) : UniversalKey(), VerifyingKey by key {
override val id: KeyId by lazy { key.id }
override fun toString() = "U.Ver:$id"
}
companion object { companion object {
fun from(key: KeyInstance): UniversalKey = fun newSecretKey() = Asymmetric.newSecretKey()
when (key) { fun newSigningKey() = SigningSecretKey.new()
is UniversalKey -> key
is Asymmetric.SecretKey -> Secret(key)
is Asymmetric.PublicKey -> Public(key)
is SymmetricKey -> Symmetric(key)
is SafeKeyExchange.SessionKey -> Session(key)
else -> throw UnsupportedOperationException("can't create universal key from ${key::class.simpleName}")
}
fun newSecretKey(): Secret =
Secret(Asymmetric.newSecretKey())
fun newSigningKey(): Signing =
Signing(SigningSecretKey.new())
@Suppress("unused") @Suppress("unused")
fun newSymmetricKey(): Symmetric = fun newSymmetricKey() = SymmetricKey.new()
Symmetric(SymmetricKey.new())
}
}
} }
open class IllegalSignatureException(text: String = "signed data is tampered or signature is corrupted") :
IllegalStateException(text)
class ExpiredSignatureException(text: String) : IllegalSignatureException(text)

View File

@ -17,7 +17,7 @@ import kotlinx.serialization.Serializable
class UniversalRing( class UniversalRing(
val keyWithTags: Map<UniversalKey, Set<String>>, val keyWithTags: Map<UniversalKey, Set<String>>,
) { ) {
constructor(vararg keys: UniversalKey) : this(keys.associateWith { setOf() }) constructor(vararg keys: UniversalKey) : this(keys.associate { it to setOf() })
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) })
@ -37,10 +37,12 @@ class UniversalRing(
val allKeys: Set<UniversalKey> by lazy { keyWithTags.keys } val allKeys: Set<UniversalKey> by lazy { keyWithTags.keys }
/** /**
* Find a key of the specified type that matches the id. __Important__ it is not possible to * Find a key of the specified type that matches the id. In general, you require key implementations like
* require [UniversalKey] as [T], it is not a [KeyInstance], while its descendants are, [UniversalKey.Secret], etc. * [Asymmetric.SecretKey], [Asymmetric.PublicKey], [SigningPublicKey], [SigningSecretKey] and [SymmetricKey],
* You can freely use [UniversalKey] subtypes or general key interfaces, e.g. * or just key interfaces: [EncryptingKey], [DecryptingKey], [SigningKey] and [VerifyingKey].
* [EncryptingKey], [DecryptingKey], [SigningKey] and [VerifyingKey]. *
* Note that key interfaces are not serializable as for now, you should try to cast to a serializable
* base.
* *
* Please avoid selecting parameters that make possible to pick more than one key, it will cause an exception. * Please avoid selecting parameters that make possible to pick more than one key, it will cause an exception.
* *
@ -227,15 +229,15 @@ class UniversalRing(
* Convert any keys to [UniversalKey] and form a ring with it. * Convert any keys to [UniversalKey] and form a ring with it.
* @throws UnsupportedOperationException if [UniversalKey] can't build an instance of the specified class. * @throws UnsupportedOperationException if [UniversalKey] can't build an instance of the specified class.
*/ */
fun from(vararg keys: KeyInstance): UniversalRing = fun from(vararg keys: DecryptingKey): UniversalRing =
UniversalRing(keys.associate { UniversalKey.from(it) to setOf() } ) UniversalRing(keys.associate { it as UniversalKey to setOf() } )
/** /**
* Convert any keys to [UniversalKey] and form a ring with it. * Convert any keys to [UniversalKey] and form a ring with it.
* @throws UnsupportedOperationException if [UniversalKey] can't build an instance of the specified class. * @throws UnsupportedOperationException if [UniversalKey] can't build an instance of the specified class.
*/ */
fun from(vararg keyTags: Pair<KeyInstance,String>): UniversalRing = fun from(vararg keyTags: Pair<UniversalKey,String>): UniversalRing =
UniversalRing(keyTags.associate { UniversalKey.from(it.first) to setOf(it.second) } ) UniversalRing(keyTags.associate {it.first to setOf(it.second) } )
} }
} }

View File

@ -0,0 +1,10 @@
package net.sergeych.tools
import net.sergeych.bipack.BipackDecoder
import net.sergeych.bipack.BipackEncoder
inline fun <reified T>bipack(value: T): UByteArray = BipackEncoder.encode(value).toUByteArray()
inline fun <reified T>biunpack(value: UByteArray): T = BipackDecoder.decode(value.toByteArray())

View File

@ -4,6 +4,8 @@ import kotlinx.coroutines.test.runTest
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import net.sergeych.crypto2.* import net.sergeych.crypto2.*
import net.sergeych.tools.bipack
import net.sergeych.tools.biunpack
import net.sergeych.utools.now import net.sergeych.utools.now
import net.sergeych.utools.pack import net.sergeych.utools.pack
import net.sergeych.utools.unpack import net.sergeych.utools.unpack
@ -187,9 +189,9 @@ class KeysTest {
assertEquals(sy1, deepCopy(sy1), "symmetric key should be equal to the restored copy") assertEquals(sy1, deepCopy(sy1), "symmetric key should be equal to the restored copy")
assertEquals(sy1.hashCode(), deepCopy(sy1).hashCode(), "hashcode of the restored symmetric key is wrong") assertEquals(sy1.hashCode(), deepCopy(sy1).hashCode(), "hashcode of the restored symmetric key is wrong")
val usy1 = UniversalKey.from(sy1) val usy1 = sy1 as UniversalKey
val usy2 = UniversalKey.from(sy2) val usy2 = sy2 as UniversalKey
val usy3 = UniversalKey.from(sy3) val usy3 = sy3 as UniversalKey
assertEquals(usy1, usy2) assertEquals(usy1, usy2)
assertEquals(usy2, usy1) assertEquals(usy2, usy1)
@ -203,10 +205,10 @@ class KeysTest {
assertEquals(sk2, sk1) assertEquals(sk2, sk1)
assertFalse { sk1 == sk3 } assertFalse { sk1 == sk3 }
var usk1 = UniversalKey.from(sk1) var usk1 = sk1 as UniversalKey
var usk2 = UniversalKey.from(sk2) var usk2 = sk2 as UniversalKey
var usk3 = UniversalKey.from(sk3) var usk3 = sk3 as UniversalKey
val usk4 = UniversalKey.from(sy3) val usk4 = sy3 as UniversalKey
assertEquals(usk1, usk2) assertEquals(usk1, usk2)
assertEquals(usk2, usk1) assertEquals(usk2, usk1)
@ -223,7 +225,7 @@ class KeysTest {
usk2 = deepCopy(usk2) usk2 = deepCopy(usk2)
usk3 = deepCopy(usk3) usk3 = deepCopy(usk3)
assertEquals(usk1.hashCode(),usk2.hashCode()) assertEquals(usk1.hashCode(), usk2.hashCode())
assertEquals(usk1, usk2) assertEquals(usk1, usk2)
assertEquals(usk2, usk1) assertEquals(usk2, usk1)
@ -239,4 +241,13 @@ class KeysTest {
// usk1 and usk2 are equal so set with only one of should be the same // usk1 and usk2 are equal so set with only one of should be the same
assertEquals(a, setOf(usk1, usk3, usk4)) assertEquals(a, setOf(usk1, usk3, usk4))
} }
@Test
fun testKiSerialization() = runTest {
initCrypto()
val k: UniversalKey = SymmetricKey.new()
val d = bipack(k)
val k1: UniversalKey = biunpack<UniversalKey>(d) as SymmetricKey
assertEquals(k, k1)
}
} }

View File

@ -20,14 +20,14 @@ class RingTest {
val e2: Asymmetric.SecretKey = BipackDecoder.decode(BipackEncoder.encode(e1)) val e2: Asymmetric.SecretKey = BipackDecoder.decode(BipackEncoder.encode(e1))
assertEquals(e1, e2) assertEquals(e1, e2)
val k1 = UniversalKey.from(SymmetricKey("1234567890Hello,dolly.here-we-go".encodeToUByteArray())) val k1 = SymmetricKey("1234567890Hello,dolly.here-we-go".encodeToUByteArray()) as UniversalKey
val k11 = UniversalKey.from(SymmetricKey("1234567890Hello,dolly.here-we-go".encodeToUByteArray())) val k11 = SymmetricKey("1234567890Hello,dolly.here-we-go".encodeToUByteArray()) as UniversalKey
assertEquals(k1, k11) assertEquals(k1, k11)
val k2 = UniversalKey.from(Asymmetric.newSecretKey()) val k2 = Asymmetric.newSecretKey()
val k3 = UniversalKey.from(Asymmetric.newSecretKey()) val k3 = Asymmetric.newSecretKey()
// //
val r = UniversalRing(k1, k2) val r = UniversalRing(k1, k2)
// val r = UniversalRing(k1) // val r = UniversalRing(k1)
@ -40,7 +40,7 @@ class RingTest {
val encoded = BipackEncoder.encode(r) val encoded = BipackEncoder.encode(r)
println(encoded.toDump()) println(encoded.toDump())
println(encoded.size) println(encoded.size)
assertTrue { encoded.size < 80 } assertTrue { encoded.size < 82 }
val r2: UniversalRing = BipackDecoder.decode(encoded) val r2: UniversalRing = BipackDecoder.decode(encoded)
assertTrue { k2 in r2 } assertTrue { k2 in r2 }
assertTrue { k1 in r2 } assertTrue { k1 in r2 }
@ -69,16 +69,16 @@ class RingTest {
val r1 = deepCopy(r) val r1 = deepCopy(r)
println(r1.findKey<EncryptingKey>(sk.id)) println(r1.findKey<EncryptingKey>(sk.id))
println(sk) println(sk)
assertTrue { sk.publicKey.toUniversalKey() == r1.findKey<EncryptingKey>(sk.id) } assertTrue { sk.publicKey as UniversalKey == r1.findKey<EncryptingKey>(sk.id) }
assertTrue { sk.publicKey.toUniversalKey() == r1.keyByTag<EncryptingKey>("foo") } assertTrue { sk.publicKey as UniversalKey == r1.keyByTag<EncryptingKey>("foo") }
} }
@Test @Test
fun testTags() = runTest { fun testTags() = runTest {
initCrypto() initCrypto()
val k1 = UniversalKey.from(SymmetricKey("1234567890Hello,dolly.here-we-go".encodeToUByteArray())) val k1 = SymmetricKey("1234567890Hello,dolly.here-we-go".encodeToUByteArray()) as UniversalKey
val k2 = UniversalKey.from(Asymmetric.newSecretKey()) val k2 = Asymmetric.newSecretKey() as UniversalKey
val r1 = UniversalRing(k1, k2) val r1 = UniversalRing(k1, k2)
var r2 = UniversalRing(deepCopy(k1), deepCopy(k2)) var r2 = UniversalRing(deepCopy(k1), deepCopy(k2))
@ -114,7 +114,7 @@ class RingTest {
val data = "Mendeleev' table".encodeToUByteArray() val data = "Mendeleev' table".encodeToUByteArray()
var r = UniversalRing(sk2, sk3, sk1.publicKey, sk3.publicKey, sik3.publicKey, sik1.publicKey) var r = UniversalRing(sk2, sk3, sk1.publicKey, sk3.publicKey, sik3.verifyingKey, sik1.verifyingKey)
r = r.addTags(sik1, "SECRET_SIGN") r = r.addTags(sik1, "SECRET_SIGN")
@ -122,11 +122,11 @@ class RingTest {
assertContentEquals(data, box.decryptWith(r)) assertContentEquals(data, box.decryptWith(r))
assertEquals(sk3.publicKey, r.findKey<EncryptingKey>(sk3.id)) assertEquals(sk3.publicKey, r.findKey<EncryptingKey>(sk3.id))
assertTrue { sik3.publicKey in r } assertTrue { sik3.verifyingKey in r }
assertTrue { sik1 in r } assertTrue { sik1 in r }
assertEquals(sik1, r.keyByTag<UniversalKey>("SECRET_SIGN")) assertEquals(sik1, r.keyByTag<UniversalKey>("SECRET_SIGN"))
assertEquals(sik1, r.findKey<SigningKey>(sik1.publicKey.id)) assertEquals(sik1, r.findKey<SigningKey>(sik1.verifyingKey.id))
} }
@Test @Test
@ -154,17 +154,17 @@ class RingTest {
var r1 = ra + rb + rc + rd var r1 = ra + rb + rc + rd
assertEquals(a, r1.findKey<UniversalKey.Secret>(a.id)) assertEquals(a, r1.findKey<Asymmetric.SecretKey>(a.id))
assertEquals(a, r1.keyByTag<UniversalKey>("foo_a")) assertEquals(a, r1.keyByTag<UniversalKey>("foo_a"))
assertEquals(b, r1.findKey<SigningKey>(b.id)) assertEquals(b, r1.findKey<SigningKey>(b.id))
assertEquals(c, r1.keysById(c.key.id).first()) assertEquals(c, r1.keysById(c.id).first())
r1 = UniversalRing.join(listOf(ra, rb, rc, rd)) r1 = UniversalRing.join(listOf(ra, rb, rc, rd))
assertEquals(a, r1.findKey<UniversalKey.Secret>(a.id)) assertEquals(a, r1.findKey<Asymmetric.SecretKey>(a.id))
assertEquals(a, r1.keyByTag<UniversalKey>("foo_a")) assertEquals(a, r1.keyByTag<UniversalKey>("foo_a"))
assertEquals(b, r1.findKey<SigningKey>(b.id)) assertEquals(b, r1.findKey<SigningKey>(b.id))
assertEquals(c, r1.keysById(c.key.id).first()) assertEquals(c, r1.keysById(c.id).first())
} }
} }