forked from sergeych/crypto2
		
	0.5.8-SNAPSHOT: Multikeys
This commit is contained in:
		
							parent
							
								
									491f9d47f6
								
							
						
					
					
						commit
						8e652e0421
					
				@ -8,7 +8,7 @@ plugins {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
group = "net.sergeych"
 | 
			
		||||
version = "0.5.7"
 | 
			
		||||
version = "0.5.8-SNAPSHOT"
 | 
			
		||||
 | 
			
		||||
repositories {
 | 
			
		||||
    mavenCentral()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										76
									
								
								src/commonMain/kotlin/net/sergeych/crypto2/ByteChunk.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/commonMain/kotlin/net/sergeych/crypto2/ByteChunk.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,76 @@
 | 
			
		||||
package net.sergeych.crypto2
 | 
			
		||||
 | 
			
		||||
import kotlinx.serialization.Serializable
 | 
			
		||||
import net.sergeych.bintools.decodeHex
 | 
			
		||||
import net.sergeych.bintools.encodeToHex
 | 
			
		||||
import kotlin.math.min
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Bytes sequence with comparison, concatenation, and string representation,
 | 
			
		||||
 * could be used as hash keys for pure binary values, etc.
 | 
			
		||||
 */
 | 
			
		||||
@Suppress("unused")
 | 
			
		||||
@Serializable
 | 
			
		||||
class ByteChunk(val data: UByteArray): Comparable<ByteChunk> {
 | 
			
		||||
 | 
			
		||||
    val size: Int get() = data.size
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Per-byte comparison also of different length. From two chunks
 | 
			
		||||
     * of different size but equal beginning, the shorter is considered
 | 
			
		||||
     * the smaller.
 | 
			
		||||
     */
 | 
			
		||||
    override fun compareTo(other: ByteChunk): Int {
 | 
			
		||||
        val limit = min(size, other.size)
 | 
			
		||||
        for( i in 0 ..< limit) {
 | 
			
		||||
            val own = data[i]
 | 
			
		||||
            val their = other.data[i]
 | 
			
		||||
            if( own < their) return -1
 | 
			
		||||
            else if( own > their) return 1
 | 
			
		||||
        }
 | 
			
		||||
        if( size < other.size ) return -1
 | 
			
		||||
        if( size > other.size ) return 1
 | 
			
		||||
        return 0
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Equal chunks means content equality.
 | 
			
		||||
     */
 | 
			
		||||
    override fun equals(other: Any?): Boolean {
 | 
			
		||||
        if (this === other) return true
 | 
			
		||||
        if (other !is ByteChunk) return false
 | 
			
		||||
 | 
			
		||||
        return data contentEquals other.data
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Content-based hash code
 | 
			
		||||
     */
 | 
			
		||||
    override fun hashCode(): Int {
 | 
			
		||||
        return data.contentHashCode()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * hex representation of data
 | 
			
		||||
     */
 | 
			
		||||
    override fun toString(): String = hex
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Hex encoded data
 | 
			
		||||
     */
 | 
			
		||||
    val hex by lazy { data.encodeToHex() }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * human-readable dump
 | 
			
		||||
     */
 | 
			
		||||
    val dump by lazy { data.toDump() }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Concatenate two chunks and return new one
 | 
			
		||||
     */
 | 
			
		||||
    operator fun plus(other: ByteChunk): ByteChunk = ByteChunk(data + other.data)
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        fun fromHex(hex: String): ByteChunk = ByteChunk(hex.decodeHex().asUByteArray())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -28,6 +28,8 @@ data class KeyId(val id: BinaryId, val kdp: PBKD.Params? = null) {
 | 
			
		||||
    /**
 | 
			
		||||
     * Binary array representation of the [id], not including the [kdp]. Used in [SafeKeyExchange]
 | 
			
		||||
     * and other key exchanges to generate session tokens, etc.
 | 
			
		||||
     *
 | 
			
		||||
     * In shortcut for packed [BinaryId], from [id]. If you need only key bytes, use [UniversalKey.keyBytes].
 | 
			
		||||
     */
 | 
			
		||||
    val binaryTag: UByteArray by lazy { id.id }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										178
									
								
								src/commonMain/kotlin/net/sergeych/crypto2/Multikey.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								src/commonMain/kotlin/net/sergeych/crypto2/Multikey.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,178 @@
 | 
			
		||||
package net.sergeych.crypto2
 | 
			
		||||
 | 
			
		||||
import kotlinx.serialization.SerialName
 | 
			
		||||
import kotlinx.serialization.Serializable
 | 
			
		||||
import net.sergeych.crypto2.Multikey.Companion.allOf
 | 
			
		||||
import net.sergeych.crypto2.Multikey.Companion.allOfMultikeys
 | 
			
		||||
import net.sergeych.crypto2.Multikey.Companion.anyOf
 | 
			
		||||
import net.sergeych.crypto2.Multikey.Companion.anyOfMultikeys
 | 
			
		||||
import net.sergeych.crypto2.Multikey.Companion.invoke
 | 
			
		||||
import net.sergeych.crypto2.Multikey.Companion.someOf
 | 
			
		||||
import net.sergeych.crypto2.Multikey.Companion.someOfMultikeys
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Multi-signed key.
 | 
			
		||||
 * An arbitrary combination of [VerifyingPublicKey] to implement any multiple keys scenario, like N of M,
 | 
			
		||||
 * and logical expression. Sample usage:
 | 
			
		||||
 *
 | 
			
		||||
 * ```kotlin
 | 
			
		||||
 * val k1 = SigningSecretKey.new().verifyingKey
 | 
			
		||||
 * val k2 = SigningSecretKey.new().verifyingKey
 | 
			
		||||
 * val k3 = SigningSecretKey.new().verifyingKey
 | 
			
		||||
 * val k4 = SigningSecretKey.new().verifyingKey
 | 
			
		||||
 *
 | 
			
		||||
 * val multikey = (k1 or k2) and (k3 or k4)
 | 
			
		||||
 *
 | 
			
		||||
 * val b: SealedBox = SealedBox.decode(someData)
 | 
			
		||||
 *
 | 
			
		||||
 * if( b.isSealedBy(multikey) ) {
 | 
			
		||||
 *      println("sealed box is properly sealed by a multikey")
 | 
			
		||||
 * }
 | 
			
		||||
 * ```
 | 
			
		||||
 * To build multikeys, use `and` and `or` infix operators against [VerifyingPublicKey], [Multikey], or even
 | 
			
		||||
 * [SigningSecretKey] instances, and shortcut methods:
 | 
			
		||||
 *
 | 
			
		||||
 * - [someOfMultikeys], [someOf] family for `n of M` logic
 | 
			
		||||
 * - [anyOfMultikeys], [anyOf], [allOf], and [allOfMultikeys]
 | 
			
		||||
 * - [invoke] for a single-key multikey
 | 
			
		||||
 *
 | 
			
		||||
 *  __Important__. When serializing, always serialize as root [Multikey] instance to keep
 | 
			
		||||
 * it compatible with any combination.
 | 
			
		||||
 */
 | 
			
		||||
@Serializable
 | 
			
		||||
sealed class Multikey {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check that the [keys] satisfy the condition of this instance
 | 
			
		||||
     */
 | 
			
		||||
    abstract fun check(keys: Iterable<VerifyingPublicKey>): Boolean
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check that [verifyingKeys] satisfy the multikey condition
 | 
			
		||||
     */
 | 
			
		||||
    fun check(vararg verifyingKeys: VerifyingPublicKey): Boolean = check(verifyingKeys.asIterable())
 | 
			
		||||
 | 
			
		||||
    infix fun or(mk: Multikey): Multikey = SomeOf(1, listOf(this,mk))
 | 
			
		||||
 | 
			
		||||
    infix fun or(k: VerifyingPublicKey) = SomeOf( 1, listOf(this, Multikey(k)))
 | 
			
		||||
 | 
			
		||||
    infix fun or(k: SigningSecretKey) = SomeOf( 1, listOf(this, Multikey(k.verifyingKey)))
 | 
			
		||||
 | 
			
		||||
    infix fun and(mk: Multikey): Multikey = SomeOf(2, listOf(this,mk))
 | 
			
		||||
 | 
			
		||||
    infix fun and(k: VerifyingPublicKey) = SomeOf( 2, listOf(this, Multikey(k)))
 | 
			
		||||
 | 
			
		||||
    infix fun and(k: SigningSecretKey) = SomeOf( 2, listOf(this, Multikey(k.verifyingKey)))
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Multikey instance implementing `m of N` logic against [VerifyingPublicKey] set. Do not use
 | 
			
		||||
     * it directly, use any [Multikey.someOfMultikeys] functions instead.
 | 
			
		||||
     */
 | 
			
		||||
    @Serializable
 | 
			
		||||
    @SerialName("k")
 | 
			
		||||
    class Keys internal constructor(val requiredMinimum: Int, val validKeys: Set<VerifyingPublicKey>) : Multikey() {
 | 
			
		||||
        override fun check(keys: Iterable<VerifyingPublicKey>): Boolean {
 | 
			
		||||
            var matches = 0
 | 
			
		||||
            for( signer in keys ) {
 | 
			
		||||
                if( signer in validKeys) {
 | 
			
		||||
                    if( ++matches >= requiredMinimum ) return true
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return false
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Multikey instance implementing `m of N` logic against other [Multikey] instances. Do not use
 | 
			
		||||
     * it directly, use any [Multikey.someOfMultikeys] functions instead.
 | 
			
		||||
     */
 | 
			
		||||
    @Serializable
 | 
			
		||||
    @SerialName("n")
 | 
			
		||||
    class SomeOf internal constructor(val requiredMinimum: Int,val validKeys: List<Multikey>) : Multikey() {
 | 
			
		||||
        override fun check(keys: Iterable<VerifyingPublicKey>): Boolean {
 | 
			
		||||
            var matches = 0
 | 
			
		||||
            for( k in validKeys ) {
 | 
			
		||||
                if( k.check(keys) ) {
 | 
			
		||||
                    if( ++matches >= requiredMinimum ) return true
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return false
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
 | 
			
		||||
        operator fun invoke(k: SigningSecretKey): Multikey = Keys(1, setOf( k.verifyingKey))
 | 
			
		||||
        operator fun invoke(k: VerifyingPublicKey): Multikey = Keys(1, setOf( k))
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Create a multikey instance that requires some keys from a list
 | 
			
		||||
         */
 | 
			
		||||
        fun someOf(requiredMinimum: Int, vararg keys: VerifyingPublicKey): Multikey =
 | 
			
		||||
            Keys(requiredMinimum, keys.toSet())
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Create a multikey instance that requires some keys from a list
 | 
			
		||||
         */
 | 
			
		||||
        fun someOfMultikeys(requiredMinimum: Int, vararg keys: Multikey): Multikey =
 | 
			
		||||
            SomeOf(requiredMinimum, keys.toList())
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Create a multikey instance that requires some keys from a list
 | 
			
		||||
         */
 | 
			
		||||
        fun someOfMultikeys(requiredMinimum: Int, keys: List<Multikey>): Multikey =
 | 
			
		||||
            SomeOf(requiredMinimum, keys)
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Create a multikey instance that requires some keys from a list
 | 
			
		||||
         */
 | 
			
		||||
        fun someOf(requiredMinimum: Int, keys: List<VerifyingPublicKey>): Multikey =
 | 
			
		||||
            Keys(requiredMinimum, keys.toSet())
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Create a multikey instance that requires any key from a list
 | 
			
		||||
         */
 | 
			
		||||
        fun anyOf(vararg keys: VerifyingPublicKey): Multikey =  someOf(1, *keys)
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Create a multikey instance that requires any key from a list
 | 
			
		||||
         */
 | 
			
		||||
        fun anyOfMultikeys(vararg keys: Multikey): Multikey = someOfMultikeys(1, *keys)
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Create a multikey instance that requires any key from a list
 | 
			
		||||
         */
 | 
			
		||||
        fun anyOfMultikeys(keys: List<Multikey>): Multikey = someOfMultikeys(1, keys)
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Create a multikey instance that requires any key from a list
 | 
			
		||||
         */
 | 
			
		||||
        fun anyOf(keys: List<VerifyingPublicKey>): Multikey = someOf(1, keys)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Create a multikey instance that requires all keys from a list
 | 
			
		||||
         */
 | 
			
		||||
        fun allOf(vararg keys: VerifyingPublicKey): Multikey =  someOf(keys.size, *keys)
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Create a multikey instance that requires all keys from a list
 | 
			
		||||
         */
 | 
			
		||||
        fun allOfMultikeys(vararg keys: Multikey): Multikey = someOfMultikeys(keys.size, *keys)
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Create a multikey instance that requires all keys from a list
 | 
			
		||||
         */
 | 
			
		||||
        fun allOfMultikeys(keys: List<Multikey>): Multikey = someOfMultikeys(keys.size, keys)
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Create a multikey instance that requires all keys from a list
 | 
			
		||||
         */
 | 
			
		||||
        fun allOf(keys: List<VerifyingPublicKey>): Multikey = someOf(keys.size, keys)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -27,11 +27,22 @@ import net.sergeych.bipack.decodeFromBipack
 | 
			
		||||
@Serializable
 | 
			
		||||
class SealedBox(
 | 
			
		||||
    val message: UByteArray,
 | 
			
		||||
    private val seals: List<Seal>,
 | 
			
		||||
    /**
 | 
			
		||||
     * [Seal] instance representing _correct signatures_ of this box. Note that if the box
 | 
			
		||||
     * is constructed (deserialized, etc) successfully, all seals are ok. Initial check
 | 
			
		||||
     * of signatures could be bypassed by setting [checkOnInit] to false, which should
 | 
			
		||||
     * be avoided.
 | 
			
		||||
     */
 | 
			
		||||
    val seals: List<Seal>,
 | 
			
		||||
    @Transient
 | 
			
		||||
    private val checkOnInit: Boolean = true
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Extract [VerifyingPublicKey] from [seals].
 | 
			
		||||
     */
 | 
			
		||||
    val signedByKeys: List<VerifyingPublicKey> by lazy { seals.map { it.publicKey } }
 | 
			
		||||
 | 
			
		||||
    @Suppress("unused")
 | 
			
		||||
    constructor(message: UByteArray, vararg keys: SigningKey) :
 | 
			
		||||
            this(message, keys.map { it.seal(message) } )
 | 
			
		||||
@ -61,6 +72,12 @@ class SealedBox(
 | 
			
		||||
        return seals.any { it.publicKey == publicKey }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks that the box is signed by enough keys to satisfy the given [Multikey].
 | 
			
		||||
     */
 | 
			
		||||
    @Suppress("unused")
 | 
			
		||||
    fun isSealedBy(multikey: Multikey) = multikey.check(signedByKeys)
 | 
			
		||||
 | 
			
		||||
    init {
 | 
			
		||||
        if (seals.isEmpty()) throw IllegalArgumentException("there should be at least one seal")
 | 
			
		||||
        if (checkOnInit) {
 | 
			
		||||
 | 
			
		||||
@ -33,6 +33,32 @@ class SigningSecretKey(
 | 
			
		||||
    override val label: String
 | 
			
		||||
        get() = "sig"
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a [Multikey] that requires presence of this or [other] key
 | 
			
		||||
     */
 | 
			
		||||
    infix fun or(other: VerifyingPublicKey) = Multikey(this) or other
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a [Multikey] that requires presence of this or [other] key
 | 
			
		||||
     */
 | 
			
		||||
    infix fun or(other: SigningSecretKey) = Multikey(this) or other
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a [Multikey] that requires presence of this or [other] key
 | 
			
		||||
     */
 | 
			
		||||
    infix fun or(other: Multikey) = Multikey(this) or other
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a [Multikey] that requires presence of this and [other] key
 | 
			
		||||
     */
 | 
			
		||||
    infix fun and(other: VerifyingPublicKey) = Multikey(this) and other
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a [Multikey] that requires presence of this and [other] key
 | 
			
		||||
     */
 | 
			
		||||
    infix fun and(other: SigningSecretKey) = Multikey(this) and other
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a [Multikey] that requires presence of this and [other] key
 | 
			
		||||
     */
 | 
			
		||||
    infix fun and(other: Multikey) = Multikey(this) and other
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
 | 
			
		||||
        data class SigningKeyPair(val secretKey: SigningSecretKey, val publicKey: VerifyingPublicKey)
 | 
			
		||||
 | 
			
		||||
@ -26,4 +26,32 @@ class VerifyingPublicKey(override val keyBytes: UByteArray) : UniversalKey(), Ve
 | 
			
		||||
    override val magic: KeysmagicNumber = KeysmagicNumber.defaultVerifying
 | 
			
		||||
 | 
			
		||||
    override val id by lazy { KeyId(magic, keyBytes, null, true) }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a [Multikey] that requires presence of this or [other] key
 | 
			
		||||
     */
 | 
			
		||||
    infix fun or(other: VerifyingPublicKey) = Multikey(this) or other
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a [Multikey] that requires presence of this or [other] key
 | 
			
		||||
     */
 | 
			
		||||
    infix fun or(other: SigningSecretKey) = Multikey(this) or other
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a [Multikey] that requires presence of this or [other] key
 | 
			
		||||
     */
 | 
			
		||||
    infix fun or(other: Multikey) = Multikey(this) or other
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a [Multikey] that requires presence of this and [other]
 | 
			
		||||
     */
 | 
			
		||||
    infix fun and(other: VerifyingPublicKey) = Multikey(this) and other
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a [Multikey] that requires presence of this and [other]
 | 
			
		||||
     */
 | 
			
		||||
    infix fun and(other: SigningSecretKey) = Multikey(this) and other
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a [Multikey] that requires presence of this and [other]
 | 
			
		||||
     */
 | 
			
		||||
    infix fun and(other: Multikey) = Multikey(this) and other
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -276,4 +276,72 @@ class KeysTest {
 | 
			
		||||
        // and restored from id should be the same:
 | 
			
		||||
        assertEquals( k.verifyingKey, dk2.id.id.asVerifyingKey)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun multiKeyTestSom() = runTest {
 | 
			
		||||
        initCrypto()
 | 
			
		||||
        val k1 = SigningSecretKey.new()
 | 
			
		||||
        val k2 = SigningSecretKey.new()
 | 
			
		||||
        val k3 = SigningSecretKey.new()
 | 
			
		||||
        val k4 = SigningSecretKey.new()
 | 
			
		||||
        val k5 = SigningSecretKey.new()
 | 
			
		||||
//        val k6 = SigningSecretKey.new()
 | 
			
		||||
        val mk: Multikey = Multikey.Keys(1, setOf(k1.verifyingKey))
 | 
			
		||||
        val mk23: Multikey = Multikey.Keys(2, setOf(k1.verifyingKey, k2.verifyingKey, k3.verifyingKey))
 | 
			
		||||
        val mk13: Multikey = Multikey.Keys(1, setOf(k1.verifyingKey, k2.verifyingKey, k3.verifyingKey))
 | 
			
		||||
 | 
			
		||||
        assertTrue { mk.check(k1.verifyingKey) }
 | 
			
		||||
        assertFalse { mk.check(k2.verifyingKey) }
 | 
			
		||||
 | 
			
		||||
        assertTrue { mk23.check(k1.verifyingKey, k2.verifyingKey, k4.verifyingKey) }
 | 
			
		||||
        assertTrue { mk23.check(k3.verifyingKey, k2.verifyingKey, k4.verifyingKey) }
 | 
			
		||||
        assertFalse { mk23.check(k4.verifyingKey, k2.verifyingKey, k5.verifyingKey) }
 | 
			
		||||
        assertTrue { mk13.check(k4.verifyingKey, k2.verifyingKey, k5.verifyingKey) }
 | 
			
		||||
 | 
			
		||||
        println(pack(mk23).toDump())
 | 
			
		||||
        println(pack(mk23).size)
 | 
			
		||||
 | 
			
		||||
        val smk23: Multikey = Multikey.someOf(2,  k1.verifyingKey, k2.verifyingKey, k3.verifyingKey)
 | 
			
		||||
//        val smk13: Multikey = Multikey.Keys(1, setOf(k1.verifyingKey, k2.verifyingKey, k3.verifyingKey))
 | 
			
		||||
 | 
			
		||||
        assertTrue { smk23.check(k1.verifyingKey, k2.verifyingKey, k4.verifyingKey) }
 | 
			
		||||
        assertTrue { smk23.check(k3.verifyingKey, k2.verifyingKey, k4.verifyingKey) }
 | 
			
		||||
        assertFalse { smk23.check(k4.verifyingKey, k2.verifyingKey, k5.verifyingKey) }
 | 
			
		||||
//        assertTrue { smk13.check(k4.verifyingKey, k2.verifyingKey, k5.verifyingKey) }
 | 
			
		||||
 | 
			
		||||
        println(pack(smk23).toDump())
 | 
			
		||||
        println(pack(smk23).size)
 | 
			
		||||
 | 
			
		||||
        val s1 = k1 or k2 or k3
 | 
			
		||||
        println(pack(s1).toDump())
 | 
			
		||||
        println(pack(s1).size)
 | 
			
		||||
        assertTrue { s1.check(k1.verifyingKey, k2.verifyingKey, k3.verifyingKey) }
 | 
			
		||||
        assertTrue { s1.check(k1.verifyingKey) }
 | 
			
		||||
        assertTrue { s1.check(k2.verifyingKey) }
 | 
			
		||||
        assertTrue { s1.check(k3.verifyingKey) }
 | 
			
		||||
        assertFalse { s1.check(k4.verifyingKey) }
 | 
			
		||||
 | 
			
		||||
        val s2 = (k1 or k2) and k3
 | 
			
		||||
        println(pack(s2).toDump())
 | 
			
		||||
        println(pack(s2).size)
 | 
			
		||||
        assertTrue { s2.check(k1.verifyingKey, k3.verifyingKey) }
 | 
			
		||||
        assertTrue { s2.check(k2.verifyingKey, k3.verifyingKey) }
 | 
			
		||||
        assertTrue { s2.check(k1.verifyingKey, k2.verifyingKey, k3.verifyingKey) }
 | 
			
		||||
        assertFalse { s2.check(k4.verifyingKey) }
 | 
			
		||||
        assertFalse { s2.check(k1.verifyingKey) }
 | 
			
		||||
        assertFalse { s2.check(k2.verifyingKey) }
 | 
			
		||||
        assertFalse { s2.check(k3.verifyingKey) }
 | 
			
		||||
        assertFalse { s2.check(k1.verifyingKey, k2.verifyingKey) }
 | 
			
		||||
 | 
			
		||||
        val s3 = (k1 and k2) or k3
 | 
			
		||||
        println(pack(s3).toDump())
 | 
			
		||||
        println(pack(s3).size)
 | 
			
		||||
        assertTrue { s3.check(k1.verifyingKey, k3.verifyingKey) }
 | 
			
		||||
        assertTrue { s3.check(k3.verifyingKey) }
 | 
			
		||||
        assertTrue { s3.check(k2.verifyingKey, k1.verifyingKey) }
 | 
			
		||||
        assertFalse { s3.check(k1.verifyingKey) }
 | 
			
		||||
        assertFalse { s3.check(k2.verifyingKey) }
 | 
			
		||||
        assertFalse { s3.check(k1.verifyingKey, k4.verifyingKey) }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user