refining keys model
This commit is contained in:
		
							parent
							
								
									c4accfcd91
								
							
						
					
					
						commit
						bb383b5457
					
				@ -80,7 +80,7 @@ sealed class Container {
 | 
				
			|||||||
     * @return decrypted data or null if this ring contains no proper key for it
 | 
					     * @return decrypted data or null if this ring contains no proper key for it
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    fun decryptWith(vararg keys: DecryptingKey): UByteArray? =
 | 
					    fun decryptWith(vararg keys: DecryptingKey): UByteArray? =
 | 
				
			||||||
        decryptWith(UniversalRing(*keys))
 | 
					        decryptWith(UniversalRing.from(*keys))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Transient
 | 
					    @Transient
 | 
				
			||||||
    var decryptedData: UByteArray? = null
 | 
					    var decryptedData: UByteArray? = null
 | 
				
			||||||
 | 
				
			|||||||
@ -3,13 +3,28 @@ package net.sergeych.crypto2
 | 
				
			|||||||
import kotlinx.serialization.Serializable
 | 
					import kotlinx.serialization.Serializable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Tag that identifies in some way the _decrypting key_. Is used in keyrings and
 | 
					 * Key Identity. Can be used to find matching keys for decryption or verifying, etc. The identity
 | 
				
			||||||
 * containers to fast find a proper key
 | 
					 * may contain [KDF] parameters if the corresponding key could be derived from a password.
 | 
				
			||||||
 | 
					 * Note that [kdf] part is not respected in [equals].
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Important. `KeyId` of matching keys are the same, so you can use it to identify
 | 
				
			||||||
 | 
					 * and find matching keys in the [UniversalRing], etc. For example:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * - [Asymmetric.SecretKey] and [Asymmetric.PublicKey] from the same pair have the same `KeyId`, thus the former
 | 
				
			||||||
 | 
					 *   can decrypt what was encrypted with the latter.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * - [SigningSecretKey] and corresponding [VerifyingKey] have the same `KeyId`. Use it to pick a proper key for
 | 
				
			||||||
 | 
					 *   signing from a ring with [UniversalRing.findKey]
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@Serializable
 | 
					@Serializable
 | 
				
			||||||
data class KeyId(val id: BinaryId, val kdp: KeyDerivationParams?=null ) {
 | 
					data class KeyId(val id: BinaryId, val kdf: KeyDerivationParams?=null ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    val tag: UByteArray by lazy { id.id }
 | 
					    /**
 | 
				
			||||||
 | 
					     * Binary array representation of the [id], not including the [kdf]. Used in [SafeKeyExchange]
 | 
				
			||||||
 | 
					     * and other key exchanges to generate session tokens, etc.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    val binaryTag: UByteArray by lazy { id.id }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun equals(other: Any?): Boolean {
 | 
					    override fun equals(other: Any?): Boolean {
 | 
				
			||||||
        if (this === other) return true
 | 
					        if (this === other) return true
 | 
				
			||||||
 | 
				
			|||||||
@ -47,9 +47,9 @@ class SafeKeyExchange {
 | 
				
			|||||||
        @Suppress("unused")
 | 
					        @Suppress("unused")
 | 
				
			||||||
        val sessionTag: UByteArray by lazy {
 | 
					        val sessionTag: UByteArray by lazy {
 | 
				
			||||||
            if (!isClient)
 | 
					            if (!isClient)
 | 
				
			||||||
                blake2b(id.tag + id.tag)
 | 
					                blake2b(id.binaryTag + id.binaryTag)
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                blake2b(id.tag + id.tag)
 | 
					                blake2b(id.binaryTag + id.binaryTag)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        override val id: KeyId
 | 
					        override val id: KeyId
 | 
				
			||||||
 | 
				
			|||||||
@ -4,53 +4,101 @@ import kotlinx.serialization.Serializable
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@Serializable
 | 
					@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.associateWith { setOf() })
 | 
				
			||||||
    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) })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    val decryptingKeys: Set<DecryptingKey> by lazy { keys<DecryptingKey>() }
 | 
					    val decryptingKeys: Set<DecryptingKey> by lazy { keys<DecryptingKey>() }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Select keys of the specified type
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    inline fun <reified T> keys(): Set<T> =
 | 
				
			||||||
 | 
					        allKeys.mapNotNull { it as? T }.toSet()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    inline fun <reified T>keys(): Set<T> =
 | 
					    val allKeys: Set<UniversalKey> by lazy { keyWithTags.keys }
 | 
				
			||||||
        keyWithTags.keys.mapNotNull { it as? T }.toSet()
 | 
					    
 | 
				
			||||||
 | 
					    inline fun <reified T> findKey(id: KeyId): UniversalKey? =
 | 
				
			||||||
 | 
					        allKeys.find { it is T && it.id == id }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    inline fun <reified T>findKey(id: KeyId): UniversalKey? =
 | 
					    fun keysById(id: KeyId): List<UniversalKey> = allKeys.filter { it.id == id }
 | 
				
			||||||
        keyWithTags.keys.find { it is T && it.id == id }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun allByAnyOfTags(vararg tags: String) = sequence {
 | 
					    /**
 | 
				
			||||||
        for( e in keyWithTags.entries) {
 | 
					     * Return sequence of keys that have at least one of the [tags]
 | 
				
			||||||
            if( tags.any { it in e.value }) yield(e.key)
 | 
					     */
 | 
				
			||||||
 | 
					    fun keysByTags(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 }
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the first key of the specified type having the [tag]
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    inline fun <reified T> keyByTag(tag: String) = keysByTags(tag).first { it is T }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Suppress("unused")
 | 
					    @Suppress("unused")
 | 
				
			||||||
    inline fun <reified T>keyByAnyTag(vararg tags: String) = allByAnyOfTags(*tags).first { it is T }
 | 
					    inline fun <reified T> keyByAnyTag(vararg tags: String) = keysByTags(*tags).first { it is T }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    operator fun get(keyId: KeyId): Collection<UniversalKey> = keyWithTags.keys.filter { it.id == keyId }
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get all keys with a given id. Note that _matching keys_ have the same id, see [KeyId] for more.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    operator fun get(keyId: KeyId): Collection<UniversalKey> = allKeys.filter { it.id == keyId }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun getTags(key: UniversalKey): Set<String>? = keyWithTags[key]
 | 
					    fun getTags(key: UniversalKey): Set<String>? = keyWithTags[key]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    operator fun contains(element: UniversalKey): Boolean = element in keyWithTags
 | 
					    operator fun contains(element: UniversalKey): Boolean = element in keyWithTags
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Add a key if not already in a ring, otherwise return existing ring.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    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()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    operator fun plus(keyTag: Pair<UniversalKey,String>): UniversalRing =
 | 
					    /**
 | 
				
			||||||
        if( keyTag.first in this )
 | 
					     * Add a key and tags to the ring. If the key exists, add the tag to it.
 | 
				
			||||||
            addTags(keyTag.first,keyTag.second)
 | 
					     * See also [addTags].
 | 
				
			||||||
        else UniversalRing(keyWithTags + keyWithTags)
 | 
					     */
 | 
				
			||||||
 | 
					    operator fun plus(keyTag: Pair<UniversalKey, String>): UniversalRing =
 | 
				
			||||||
 | 
					        if (keyTag.first in this)
 | 
				
			||||||
 | 
					            addTags(keyTag.first, keyTag.second)
 | 
				
			||||||
 | 
					        else add(keyTag.first, keyTag.second)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Merge two rings. The result will contain all keys and all tags from
 | 
				
			||||||
 | 
					     * both rings.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    operator fun plus(other: UniversalRing): UniversalRing {
 | 
				
			||||||
 | 
					        var result = keyWithTags.toMutableMap()
 | 
				
			||||||
 | 
					        for (e in other.keyWithTags.entries) {
 | 
				
			||||||
 | 
					            result[e.key]?.let {
 | 
				
			||||||
 | 
					                result[e.key] = it + e.value
 | 
				
			||||||
 | 
					            } ?: run {
 | 
				
			||||||
 | 
					                result[e.key] = e.value
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return UniversalRing(result)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Add key and tags to the ring. If the key already exists, tags are merged.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    fun add(key: UniversalKey, vararg tags: String): UniversalRing =
 | 
					    fun add(key: UniversalKey, vararg tags: String): UniversalRing =
 | 
				
			||||||
        UniversalRing(keyWithTags + (key to tags.toSet()) )
 | 
					        UniversalRing(keyWithTags + (key to tags.toSet()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Add key and tags to the ring. If the key already exists, tags are merged.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    fun add(key: UniversalKey, tags: Collection<String>): UniversalRing =
 | 
					    fun add(key: UniversalKey, tags: Collection<String>): UniversalRing =
 | 
				
			||||||
        UniversalRing(keyWithTags + (key to tags.toSet()) )
 | 
					        UniversalRing(keyWithTags + (key to tags.toSet()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun addTags(key: UniversalKey,tags: Set<String>): UniversalRing {
 | 
					    /**
 | 
				
			||||||
 | 
					     * Add tags to the key, and add key if it is not in the ring.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fun addTags(key: UniversalKey, tags: Set<String>): UniversalRing {
 | 
				
			||||||
        val kt1 = keyWithTags.toMutableMap()
 | 
					        val kt1 = keyWithTags.toMutableMap()
 | 
				
			||||||
        kt1[key]?.let {
 | 
					        kt1[key]?.let {
 | 
				
			||||||
            kt1[key] = it + tags
 | 
					            kt1[key] = it + tags
 | 
				
			||||||
@ -60,11 +108,17 @@ class UniversalRing(
 | 
				
			|||||||
        return UniversalRing(kt1)
 | 
					        return UniversalRing(kt1)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun addTags(key: UniversalKey,vararg tags: String): UniversalRing =
 | 
					    /**
 | 
				
			||||||
        addTags(key,tags.toSet())
 | 
					     * Add tags to the key, and add key if it is not in the ring.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fun addTags(key: UniversalKey, vararg tags: String): UniversalRing =
 | 
				
			||||||
 | 
					        addTags(key, tags.toSet())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * return the ring without [key] if existed, otherwise returns `this`.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun equals(other: Any?): Boolean {
 | 
					    override fun equals(other: Any?): Boolean {
 | 
				
			||||||
        if (this === other) return true
 | 
					        if (this === other) return true
 | 
				
			||||||
@ -72,27 +126,64 @@ class UniversalRing(
 | 
				
			|||||||
        return keyWithTags == other.keyWithTags
 | 
					        return keyWithTags == other.keyWithTags
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun toString(): String {
 | 
					 | 
				
			||||||
        val ss = keyWithTags.entries
 | 
					 | 
				
			||||||
            .joinToString(","){"${it.value.joinToString{ ":" }}:${it.key}"}
 | 
					 | 
				
			||||||
        return "Kr[$ss]"
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    override fun hashCode(): Int {
 | 
					    override fun hashCode(): Int {
 | 
				
			||||||
        return keyWithTags.hashCode()
 | 
					        return keyWithTags.hashCode()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    infix fun equalKeys(other: UniversalRing): Boolean = keyWithTags.keys == other.keyWithTags.keys
 | 
					    override fun toString(): String {
 | 
				
			||||||
 | 
					        val ss = keyWithTags.entries
 | 
				
			||||||
    fun removeTags(key: UniversalKey, vararg tags: String): UniversalRing = removeTags(key, tags.toSet())
 | 
					            .joinToString(",") { "${it.value.joinToString { ":" }}:${it.key}" }
 | 
				
			||||||
 | 
					        return "Kr[$ss]"
 | 
				
			||||||
    fun removeTags(key: UniversalKey, tags: Set<String>): UniversalRing {
 | 
					 | 
				
			||||||
        val kt1 = keyWithTags.toMutableMap()
 | 
					 | 
				
			||||||
        kt1[key]?.let {
 | 
					 | 
				
			||||||
            kt1[key] = it - tags
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return UniversalRing(kt1)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    infix fun equalKeys(other: UniversalRing): Boolean = allKeys == other.allKeys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Create a collection where no [tags] are specified for the [key]. If the key is not
 | 
				
			||||||
 | 
					     * in the collection, it returns this.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fun removeTags(key: UniversalKey, vararg tags: String): UniversalRing = removeTags(key, tags.toSet())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Create a collection where no [tags] are specified for the [key]. If the key is not
 | 
				
			||||||
 | 
					     * in the collection, it returns this.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fun removeTags(key: UniversalKey, tags: Set<String>): UniversalRing =
 | 
				
			||||||
 | 
					        keyWithTags[key]?.let { existingTags ->
 | 
				
			||||||
 | 
					            val kt1 = keyWithTags.toMutableMap()
 | 
				
			||||||
 | 
					            kt1[key] = existingTags - tags
 | 
				
			||||||
 | 
					            UniversalRing(kt1)
 | 
				
			||||||
 | 
					        } ?: this
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Create string "report" of the ring contents. Note it has no trailing `\n`
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fun ls(): String {
 | 
				
			||||||
 | 
					        val result = mutableListOf<String>()
 | 
				
			||||||
 | 
					        for( e in keyWithTags.entries) {
 | 
				
			||||||
 | 
					            result += "${e.key} ${e.value.joinToString(" ")}"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return result.joinToString("\n")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    companion object {
 | 
				
			||||||
 | 
					        val EMPTY = UniversalRing(keyWithTags = emptyMap())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Join a collection of keyrings together (same as reducing with `+`). Correctly
 | 
				
			||||||
 | 
					         * works if there is no keyring (returns [EMPTY]), or only one keyring (returns
 | 
				
			||||||
 | 
					         * it with no extra work).
 | 
				
			||||||
 | 
					         *
 | 
				
			||||||
 | 
					         * Note that for the known number of rings using [plus] is more clear and expressive
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        fun join(keyRings: Collection<UniversalRing>): UniversalRing {
 | 
				
			||||||
 | 
					            if (keyRings.isEmpty()) return EMPTY
 | 
				
			||||||
 | 
					            if (keyRings.size == 1) return keyRings.first()
 | 
				
			||||||
 | 
					            return keyRings.reduce { l, r -> l + r }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fun from(vararg keys: DecryptingKey): UniversalRing =
 | 
				
			||||||
 | 
					            UniversalRing(keys.associate { UniversalKey.from(it) to setOf() } )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -114,6 +114,40 @@ class RingTest {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Test
 | 
					    @Test
 | 
				
			||||||
    fun testSize() = runTest {
 | 
					    fun testSize() = runTest {
 | 
				
			||||||
//        val sy1 = SymmetricKey.random().toUniversal()
 | 
					        initCrypto()
 | 
				
			||||||
 | 
					        val r = UniversalRing(UniversalKey.newSymmetricKey())
 | 
				
			||||||
 | 
					        val rd = BipackEncoder.encode(r)
 | 
				
			||||||
 | 
					        println(rd.size)
 | 
				
			||||||
 | 
					        println(rd.toDump())
 | 
				
			||||||
 | 
					        assertTrue { rd.size <= 46 }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun testJoin() = runTest {
 | 
				
			||||||
 | 
					        initCrypto()
 | 
				
			||||||
 | 
					        val a = UniversalKey.newSecretKey()
 | 
				
			||||||
 | 
					        val b = UniversalKey.newSigningKey()
 | 
				
			||||||
 | 
					        val c = UniversalKey.newSymmetricKey()
 | 
				
			||||||
 | 
					        val d = UniversalKey.newSigningKey()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val ra = UniversalRing(a)
 | 
				
			||||||
 | 
					        val rb = UniversalRing(b)
 | 
				
			||||||
 | 
					        val rc = UniversalRing(c)
 | 
				
			||||||
 | 
					        val rd = UniversalRing(d) + (a to "foo_a")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var r1 = ra + rb + rc + rd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertEquals(a, r1.findKey<UniversalKey.Secret>(a.id))
 | 
				
			||||||
 | 
					        assertEquals(a, r1.keyByTag<UniversalKey>("foo_a"))
 | 
				
			||||||
 | 
					        assertEquals(b, r1.findKey<SigningKey>(b.id))
 | 
				
			||||||
 | 
					        assertEquals(c, r1.keysById(c.key.id).first())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        r1 = UniversalRing.join(listOf(ra, rb, rc, rd))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertEquals(a, r1.findKey<UniversalKey.Secret>(a.id))
 | 
				
			||||||
 | 
					        assertEquals(a, r1.keyByTag<UniversalKey>("foo_a"))
 | 
				
			||||||
 | 
					        assertEquals(b, r1.findKey<SigningKey>(b.id))
 | 
				
			||||||
 | 
					        assertEquals(c, r1.keysById(c.key.id).first())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user