From 67c0009b5b336847bea7fd89f4208317990d6a79 Mon Sep 17 00:00:00 2001 From: sergeych Date: Wed, 22 Nov 2023 12:38:00 +0300 Subject: [PATCH] use top-level Seal class --- .../kotlin/net/sergeych/crypto2/Seal.kt | 11 ++++++++ .../kotlin/net/sergeych/crypto2/SignedBox.kt | 26 ++++--------------- .../kotlin/net/sergeych/crypto2/SigningKey.kt | 4 ++- .../kiloparsec/KiloClientConnection.kt | 10 +++---- .../kiloparsec/KiloServerConnection.kt | 9 ++----- .../net/sergeych/kiloparsec/commands.kt | 4 +-- 6 files changed, 27 insertions(+), 37 deletions(-) create mode 100644 src/commonMain/kotlin/net/sergeych/crypto2/Seal.kt diff --git a/src/commonMain/kotlin/net/sergeych/crypto2/Seal.kt b/src/commonMain/kotlin/net/sergeych/crypto2/Seal.kt new file mode 100644 index 0000000..33e5ff5 --- /dev/null +++ b/src/commonMain/kotlin/net/sergeych/crypto2/Seal.kt @@ -0,0 +1,11 @@ +package net.sergeych.crypto2 + +import kotlinx.serialization.Serializable + +@Serializable +class Seal( + val publicKey: SigningKey.Public, + val signature: UByteArray +) { + inline fun verify(message: UByteArray) = publicKey.verify(signature, message) +} \ No newline at end of file diff --git a/src/commonMain/kotlin/net/sergeych/crypto2/SignedBox.kt b/src/commonMain/kotlin/net/sergeych/crypto2/SignedBox.kt index 522a846..9431d1e 100644 --- a/src/commonMain/kotlin/net/sergeych/crypto2/SignedBox.kt +++ b/src/commonMain/kotlin/net/sergeych/crypto2/SignedBox.kt @@ -30,14 +30,14 @@ class SignedBox( * _can't assume it always returns a copied object!_ */ operator fun plus(key: SigningKey.Secret): SignedBox = - if (key.verifying in this) this - else SignedBox(message, seals + Seal.create(key, message), false) + if (key.publicKey in this) this + else SignedBox(message, seals + key.seal(message), false) /** * Check that it is signed with a specified key. */ - operator fun contains(verifyingKey: SigningKey.Public): Boolean { - return seals.any { it.key == verifyingKey } + operator fun contains(publicKey: SigningKey.Public): Boolean { + return seals.any { it.publicKey == publicKey } } init { @@ -47,22 +47,6 @@ class SignedBox( } } - /** - * A key + signature pair for [SignedBox] boxes, usually you don't use it - * directly bug call [SignedBox] constructor or [SignedBox.plus] to - * add seals. - */ - @Serializable - data class Seal(val key: SigningKey.Public, val signature: UByteArray) { - - fun verify(message: UByteArray): Boolean = key.verify(signature, message) - - companion object { - fun create(key: SigningKey.Secret, message: UByteArray): Seal { - return Seal(key.verifying, key.sign(message)) - } - } - } companion object { /** @@ -76,6 +60,6 @@ class SignedBox( * @throws IllegalArgumentException if keys are not specified. */ operator fun invoke(data: UByteArray, vararg keys: SigningKey.Secret): SignedBox = - SignedBox(data, keys.map { Seal.create(it, data) }, false) + SignedBox(data, keys.map { it.seal(data) }, false) } } \ No newline at end of file diff --git a/src/commonMain/kotlin/net/sergeych/crypto2/SigningKey.kt b/src/commonMain/kotlin/net/sergeych/crypto2/SigningKey.kt index 0dd033b..cd38676 100644 --- a/src/commonMain/kotlin/net/sergeych/crypto2/SigningKey.kt +++ b/src/commonMain/kotlin/net/sergeych/crypto2/SigningKey.kt @@ -54,11 +54,13 @@ sealed class SigningKey { @SerialName("s") class Secret(override val packed: UByteArray) : SigningKey() { - val verifying: Public by lazy { + val publicKey: Public by lazy { Public(Signature.ed25519SkToPk(packed)) } fun sign(message: UByteArray): UByteArray = Signature.detached(message, packed) + + fun seal(message: UByteArray): Seal = Seal(this.publicKey, sign(message)) override fun toString(): String = "Sct:${super.toString()}" companion object { diff --git a/src/commonMain/kotlin/net/sergeych/kiloparsec/KiloClientConnection.kt b/src/commonMain/kotlin/net/sergeych/kiloparsec/KiloClientConnection.kt index c60e50f..4579e34 100644 --- a/src/commonMain/kotlin/net/sergeych/kiloparsec/KiloClientConnection.kt +++ b/src/commonMain/kotlin/net/sergeych/kiloparsec/KiloClientConnection.kt @@ -59,19 +59,17 @@ class KiloClientConnection( var params = KiloParams(false, transport, sk, session, null, this@KiloClientConnection) // Check ID if any - serverHe.serverPublicKey?.let { k -> - if (serverHe.signature == null) - throw RemoteInterface.SecurityException("missing signature") - if (!k.verify(serverHe.signature, params.token)) + serverHe.signature?.let { s -> + if (!s.verify(params.token)) throw RemoteInterface.SecurityException("wrong signature") - params = params.copy(remoteIdentity = k) + params = params.copy(remoteIdentity = s.publicKey) } transport.call( L0ClientId, params.encrypt( pack( ClientIdentity( - secretIdKey?.verifying, + secretIdKey?.publicKey, secretIdKey?.sign(params.token) ) ) diff --git a/src/commonMain/kotlin/net/sergeych/kiloparsec/KiloServerConnection.kt b/src/commonMain/kotlin/net/sergeych/kiloparsec/KiloServerConnection.kt index 83d3bbb..6a664d9 100644 --- a/src/commonMain/kotlin/net/sergeych/kiloparsec/KiloServerConnection.kt +++ b/src/commonMain/kotlin/net/sergeych/kiloparsec/KiloServerConnection.kt @@ -60,14 +60,9 @@ class KiloServerConnection( this@KiloServerConnection ) - var public: SigningKey.Public? = null - var signature: UByteArray? = null - if( serverSigningKey != null ) { - public = serverSigningKey.verifying - signature = serverSigningKey.sign(params!!.token) - } - Handshake(1u, pair.publicKey, public, signature) + Handshake(1u, pair.publicKey, serverSigningKey?.seal(params!!.token)) } + on(L0ClientId) { var p = params ?: throw RemoteInterface.ClosedException("wrong handshake sequence") val ci = unpack(p.decrypt(it)) diff --git a/src/commonMain/kotlin/net/sergeych/kiloparsec/commands.kt b/src/commonMain/kotlin/net/sergeych/kiloparsec/commands.kt index 4f97842..255db48 100644 --- a/src/commonMain/kotlin/net/sergeych/kiloparsec/commands.kt +++ b/src/commonMain/kotlin/net/sergeych/kiloparsec/commands.kt @@ -1,13 +1,13 @@ package net.sergeych.kiloparsec import kotlinx.serialization.Serializable +import net.sergeych.crypto2.Seal import net.sergeych.crypto2.SigningKey // L0 commands - key exchange and check: @Serializable data class Handshake(val version: UInt, val publicKey: UByteArray, - val serverPublicKey: SigningKey.Public? = null, - val signature: UByteArray? = null) + val signature: Seal? = null) @Serializable data class ClientIdentity(val clientIdKey: SigningKey.Public?, val signature: UByteArray?)