refactoring in progress
This commit is contained in:
		
							parent
							
								
									a1f984c4e6
								
							
						
					
					
						commit
						7eeb780bdb
					
				@ -123,8 +123,8 @@ object Asymmetric {
 | 
			
		||||
    @Serializable
 | 
			
		||||
    class PublicKey(val keyBytes: UByteArray) {
 | 
			
		||||
 | 
			
		||||
        val tag: KeyTag by lazy {
 | 
			
		||||
            KeyTag(KeysMagickNumbers.defaultAssymmetric, blake2b(keyBytes))
 | 
			
		||||
        val tag: KeyId by lazy {
 | 
			
		||||
            KeyId(KeysMagickNumbers.defaultAssymmetric, blake2b(keyBytes))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        override fun equals(other: Any?): Boolean {
 | 
			
		||||
@ -250,7 +250,7 @@ object Asymmetric {
 | 
			
		||||
            return message.decrypt(this)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        override val tag: KeyTag by lazy { publicKey.tag }
 | 
			
		||||
        override val id: KeyId by lazy { publicKey.tag }
 | 
			
		||||
 | 
			
		||||
        override val nonceBytesLength: Int
 | 
			
		||||
            get() = 0
 | 
			
		||||
 | 
			
		||||
@ -143,7 +143,7 @@ sealed class Container {
 | 
			
		||||
    @Serializable
 | 
			
		||||
    @SerialName("1")
 | 
			
		||||
    internal class Single(
 | 
			
		||||
        val keyTag: KeyTag, val encryptedMessage: UByteArray,
 | 
			
		||||
        val keyId: KeyId, val encryptedMessage: UByteArray,
 | 
			
		||||
        @Transient private val creationData: UByteArray? = null,
 | 
			
		||||
        @Transient private val reEncryptionKey: EncryptingKey? = null,
 | 
			
		||||
        @Transient private var encryptionPair: AsymmetricEncryptionPair? = null,
 | 
			
		||||
@ -158,8 +158,8 @@ sealed class Container {
 | 
			
		||||
 | 
			
		||||
        override fun decryptWith(keyRing: UniversalRing): UByteArray? {
 | 
			
		||||
            decryptedData?.let { return it }
 | 
			
		||||
            for (k in keyRing) {
 | 
			
		||||
                if (k.tag == keyTag) {
 | 
			
		||||
            for (k in keyRing.decryptingKeys) {
 | 
			
		||||
                if (k.id == keyId) {
 | 
			
		||||
                    kotlin.runCatching { k.decrypt(encryptedMessage) }.getOrNull()?.let {
 | 
			
		||||
                        decryptedData = it
 | 
			
		||||
                        decryptedWithKey = k
 | 
			
		||||
@ -226,9 +226,9 @@ sealed class Container {
 | 
			
		||||
        @Transient internal var knownPlainData: UByteArray? = null,
 | 
			
		||||
        ) : Container() {
 | 
			
		||||
        @Serializable
 | 
			
		||||
        class EncryptedKey(val tag: KeyTag, val cipherData: UByteArray) {
 | 
			
		||||
        class EncryptedKey(val tag: KeyId, val cipherData: UByteArray) {
 | 
			
		||||
            constructor(key: EncryptingKey, encodeMainKey: UByteArray) :
 | 
			
		||||
                    this(key.tag, key.encrypt(encodeMainKey))
 | 
			
		||||
                    this(key.id, key.encrypt(encodeMainKey))
 | 
			
		||||
 | 
			
		||||
            constructor(sender: Asymmetric.SecretKey?, recipient: Asymmetric.PublicKey, encodeMainKey: UByteArray) :
 | 
			
		||||
                    this(
 | 
			
		||||
@ -246,8 +246,8 @@ sealed class Container {
 | 
			
		||||
 | 
			
		||||
        override fun decryptWith(keyRing: UniversalRing): UByteArray? {
 | 
			
		||||
            decryptedData?.let { return it }
 | 
			
		||||
            for (key in keyRing) {
 | 
			
		||||
                val tag = key.tag
 | 
			
		||||
            for (key in keyRing.decryptingKeys) {
 | 
			
		||||
                val tag = key.id
 | 
			
		||||
                for (encryptedKey in encryptedKeys) {
 | 
			
		||||
                    if (tag == encryptedKey.tag) {
 | 
			
		||||
                        kotlin.runCatching {
 | 
			
		||||
@ -384,7 +384,7 @@ sealed class Container {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private fun createSingle() = plainKeys.firstOrNull()?.let {
 | 
			
		||||
                Single(it.tag, it.encrypt(plainData, fillRange), plainData, reEncryptionKey = it)
 | 
			
		||||
                Single(it.id, it.encrypt(plainData, fillRange), plainData, reEncryptionKey = it)
 | 
			
		||||
            } ?: run {
 | 
			
		||||
                val pair = keyPairs.first()
 | 
			
		||||
                val (sk, pk) = pair
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,7 @@ interface DecryptingKey : NonceBased {
 | 
			
		||||
 | 
			
		||||
    fun decryptString(cipherData: UByteArray): String = decrypt(cipherData).decodeFromUByteArray()
 | 
			
		||||
 | 
			
		||||
    val tag: KeyTag
 | 
			
		||||
    val id: KeyId
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -27,7 +27,7 @@ interface EncryptingKey : NonceBased {
 | 
			
		||||
    fun encrypt(plainText: String,randomFill: IntRange? = null): UByteArray =
 | 
			
		||||
        encrypt(plainText.encodeToUByteArray(),randomFill)
 | 
			
		||||
 | 
			
		||||
    val tag: KeyTag
 | 
			
		||||
    val id: KeyId
 | 
			
		||||
 | 
			
		||||
    fun encryptWithNonce(plainData: UByteArray, nonce: UByteArray, randomFill: IntRange? = null): UByteArray
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -7,13 +7,13 @@ import kotlinx.serialization.Serializable
 | 
			
		||||
 * containers to fast find a proper key
 | 
			
		||||
 */
 | 
			
		||||
@Serializable
 | 
			
		||||
data class KeyTag(val id: BinaryId,val kdp: KeyDerivationParams?=null ) {
 | 
			
		||||
data class KeyId(val id: BinaryId, val kdp: KeyDerivationParams?=null ) {
 | 
			
		||||
 | 
			
		||||
    val tag: UByteArray by lazy { id.id }
 | 
			
		||||
 | 
			
		||||
    override fun equals(other: Any?): Boolean {
 | 
			
		||||
        if (this === other) return true
 | 
			
		||||
        if (other !is KeyTag) return false
 | 
			
		||||
        if (other !is KeyId) return false
 | 
			
		||||
        return id == other.id
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@ enum class KeysMagickNumbers(val number: Int) {
 | 
			
		||||
    defaultAssymmetric(0),
 | 
			
		||||
    defaultSymmetric(1),
 | 
			
		||||
    defaultSession(2),
 | 
			
		||||
    defaultSigning(3),
 | 
			
		||||
    ;
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
 | 
			
		||||
@ -47,13 +47,13 @@ class SafeKeyExchange {
 | 
			
		||||
        @Suppress("unused")
 | 
			
		||||
        val sessionTag: UByteArray by lazy {
 | 
			
		||||
            if (!isClient)
 | 
			
		||||
                blake2b(tag.tag + tag.tag)
 | 
			
		||||
                blake2b(id.tag + id.tag)
 | 
			
		||||
            else
 | 
			
		||||
                blake2b(tag.tag + tag.tag)
 | 
			
		||||
                blake2b(id.tag + id.tag)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        override val tag: KeyTag
 | 
			
		||||
            get() = if( isClient ) sendingKey.tag else receivingKey.tag
 | 
			
		||||
        override val id: KeyId
 | 
			
		||||
            get() = if( isClient ) sendingKey.id else receivingKey.id
 | 
			
		||||
 | 
			
		||||
        override fun equals(other: Any?): Boolean {
 | 
			
		||||
            if (this === other) return true
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,7 @@ import net.sergeych.utools.now
 | 
			
		||||
 */
 | 
			
		||||
@Serializable
 | 
			
		||||
class Seal(
 | 
			
		||||
    val publicKey: SigningKey.Public,
 | 
			
		||||
    val publicKey: Signing.PublicKey,
 | 
			
		||||
    val signature: UByteArray,
 | 
			
		||||
    val nonce: UByteArray?,
 | 
			
		||||
    val createdAt: Instant,
 | 
			
		||||
@ -95,7 +95,7 @@ class Seal(
 | 
			
		||||
         * Seal [message] with a [key].
 | 
			
		||||
         *
 | 
			
		||||
         * Seals are kotlinx-serializable and can be used
 | 
			
		||||
         * to check the authenticity of the arbitrary [message] using a public key, [SigningKey.Public]
 | 
			
		||||
         * to check the authenticity of the arbitrary [message] using a public key, [Signing.PublicKey]
 | 
			
		||||
         * instance, using public-key signing algorithms.
 | 
			
		||||
         *
 | 
			
		||||
         * 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.
 | 
			
		||||
         */
 | 
			
		||||
        fun create(
 | 
			
		||||
            key: SigningKey.Secret,
 | 
			
		||||
            key: Signing.SecretKey,
 | 
			
		||||
            message: UByteArray,
 | 
			
		||||
            createdAt: Instant = now(),
 | 
			
		||||
            expiresAt: Instant? = null,
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,7 @@ class SealedBox(
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    @Suppress("unused")
 | 
			
		||||
    constructor(message: UByteArray, vararg keys: SigningKey.Secret) :
 | 
			
		||||
    constructor(message: UByteArray, vararg keys: Signing.SecretKey) :
 | 
			
		||||
            this(message, keys.map { it.seal(message) } )
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -38,7 +38,7 @@ class SealedBox(
 | 
			
		||||
     * key, or return unchanged (same) object if it is already signed by this key; you
 | 
			
		||||
     * _can't assume it always returns a copied object!_
 | 
			
		||||
     */
 | 
			
		||||
    operator fun plus(key: SigningKey.Secret): SealedBox =
 | 
			
		||||
    operator fun plus(key: Signing.SecretKey): SealedBox =
 | 
			
		||||
        if (key.publicKey in this) this
 | 
			
		||||
        else SealedBox(message, seals + key.seal(message),false)
 | 
			
		||||
 | 
			
		||||
@ -46,7 +46,7 @@ class SealedBox(
 | 
			
		||||
     * Add expiring seal, otherwise use [plus]. Overrides exising seal for [key]
 | 
			
		||||
     * if present:
 | 
			
		||||
     */
 | 
			
		||||
    fun addSeal(key: SigningKey.Secret,expresAt: Instant): SealedBox {
 | 
			
		||||
    fun addSeal(key: Signing.SecretKey, expresAt: Instant): SealedBox {
 | 
			
		||||
        val filtered = seals.filter { it.publicKey != key.publicKey }
 | 
			
		||||
        return SealedBox(message, filtered + key.seal(message, expresAt), false)
 | 
			
		||||
    }
 | 
			
		||||
@ -54,7 +54,7 @@ class SealedBox(
 | 
			
		||||
    /**
 | 
			
		||||
     * Check that it is signed with a specified key.
 | 
			
		||||
     */
 | 
			
		||||
    operator fun contains(publicKey: SigningKey.Public): Boolean {
 | 
			
		||||
    operator fun contains(publicKey: Signing.PublicKey): Boolean {
 | 
			
		||||
        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.
 | 
			
		||||
         * @throws IllegalArgumentException if keys are not specified.
 | 
			
		||||
         */
 | 
			
		||||
        fun create(data: UByteArray, vararg keys: SigningKey.Secret): SealedBox {
 | 
			
		||||
        fun create(data: UByteArray, vararg keys: Signing.SecretKey): SealedBox {
 | 
			
		||||
            return SealedBox(data, keys.map { it.seal(data) }, false)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -5,9 +5,24 @@ import com.ionspin.kotlin.crypto.signature.Signature
 | 
			
		||||
import kotlinx.datetime.Instant
 | 
			
		||||
import kotlinx.serialization.SerialName
 | 
			
		||||
import kotlinx.serialization.Serializable
 | 
			
		||||
import net.sergeych.crypto2.SigningKey.Companion.pair
 | 
			
		||||
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
 | 
			
		||||
@ -16,11 +31,13 @@ import net.sergeych.utools.now
 | 
			
		||||
 * Use [pair] to create new keys.
 | 
			
		||||
 */
 | 
			
		||||
@Serializable
 | 
			
		||||
sealed class SigningKey {
 | 
			
		||||
sealed class Signing {
 | 
			
		||||
    abstract val id: KeyId
 | 
			
		||||
 | 
			
		||||
    abstract val packed: UByteArray
 | 
			
		||||
 | 
			
		||||
    override fun equals(other: Any?): Boolean {
 | 
			
		||||
        return other is SigningKey && other.packed contentEquals packed
 | 
			
		||||
        return other is Signing && other.packed contentEquals packed
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun hashCode(): Int {
 | 
			
		||||
@ -34,11 +51,11 @@ sealed class SigningKey {
 | 
			
		||||
     */
 | 
			
		||||
    @Serializable
 | 
			
		||||
    @SerialName("p")
 | 
			
		||||
    class Public(override val packed: UByteArray) : SigningKey() {
 | 
			
		||||
    class PublicKey(override val packed: UByteArray) : Signing(), VerifyingKey {
 | 
			
		||||
        /**
 | 
			
		||||
         * Verify the signature and return true if it is correct.
 | 
			
		||||
         */
 | 
			
		||||
        fun verify(signature: UByteArray, message: UByteArray): Boolean = try {
 | 
			
		||||
        override fun verify(signature: UByteArray, message: UByteArray): Boolean = try {
 | 
			
		||||
            Signature.verifyDetached(signature, message, packed)
 | 
			
		||||
            true
 | 
			
		||||
        } catch (_: InvalidSignatureException) {
 | 
			
		||||
@ -47,6 +64,9 @@ sealed class SigningKey {
 | 
			
		||||
 | 
			
		||||
        override fun toString(): String = "Pub:${super.toString()}"
 | 
			
		||||
 | 
			
		||||
        override val id: KeyId by lazy {
 | 
			
		||||
            KeyId(KeysMagickNumbers.defaultSigning, packed)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -54,27 +74,29 @@ sealed class SigningKey {
 | 
			
		||||
     */
 | 
			
		||||
    @Serializable
 | 
			
		||||
    @SerialName("s")
 | 
			
		||||
    class Secret(override val packed: UByteArray) : SigningKey() {
 | 
			
		||||
    class SecretKey(override val packed: UByteArray) : Signing(), SigningKey {
 | 
			
		||||
 | 
			
		||||
        val publicKey: Public by lazy {
 | 
			
		||||
            Public(Signature.ed25519SkToPk(packed))
 | 
			
		||||
        override val publicKey: PublicKey by lazy {
 | 
			
		||||
            PublicKey(Signature.ed25519SkToPk(packed))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fun sign(message: UByteArray): UByteArray = Signature.detached(message, packed)
 | 
			
		||||
        override fun sign(message: UByteArray): UByteArray = Signature.detached(message, packed)
 | 
			
		||||
 | 
			
		||||
        fun seal(message: UByteArray, expiresAt: Instant? = null): Seal =
 | 
			
		||||
        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: Secret, val publicKey: Public)
 | 
			
		||||
        data class Pair(val secretKey: SecretKey, val publicKey: PublicKey)
 | 
			
		||||
 | 
			
		||||
        fun pair(): Pair {
 | 
			
		||||
            val p = Signature.keypair()
 | 
			
		||||
            return Pair(Secret(p.secretKey), Public(p.publicKey))
 | 
			
		||||
            return Pair(SecretKey(p.secretKey), PublicKey(p.publicKey))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -37,7 +37,7 @@ class SymmetricKey(
 | 
			
		||||
 | 
			
		||||
    override val nonceBytesLength: Int = nonceByteLength
 | 
			
		||||
 | 
			
		||||
    override val tag by lazy { KeyTag(KeysMagickNumbers.defaultSymmetric,blake2b3l(keyBytes)) }
 | 
			
		||||
    override val id by lazy { KeyId(KeysMagickNumbers.defaultSymmetric,blake2b3l(keyBytes)) }
 | 
			
		||||
 | 
			
		||||
    override fun decryptWithNonce(cipherData: UByteArray, nonce: UByteArray): UByteArray =
 | 
			
		||||
        protectDecryption {
 | 
			
		||||
 | 
			
		||||
@ -5,45 +5,79 @@ import kotlinx.serialization.Serializable
 | 
			
		||||
import kotlinx.serialization.Transient
 | 
			
		||||
 | 
			
		||||
@Serializable
 | 
			
		||||
sealed class UniversalKey : DecryptingKey {
 | 
			
		||||
 | 
			
		||||
//    abstract val tag: KeyTag
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
sealed class UniversalKey {
 | 
			
		||||
    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
 | 
			
		||||
    @SerialName("sy")
 | 
			
		||||
    @SerialName("sym")
 | 
			
		||||
    data class Symmetric(val key: SymmetricKey) : UniversalKey(), EncryptingKey by key, DecryptingKey by key {
 | 
			
		||||
        @Transient
 | 
			
		||||
        override val tag: KeyTag = key.tag
 | 
			
		||||
        override val id: KeyId = key.id
 | 
			
		||||
 | 
			
		||||
        @Transient
 | 
			
		||||
        override val nonceBytesLength: Int = key.nonceBytesLength
 | 
			
		||||
 | 
			
		||||
        override fun toString() = "U.Sym:$tag"
 | 
			
		||||
        override fun toString() = "U.Sym:$id"
 | 
			
		||||
 | 
			
		||||
        @Transient
 | 
			
		||||
        override val canDecrypt: Boolean = true
 | 
			
		||||
        @Transient
 | 
			
		||||
        override val canEncrypt: Boolean = true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Serializable
 | 
			
		||||
    @SerialName("sn")
 | 
			
		||||
    @SerialName("ssn")
 | 
			
		||||
    data class Session(val key: SafeKeyExchange.SessionKey) : UniversalKey(), EncryptingKey by key,
 | 
			
		||||
        DecryptingKey by key {
 | 
			
		||||
        @Transient
 | 
			
		||||
        override val tag: KeyTag = key.tag
 | 
			
		||||
        override val id: KeyId = key.id
 | 
			
		||||
        @Transient
 | 
			
		||||
        override val nonceBytesLength: Int = key.nonceBytesLength
 | 
			
		||||
        @Transient
 | 
			
		||||
        override val canDecrypt: Boolean = true
 | 
			
		||||
        @Transient
 | 
			
		||||
        override val canEncrypt: Boolean = true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Serializable
 | 
			
		||||
    @SerialName("se")
 | 
			
		||||
    @SerialName("sec")
 | 
			
		||||
    data class Secret(val key: Asymmetric.SecretKey) : UniversalKey(), DecryptingKey by key {
 | 
			
		||||
        override val tag: KeyTag by lazy { key.tag }
 | 
			
		||||
        override fun toString() = "U.Sec:$tag"
 | 
			
		||||
        override val id: KeyId by lazy { key.id }
 | 
			
		||||
        override fun toString() = "U.Sec:$id"
 | 
			
		||||
        @Transient
 | 
			
		||||
        override val canDecrypt: Boolean = true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Serializable
 | 
			
		||||
    @SerialName("sig")
 | 
			
		||||
    data class Signing(val key: net.sergeych.crypto2.Signing.SecretKey) : UniversalKey() {
 | 
			
		||||
        override val id: KeyId by lazy { key.id }
 | 
			
		||||
        override fun toString() = "U.Sig:$id"
 | 
			
		||||
        @Transient
 | 
			
		||||
        override val canDecrypt: Boolean = true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Serializable
 | 
			
		||||
    @SerialName("ver")
 | 
			
		||||
    data class Verifying(val key: net.sergeych.crypto2.Signing.PublicKey) : UniversalKey() {
 | 
			
		||||
        override val id: KeyId by lazy { key.id }
 | 
			
		||||
        override fun toString() = "U.Sig:$id"
 | 
			
		||||
        @Transient
 | 
			
		||||
        override val canDecrypt: Boolean = true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        fun from(key: DecryptingKey) =
 | 
			
		||||
        fun from(key: DecryptingKey): UniversalKey =
 | 
			
		||||
            when (key) {
 | 
			
		||||
                is UniversalKey -> key
 | 
			
		||||
                is Asymmetric.SecretKey -> Secret(key)
 | 
			
		||||
 | 
			
		||||
@ -1,48 +1,91 @@
 | 
			
		||||
package net.sergeych.crypto2
 | 
			
		||||
 | 
			
		||||
import kotlinx.serialization.Serializable
 | 
			
		||||
import kotlinx.serialization.Transient
 | 
			
		||||
 | 
			
		||||
@Serializable
 | 
			
		||||
class UniversalRing(
 | 
			
		||||
    private val keys: Collection<UniversalKey>
 | 
			
		||||
): Collection<UniversalKey> by keys {
 | 
			
		||||
    constructor(vararg keys: UniversalKey) : this(keys.toSet())
 | 
			
		||||
    constructor(vararg keys: DecryptingKey) : this(keys.map { UniversalKey.from(it) }.toSet())
 | 
			
		||||
    @Transient
 | 
			
		||||
    val keySet = if( keys is Set<UniversalKey> ) keys else keys.toSet()
 | 
			
		||||
    private val keyWithTags: Map<UniversalKey,Set<String>>
 | 
			
		||||
) {
 | 
			
		||||
    val decryptingKeys: Set<DecryptingKey> by lazy {
 | 
			
		||||
        keyWithTags.keys.mapNotNull { it as? DecryptingKey }.toSet()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private val byTag by lazy { keySet.associateBy { it.tag } }
 | 
			
		||||
    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>)
 | 
			
		||||
            : this(keyTags.associate { it.first to setOf(it.second) })
 | 
			
		||||
 | 
			
		||||
    operator fun get(keyTag: KeyTag): UniversalKey? = byTag[keyTag]
 | 
			
		||||
    private val byId by lazy { keyWithTags.keys.associateBy { it.id } }
 | 
			
		||||
    private val byIdWithTags by lazy { keyWithTags.entries.associate { it.key.id to (it.key to it.value) } }
 | 
			
		||||
 | 
			
		||||
    override operator fun contains(element: UniversalKey): Boolean = byTag.containsKey(element.tag)
 | 
			
		||||
    operator fun get(keyId: KeyId): UniversalKey? = byId[keyId]
 | 
			
		||||
 | 
			
		||||
    fun getTags(key: UniversalKey): Set<String>? = keyWithTags[key]
 | 
			
		||||
 | 
			
		||||
    fun keyWithTags(keyId: KeyId?): Pair<UniversalKey,Set<String>>? = byIdWithTags[keyId]
 | 
			
		||||
 | 
			
		||||
    operator fun contains(element: UniversalKey): Boolean = byId.containsKey(element.id)
 | 
			
		||||
 | 
			
		||||
    operator fun plus(key: UniversalKey): UniversalRing =
 | 
			
		||||
        if( key in this ) this else UniversalRing(keySet + key )
 | 
			
		||||
        if( key in this ) this else UniversalRing(keyWithTags + (key to setOf()) )
 | 
			
		||||
 | 
			
		||||
    operator fun plus(keyTag: Pair<UniversalKey,String>): UniversalRing =
 | 
			
		||||
        if( keyTag.first in this )
 | 
			
		||||
            addTags(keyTag.first,keyTag.second)
 | 
			
		||||
        else UniversalRing(keyWithTags + keyWithTags)
 | 
			
		||||
 | 
			
		||||
    fun add(key: UniversalKey, vararg tags: String): UniversalRing =
 | 
			
		||||
        UniversalRing(keyWithTags + (key to tags.toSet()) )
 | 
			
		||||
 | 
			
		||||
    fun add(key: UniversalKey, tags: Collection<String>): UniversalRing =
 | 
			
		||||
        UniversalRing(keyWithTags + (key to tags.toSet()) )
 | 
			
		||||
 | 
			
		||||
    fun addTags(key: UniversalKey,tags: Set<String>): UniversalRing {
 | 
			
		||||
        val kt1 = keyWithTags.toMutableMap()
 | 
			
		||||
        kt1[key]?.let {
 | 
			
		||||
            kt1[key] = it + tags
 | 
			
		||||
        } ?: run {
 | 
			
		||||
            kt1[key] = tags
 | 
			
		||||
        }
 | 
			
		||||
        return UniversalRing(kt1)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun addTags(key: UniversalKey,vararg tags: String): UniversalRing =
 | 
			
		||||
        addTags(key,tags.toSet())
 | 
			
		||||
 | 
			
		||||
    operator fun minus(key: UniversalKey): UniversalRing =
 | 
			
		||||
        if( key in this ) UniversalRing(keySet.filter { it.tag != key.tag }) else this
 | 
			
		||||
        if( key in this ) UniversalRing(keyWithTags.filter { it.key != key }) else this
 | 
			
		||||
 | 
			
		||||
    operator fun minus(keyTag: KeyTag): UniversalRing =
 | 
			
		||||
        if( keyTag in byTag ) UniversalRing(keySet.filter { it.tag != keyTag }) 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 {
 | 
			
		||||
        println("compare1\r\n")
 | 
			
		||||
        if (this === other) return true
 | 
			
		||||
        println("compare2\r\n")
 | 
			
		||||
        if (other !is UniversalRing) return false
 | 
			
		||||
 | 
			
		||||
        println("compare2 ${size == other.size}: $size : ${other.size} | ${keySet == other.keySet}\r\n")
 | 
			
		||||
        return size == other.size && keySet.containsAll(other.keySet)
 | 
			
		||||
        return keyWithTags == other.keyWithTags
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun toString(): String {
 | 
			
		||||
        return "Kr[${keys.joinToString(",")}]"
 | 
			
		||||
        val ss = keyWithTags.entries
 | 
			
		||||
            .joinToString(","){"${it.value.joinToString{ ":" }}:${it.key}"}
 | 
			
		||||
        return "Kr[$ss]"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun hashCode(): Int {
 | 
			
		||||
        return keySet.hashCode()
 | 
			
		||||
        return keyWithTags.hashCode()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    infix fun equalKeys(other: UniversalRing): Boolean = keyWithTags.keys == other.keyWithTags.keys
 | 
			
		||||
 | 
			
		||||
    fun removeTags(key: UniversalKey, vararg tags: String): UniversalRing = removeTags(key, tags.toSet())
 | 
			
		||||
 | 
			
		||||
    fun removeTags(key: UniversalKey, tags: Set<String>): UniversalRing {
 | 
			
		||||
        val kt1 = keyWithTags.toMutableMap()
 | 
			
		||||
        kt1[key]?.let {
 | 
			
		||||
            kt1[key] = it - tags
 | 
			
		||||
        }
 | 
			
		||||
        return UniversalRing(kt1)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -13,11 +13,11 @@ class KeysTest {
 | 
			
		||||
    @Test
 | 
			
		||||
    fun testSigningCreationAndMap() = runTest {
 | 
			
		||||
        initCrypto()
 | 
			
		||||
        val (stk,pbk) = SigningKey.pair()
 | 
			
		||||
        val (stk,pbk) = Signing.pair()
 | 
			
		||||
 | 
			
		||||
        val x = mapOf( stk to "STK!", pbk to "PBK!")
 | 
			
		||||
        assertEquals("STK!", x[stk])
 | 
			
		||||
        val s1 = SigningKey.Secret(stk.packed)
 | 
			
		||||
        val s1 = Signing.SecretKey(stk.packed)
 | 
			
		||||
        assertEquals(stk, s1)
 | 
			
		||||
        assertEquals("STK!", x[s1])
 | 
			
		||||
        assertEquals("PBK!", x[pbk])
 | 
			
		||||
@ -29,8 +29,8 @@ class KeysTest {
 | 
			
		||||
 | 
			
		||||
        data1[0] = 0x01u
 | 
			
		||||
        assertFalse(s.isValid(data1))
 | 
			
		||||
        val p2 = SigningKey.pair()
 | 
			
		||||
        val p3 = SigningKey.pair()
 | 
			
		||||
        val p2 = Signing.pair()
 | 
			
		||||
        val p3 = Signing.pair()
 | 
			
		||||
 | 
			
		||||
        val ms = SealedBox.create(data, s1) + p2.secretKey
 | 
			
		||||
 | 
			
		||||
@ -50,7 +50,7 @@ class KeysTest {
 | 
			
		||||
    fun testNonDeterministicSeals() = runTest {
 | 
			
		||||
        initCrypto()
 | 
			
		||||
        val data = "Welcome to the Miami, bitch!".encodeToUByteArray()
 | 
			
		||||
        val (sk,_) = SigningKey.pair()
 | 
			
		||||
        val (sk,_) = Signing.pair()
 | 
			
		||||
        val t = now()
 | 
			
		||||
        val s1 = Seal.create(sk, data, createdAt = t)
 | 
			
		||||
        val s2 = Seal.create(sk, data, createdAt = t)
 | 
			
		||||
@ -212,13 +212,8 @@ class KeysTest {
 | 
			
		||||
        assertEquals(usk2, usk1)
 | 
			
		||||
        assertFalse { usk1 == usk3 }
 | 
			
		||||
 | 
			
		||||
        var a = setOf(sy1, sy2, sk1, sk2)
 | 
			
		||||
        var b = setOf(sk1, sk2, sy2, sy1)
 | 
			
		||||
 | 
			
		||||
        assertEquals(a,b)
 | 
			
		||||
 | 
			
		||||
        a = setOf(usk1, usk2, usk3, usk4)
 | 
			
		||||
        b = setOf(usk1, usk2, usk3, usk4)
 | 
			
		||||
        var a = setOf(usk1, usk2, usk3, usk4)
 | 
			
		||||
        var b = setOf(usk1, usk2, usk3, usk4)
 | 
			
		||||
 | 
			
		||||
        assertEquals(a, b)
 | 
			
		||||
        // usk1 and usk2 are equal so set with only one of should be the same
 | 
			
		||||
 | 
			
		||||
@ -31,8 +31,8 @@ class RingTest {
 | 
			
		||||
//
 | 
			
		||||
        val r = UniversalRing(k1, k2)
 | 
			
		||||
//        val r = UniversalRing(k1)
 | 
			
		||||
        assertContains(r, k2)
 | 
			
		||||
        assertContains(r, k1)
 | 
			
		||||
        assertTrue(k2 in r)
 | 
			
		||||
        assertTrue(k1 in r)
 | 
			
		||||
        assertFalse { k3 in r }
 | 
			
		||||
 | 
			
		||||
        println(Asymmetric.randomSecretKey().keyBytes.size)
 | 
			
		||||
@ -42,8 +42,8 @@ class RingTest {
 | 
			
		||||
        println(encoded.size)
 | 
			
		||||
        assertTrue { encoded.size < 80 }
 | 
			
		||||
        val r2: UniversalRing = BipackDecoder.decode(encoded)
 | 
			
		||||
        assertContains(r2, k2)
 | 
			
		||||
        assertContains(r2, k1)
 | 
			
		||||
        assertTrue { k2 in r2 }
 | 
			
		||||
        assertTrue { k1 in r2 }
 | 
			
		||||
        assertFalse { k3 in r2 }
 | 
			
		||||
 | 
			
		||||
        println("\r\n")
 | 
			
		||||
@ -57,8 +57,42 @@ class RingTest {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    @Ignore
 | 
			
		||||
    fun testKeysWithSameTags() {
 | 
			
		||||
        // it should be able to keep keys with same tags
 | 
			
		||||
    fun testTags() = runTest {
 | 
			
		||||
        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 k11 = UniversalKey.from(SymmetricKey("1234567890Hello,dolly.here-we-go".encodeToUByteArray()))
 | 
			
		||||
        val k2 = UniversalKey.from(Asymmetric.randomSecretKey())
 | 
			
		||||
        val k3 = UniversalKey.from(Asymmetric.randomSecretKey())
 | 
			
		||||
 | 
			
		||||
        val r1 = UniversalRing(k1, k2)
 | 
			
		||||
        var r2 = UniversalRing(deepCopy(k1), deepCopy(k2))
 | 
			
		||||
        assertEquals(r2, r1)
 | 
			
		||||
        val r3 = UniversalRing(k1 to "foo", k2 to "bar")
 | 
			
		||||
        assertNotEquals(r3, r2)
 | 
			
		||||
        assertTrue { r3 equalKeys r2 }
 | 
			
		||||
 | 
			
		||||
        r2 += (k1 to "foo")
 | 
			
		||||
        r2 = r2.addTags(k2, "bar")
 | 
			
		||||
        assertEquals(r2, r3)
 | 
			
		||||
        assertEquals(deepCopy(r2), r3)
 | 
			
		||||
 | 
			
		||||
        r2 += k1 to "buzz"
 | 
			
		||||
        r2 = deepCopy(r2)
 | 
			
		||||
        assertEquals(setOf("foo", "buzz"), r2.getTags(k1))
 | 
			
		||||
        assertNotEquals(r2, r3)
 | 
			
		||||
        r2 = deepCopy(r2.removeTags(k1, "buzz"))
 | 
			
		||||
        assertEquals(r2, r3)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun testSize() = runTest {
 | 
			
		||||
//        val sy1 = SymmetricKey.random().toUniversal()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user