fix #1 UniversalPrivateKey & UniversalPublicKey

This commit is contained in:
sergeych committed 2024-11-13 18:24:44 +07:00
1 parent 194fe22afa
commit 640ceb448e
9 files changed
+131 -4

No files matched your search

@@ -20,6 +20,8 @@ import net.sergeych.crypto2.Container.Companion.createWith
* - [addRecipients] and various [plus] operators to add recipients
* - [updateData] to change decrypted content for the same recipient keys
*
* Note that container _is serialized encrypted_.
*
* Some rules:
*
* When adding public key recipient, it is faster to use your known [SecretKey], but you
@@ -126,8 +128,9 @@ sealed class Container {
abstract fun updateData(newPlainData: UByteArray, randomFill: IntRange? = null): Container
/**
* Binary encoded version. It is desirable to include [Container] as an object, though,
* especially when using custom serialization (Json, Boss, etc), it is serializable.
* Binary encoded _encrypted_ version. It is desirable to include [Container] as an object, though,
* especially when using custom serialization (Json, Boss, etc.), it is serializable. Note that
* serialized data is always encrypted.
* Still, if you need it in binary form, this is a shortcut. You can use [decode] or call
* [BipackDecoder.decode] to deserialize the binary form.
*/
@@ -474,6 +477,12 @@ sealed class Container {
inline fun <reified T> decrypt(cipherData: UByteArray, vararg keys: DecryptingKey): T? =
decryptAsUBytes(cipherData, *keys)?.let { BipackDecoder.decode<T>(it.asByteArray()) }
inline fun <reified T> decrypt(cipherData: UByteArray, ring: UniversalRing): T? =
decode(cipherData)
.decryptWith(ring)?.let {
BipackDecoder.decode<T>(it.asByteArray())
}
fun decryptAsUBytes(cipherData: UByteArray, vararg keys: DecryptingKey): UByteArray? =
decode(cipherData).decryptWith(*keys)
@@ -6,6 +6,11 @@ enum class KeysmagicNumber(val label: String) {
defaultSymmetric( "sym"),
defaultSession( "ssn"),
defaultVerifying( "ver"),
defaultSigningSecret( "sig"),
defaultUniversalPublic( "pub+"),
defaultUniversalPrivate( "prv+"),
;
}
@@ -23,6 +23,8 @@ class SigningSecretKey(
VerifyingPublicKey(Signature.ed25519SkToPk(keyBytes)).also { cachedPublicKey = it }
}
override val magic: KeysmagicNumber = KeysmagicNumber.defaultSigningSecret
override fun sign(message: UByteArray): UByteArray = Signature.detached(message, keyBytes)
override fun seal(message: UByteArray, expiresAt: Instant?): Seal =
@@ -8,7 +8,6 @@ sealed class UniversalKey: KeyInstance {
abstract val keyBytes: UByteArray
@Transient
open val magic: KeysmagicNumber = KeysmagicNumber.Unknown
@@ -0,0 +1,47 @@
package net.sergeych.crypto2
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
/**
* Combination of private/secret keys suitable for both decryption and signing.
*
* It contains two cryptographically independent keys to raise security to a maximum.
* Any converted keys poses a threat while technically possible so we avoid it.
*/
@Serializable
@SerialName("uprv")
class UniversalPrivateKey(
val signingKey: SigningSecretKey,
val decryptingKey: SecretKey
) : UniversalKey(), DecryptingKey by decryptingKey, SigningKey by signingKey {
override val keyBytes by lazy { signingKey.keyBytes + decryptingKey.keyBytes }
@Transient
override val magic = KeysmagicNumber.defaultUniversalPrivate
/**
* Important! Private key combines signing and decrypting keys, but uses
* it of the decrypting one to be used in keyring.
*/
@Transient
override val id: KeyId = decryptingKey.id
/**
* Corresponding public key able to verify amd encrypt data created by this
* private key.
*/
val publicKey by lazy {
UniversalPublicKey(signingKey.verifyingKey, decryptingKey.publicKey)
}
companion object {
/**
* Generate 2 new random keys (4 key pairs under the hood) to securely signd and
* decrypt data.
*/
fun new() = UniversalPrivateKey(SigningSecretKey.new(), SecretKey.new())
}
}
@@ -0,0 +1,34 @@
package net.sergeych.crypto2
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
/**
* Combination of public keys suitable for both encryption and verification. A counterpart
* of the [UniversalPrivateKey], available also as [UniversalPrivateKey.publicKey].
*
* When using [UniversalRing] and [Container], data encrypted with instances og this class
* can be decrypted with rings containing the corresponding [UniversalPrivateKey].
*/
@Serializable
@SerialName("upub")
class UniversalPublicKey(
val verifyingKey: VerifyingPublicKey,
val encryptingKey: PublicKey
): UniversalKey(), VerifyingKey by verifyingKey, EncryptingKey by encryptingKey{
override val keyBytes by lazy { verifyingKey.keyBytes + encryptingKey.keyBytes }
@Transient
override val magic = KeysmagicNumber.defaultUniversalPublic
/**
* Important! Private key combines signing and decrypting keys, but uses
* it of the decrypting one to be used in keyring.
*/
@Transient
override val id: KeyId = encryptingKey.id
}