Compare commits

...

7 Commits

64 changed files with 769 additions and 121 deletions

View File

@ -114,4 +114,13 @@ Secret key encryption and signing/verifying uses Edwards curves 25519 algorithms
- SHA3 256, 384, more are on the way. - SHA3 256, 384, more are on the way.
- CRC-protected binary ID with magic numbers to implement human-friendly IDS with type checks - CRC-protected binary ID with magic numbers to implement human-friendly IDS with type checks
## Licensing
# Licensing
This is work in progress, not yet moved to public domain;
you need to obtain a license from https://8-rays.dev or [Sergey Chernov]. For open source projects it will most be free on some special terms.
It will be moved to open source; we also guarantee that it will be moved to open source immediately if the software export restrictions will be lifted. We do not support such practices here at 8-rays.dev and assume open source must be open.
[Sergey Chernov]: https://t.me/real_sergeych

View File

@ -1,4 +1,14 @@
#!/bin/bash #!/bin/bash
#
# Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
#
# You may use, distribute and modify this code under the
# terms of the private license, which you must obtain from the author
#
# To obtain the license, contact the author: https://t.me/real_sergeych or email to
# real dot sergeych at gmail.
#
set -e set -e
./gradlew dokkaHtml ./gradlew dokkaHtml
rsync -avz ./build/dokka/* code.sergeych.net:/bigstore/sergeych_pub/code/docs/crypto2 rsync -avz ./build/dokka/* code.sergeych.net:/bigstore/sergeych_pub/code/docs/crypto2

View File

@ -1,5 +1,14 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins { plugins {
@ -10,13 +19,13 @@ plugins {
} }
group = "net.sergeych" group = "net.sergeych"
version = "0.7.1-SNAPSHOT" version = "0.7.4-SNAPSHOT"
repositories { repositories {
mavenCentral() mavenCentral()
maven("https://maven.universablockchain.com/") maven("https://maven.universablockchain.com/")
maven("https://gitea.sergeych.net/api/packages/SergeychWorks/maven") maven("https://gitea.sergeych.net/api/packages/SergeychWorks/maven")
maven("https://gitea.sergeych.net/api/packages/YoungBlood/maven") // maven("https://gitea.sergeych.net/api/packages/YoungBlood/maven")
mavenLocal() mavenLocal()
} }
@ -40,10 +49,10 @@ kotlin {
iosArm64() iosArm64()
iosSimulatorArm64() iosSimulatorArm64()
mingwX64() mingwX64()
@OptIn(ExperimentalWasmDsl::class) // @OptIn(ExperimentalWasmDsl::class)
wasmJs { // wasmJs {
browser() // browser()
} // }
val ktor_version = "2.3.6" val ktor_version = "2.3.6"
sourceSets { sourceSets {
@ -87,18 +96,18 @@ kotlin {
for (platform in listOf(linuxX64Main, linuxArm64Main, macosX64Main, macosArm64Main, iosX64Main, iosArm64Main, iosSimulatorArm64Main, mingwX64Main)) for (platform in listOf(linuxX64Main, linuxArm64Main, macosX64Main, macosArm64Main, iosX64Main, iosArm64Main, iosSimulatorArm64Main, mingwX64Main))
platform { dependsOn(native) } platform { dependsOn(native) }
val wasmJsMain by getting { // val wasmJsMain by getting {
val wasmJsTargetRegex = Regex(pattern = "wasmJs.*") // val wasmJsTargetRegex = Regex(pattern = "wasmJs.*")
configurations.all { // configurations.all {
if (wasmJsTargetRegex.containsMatchIn(input = this.name)) { // if (wasmJsTargetRegex.containsMatchIn(input = this.name)) {
resolutionStrategy.dependencySubstitution { // resolutionStrategy.dependencySubstitution {
substitute(module("com.ionspin.kotlin:multiplatform-crypto-libsodium-bindings:0.9.2")) // substitute(module("com.ionspin.kotlin:multiplatform-crypto-libsodium-bindings:0.9.2"))
.using(module("net.sergeych:multiplatform-crypto-libsodium-bindings:0.9.4-SNAPSHOT")) // .using(module("net.sergeych:multiplatform-crypto-libsodium-bindings:0.9.4-SNAPSHOT"))
.withoutClassifier() // .withoutClassifier()
} // }
} // }
} // }
} // }
} }
} }

View File

@ -1 +1,11 @@
#
# Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
#
# You may use, distribute and modify this code under the
# terms of the private license, which you must obtain from the author
#
# To obtain the license, contact the author: https://t.me/real_sergeych or email to
# real dot sergeych at gmail.
#
kotlin.code.style=official kotlin.code.style=official

View File

@ -1,3 +1,13 @@
#
# Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
#
# You may use, distribute and modify this code under the
# terms of the private license, which you must obtain from the author
#
# To obtain the license, contact the author: https://t.me/real_sergeych or email to
# real dot sergeych at gmail.
#
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip

16
gradlew vendored
View File

@ -1,19 +1,13 @@
#!/bin/sh #!/bin/sh
# #
# Copyright © 2015-2021 the original authors. # Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # You may use, distribute and modify this code under the
# you may not use this file except in compliance with the License. # terms of the private license, which you must obtain from the author
# You may obtain a copy of the License at
# #
# https://www.apache.org/licenses/LICENSE-2.0 # To obtain the license, contact the author: https://t.me/real_sergeych or email to
# # real dot sergeych at gmail.
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# #
############################################################################## ##############################################################################

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
pluginManagement { pluginManagement {
repositories { repositories {
mavenCentral() mavenCentral()

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import com.ionspin.kotlin.crypto.box.Box import com.ionspin.kotlin.crypto.box.Box
@ -14,10 +24,10 @@ import net.sergeych.crypto2.Asymmetric.generateKeys
* *
* ## How to * ## How to
* *
* - [SecretKey.new] to create a secret key that includes [SecretKey.publicKey]. * - [DecryptingSecretKey.new] to create a secret key that includes [DecryptingSecretKey.publicKey].
* [generateKeys] also makes the pair. * [generateKeys] also makes the pair.
* - [PublicKey] provides encryption, anonymous or authenticated. * - [EncryptingPublicKey] provides encryption, anonymous or authenticated.
* - [SecretKey] provides authenticated decryption of what [PublicKey] was encrypted with. * - [DecryptingSecretKey] provides authenticated decryption of what [EncryptingPublicKey] was encrypted with.
* - [Message] is a serializable container with all necessary data to decrypt public-key encrypted data it. * - [Message] is a serializable container with all necessary data to decrypt public-key encrypted data it.
* *
* __Algorithms:__ * __Algorithms:__
@ -31,8 +41,8 @@ object Asymmetric {
/** /**
* Encrypted message holder. * Encrypted message holder.
* *
* Do not instantiate it directly, use [PublicKey.encryptMessage], [PublicKey.encryptAnonymousMessage], etc. * Do not instantiate it directly, use [EncryptingPublicKey.encryptMessage], [EncryptingPublicKey.encryptAnonymousMessage], etc.
* instead. Also [SecretKey.decrypt] can be used to decrypt it same as [decrypt] or [decryptWithSenderKey]. * instead. Also [DecryptingSecretKey.decrypt] can be used to decrypt it same as [decrypt] or [decryptWithSenderKey].
* *
* To successfully decrypt the message, it is necessary to know a sender public key, and non-secret nonce. * To successfully decrypt the message, it is necessary to know a sender public key, and non-secret nonce.
* This class carries all this information; serialize and pass it to the recipient. * This class carries all this information; serialize and pass it to the recipient.
@ -41,12 +51,12 @@ object Asymmetric {
class Message( class Message(
private val nonce: UByteArray, private val nonce: UByteArray,
private val encryptedMessage: UByteArray, private val encryptedMessage: UByteArray,
val senderPublicKey: PublicKey, val senderPublicKey: EncryptingPublicKey,
) { ) {
/** /**
* Decrypt the message, same as [SecretKey.decrypt] * Decrypt the message, same as [DecryptingSecretKey.decrypt]
*/ */
fun decrypt(recipientKey: SecretKey): UByteArray { fun decrypt(recipientKey: DecryptingSecretKey): UByteArray {
return decryptWithSenderKey(senderPublicKey, recipientKey) return decryptWithSenderKey(senderPublicKey, recipientKey)
} }
@ -54,7 +64,7 @@ object Asymmetric {
* Decrypt a message which is not include sender's public key (which should somehow be * Decrypt a message which is not include sender's public key (which should somehow be
* known to the recipient). Use it if [senderPublicKey] is null. * known to the recipient). Use it if [senderPublicKey] is null.
*/ */
fun decryptWithSenderKey(senderKey: PublicKey, recipientKey: SecretKey): UByteArray { fun decryptWithSenderKey(senderKey: EncryptingPublicKey, recipientKey: DecryptingSecretKey): UByteArray {
return try { return try {
WithFill.decode( WithFill.decode(
Box.openEasy(encryptedMessage, nonce, senderKey.keyBytes, recipientKey.keyBytes) Box.openEasy(encryptedMessage, nonce, senderKey.keyBytes, recipientKey.keyBytes)
@ -79,19 +89,19 @@ object Asymmetric {
/** /**
* Encrypt the [plainData] using [from] sender for [recipient] public key. Note that to decrypt it * Encrypt the [plainData] using [from] sender for [recipient] public key. Note that to decrypt it
* the [SecretKey] that corresponds to the [recipient] public key is needed, Sender can't decrypt the message! * the [DecryptingSecretKey] that corresponds to the [recipient] public key is needed, Sender can't decrypt the message!
* *
* The authenticated encryption is used, is the message _is successfully decrypted_, it also means that * The authenticated encryption is used, is the message _is successfully decrypted_, it also means that
* it was signed by the sender, whose public key is known at the decryption time. * it was signed by the sender, whose public key is known at the decryption time.
* *
* When it is important not to provide senders' key, use [PublicKey.encryptAnonymousMessage]. * When it is important not to provide senders' key, use [EncryptingPublicKey.encryptAnonymousMessage].
* *
* @param from the senders' secret key. * @param from the senders' secret key.
* @param recipient the recipients' public key. * @param recipient the recipients' public key.
* @param plainData data to encrypt * @param plainData data to encrypt
*/ */
internal fun createMessage( internal fun createMessage(
from: SecretKey, recipient: PublicKey, plainData: UByteArray, from: DecryptingSecretKey, recipient: EncryptingPublicKey, plainData: UByteArray,
nonce: UByteArray = randomNonce(), nonce: UByteArray = randomNonce(),
): Message { ): Message {
return Message( return Message(
@ -104,8 +114,8 @@ object Asymmetric {
private fun randomNonce(): UByteArray = randomUBytes(crypto_box_NONCEBYTES) private fun randomNonce(): UByteArray = randomUBytes(crypto_box_NONCEBYTES)
fun generateKeys() = SecretKey.generateKeys() fun generateKeys() = DecryptingSecretKey.generateKeys()
fun newSecretKey() = SecretKey.new() fun newSecretKey() = DecryptingSecretKey.new()
val nonceBytesLength = crypto_box_NONCEBYTES val nonceBytesLength = crypto_box_NONCEBYTES
@ -115,4 +125,4 @@ object Asymmetric {
* Shortcut type: a pair of sender secret key and recipient private key could be used so * Shortcut type: a pair of sender secret key and recipient private key could be used so
* simplify such interfaces * simplify such interfaces
*/ */
typealias AsymmetricEncryptionPair = Pair<SecretKey?, PublicKey> typealias AsymmetricEncryptionPair = Pair<DecryptingSecretKey?, EncryptingPublicKey>

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import com.ionspin.kotlin.crypto.util.encodeToUByteArray import com.ionspin.kotlin.crypto.util.encodeToUByteArray
@ -48,7 +58,7 @@ open class BinaryId(
/** /**
* Bad format (crc does not match) * Bad format (crc does not match)
*/ */
class InvalidException(text: String,reason: Throwable?=null) : IllegalArgumentException(text,reason) class InvalidException(text: String, reason: Throwable? = null) : IllegalArgumentException(text, reason)
/** /**
* Attempt to compare binary ids with different magic. In this case only [equals] * Attempt to compare binary ids with different magic. In this case only [equals]
@ -70,32 +80,32 @@ open class BinaryId(
rest.last().toInt() rest.last().toInt()
} }
private val innerData: UByteArray by lazy { id.sliceArray( 1..< id.size-1 ) } private val innerData: UByteArray by lazy { id.sliceArray(1..<id.size - 1) }
/** /**
* The ID body: all the bytes except check and magic. ID bytes could carry useful information. * The ID body: all the bytes except check and magic. ID bytes could carry useful information.
* *
* - `id.size` is [body] size + 2 (see [BinaryId] inner structure) * - `id.size` is [body] size + 2 (see [BinaryId] inner structure)
*/ */
val body: UByteArray by lazy { id.sliceArray( 0 until id.size-2 ) } val body: UByteArray by lazy { id.sliceArray(0 until id.size - 2) }
val asVerifyingKey: VerifyingKey by lazy { val asVerifyingKey: VerifyingKey by lazy {
if( magic != KeysmagicNumber.defaultVerifying.ordinal) if (magic != KeysmagicNumber.defaultVerifying.ordinal)
throw InvalidException("It is not a veryfing key: magic=$magic, required ${KeysmagicNumber.defaultVerifying.ordinal}") throw InvalidException("It is not a veryfing key: magic=$magic, required ${KeysmagicNumber.defaultVerifying.ordinal}")
check(body.size == 32) check(body.size == 32)
VerifyingPublicKey(body) VerifyingPublicKey(body)
} }
/** /**
* Try to recnstruct a [PublicKey] from [id] bytes. For such keys, [PublicKey.id] and [SecretKey.id] * Try to recnstruct a [EncryptingPublicKey] from [id] bytes. For such keys, [EncryptingPublicKey.id] and [DecryptingSecretKey.id]
* are made from public key bytes so it could be restored from such an ID * are made from public key bytes so it could be restored from such an ID
* *
*/ */
val asPublicKey: PublicKey by lazy { val asPublicKey: EncryptingPublicKey by lazy {
if( magic != KeysmagicNumber.defaultAssymmetric.ordinal) if (magic != KeysmagicNumber.defaultAssymmetric.ordinal)
throw InvalidException("It is not a veryfing key: magic=$magic, required ${KeysmagicNumber.defaultAssymmetric.ordinal}") throw InvalidException("It is not a veryfing key: magic=$magic, required ${KeysmagicNumber.defaultAssymmetric.ordinal}")
check(body.size == 32) check(body.size == 32)
PublicKey(body) EncryptingPublicKey(body)
} }
override fun toString(): String = id.encodeToBase64Url() override fun toString(): String = id.encodeToBase64Url()
@ -157,8 +167,8 @@ open class BinaryId(
} }
@Suppress("unused") @Suppress("unused")
fun createRandom(magicNumber: Int, size: Int=16) = fun createRandom(magicNumber: Int, size: Int = 16) =
createFromBytes(magicNumber, Random.Default.nextBytes(size-2)) createFromBytes(magicNumber, Random.Default.nextBytes(size - 2))
/** /**
* Encode a string as UTF and create a binaryId from its bytes and provided magic. * Encode a string as UTF and create a binaryId from its bytes and provided magic.

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
@ -24,8 +34,8 @@ import net.sergeych.crypto2.Container.Companion.createWith
* *
* Some rules: * Some rules:
* *
* When adding public key recipient, it is faster to use your known [SecretKey], but you * When adding public key recipient, it is faster to use your known [DecryptingSecretKey], but you
* can stay anonymous by just adding [PublicKey] only. * can stay anonymous by just adding [EncryptingPublicKey] only.
* *
* Put your data in [SealedBox] if you need to authenticate message origin and timestamp, then put * Put your data in [SealedBox] if you need to authenticate message origin and timestamp, then put
* the sealed box in the [Container], this will conceal signers from attack. In the case you need to * the sealed box in the [Container], this will conceal signers from attack. In the case you need to
@ -107,7 +117,7 @@ sealed class Container {
* Add e key to the __decrypted__ container. The new container is also decrypted so you can add * Add e key to the __decrypted__ container. The new container is also decrypted so you can add
* more keys, etc. * more keys, etc.
*/ */
operator fun plus(recipient: PublicKey) = addRecipients { key(recipient) } operator fun plus(recipient: EncryptingPublicKey) = addRecipients { key(recipient) }
/** /**
* Add e key to the __decrypted__ container. The new container is also decrypted so you can add * Add e key to the __decrypted__ container. The new container is also decrypted so you can add
@ -119,7 +129,7 @@ sealed class Container {
* Add e key to the __decrypted__ container. The new container is also decrypted so you can add * Add e key to the __decrypted__ container. The new container is also decrypted so you can add
* more keys, etc. * more keys, etc.
*/ */
operator fun plus(pair: Pair<SecretKey, PublicKey>) = addRecipients { key(pair) } operator fun plus(pair: Pair<DecryptingSecretKey, EncryptingPublicKey>) = addRecipients { key(pair) }
/** /**
* Update the data in the decrypted container. It keeps the same set of keys and update * Update the data in the decrypted container. It keeps the same set of keys and update
@ -145,14 +155,14 @@ sealed class Container {
abstract val decryptedWithKeyId: KeyId? abstract val decryptedWithKeyId: KeyId?
/** /**
* If the container _is decrypted by the [PublicKey]_, e.g., using secret key encryption, * If the container _is decrypted by the [EncryptingPublicKey]_, e.g., using secret key encryption,
* contains the [PublicKey] that corresponds the [SecretKey] used while encrypting, this * contains the [EncryptingPublicKey] that corresponds the [DecryptingSecretKey] used while encrypting, this
* authenticating the sender party cryptographically. This key could be used to encrypt * authenticating the sender party cryptographically. This key could be used to encrypt
* the response to be visible to the sender only; the sender, providing it kept his secret key, * the response to be visible to the sender only; the sender, providing it kept his secret key,
* could decrypt it. * could decrypt it.
*/ */
@Transient @Transient
var authorisedByKey: PublicKey? = null var authorisedByKey: EncryptingPublicKey? = null
protected set protected set
/** /**
@ -193,7 +203,7 @@ sealed class Container {
kotlin.runCatching { k.decrypt(encryptedMessage) }.getOrNull()?.let { kotlin.runCatching { k.decrypt(encryptedMessage) }.getOrNull()?.let {
decryptedData = it decryptedData = it
decryptedWithKey = k decryptedWithKey = k
if( k is SecretKey) { if(k is DecryptingSecretKey) {
authorisedByKey = Asymmetric.Message.decode(encryptedMessage).senderPublicKey authorisedByKey = Asymmetric.Message.decode(encryptedMessage).senderPublicKey
} }
return it return it
@ -216,7 +226,7 @@ sealed class Container {
// otherwise, we don't know the encryption key and will try to derive it // otherwise, we don't know the encryption key and will try to derive it
// from the decryption key: // from the decryption key:
when (val k = decryptedWithKey!!) { when (val k = decryptedWithKey!!) {
is SecretKey -> { is DecryptingSecretKey -> {
key(k.publicKey) key(k.publicKey)
} }
@ -259,12 +269,12 @@ sealed class Container {
constructor(key: EncryptingKey, encodeMainKey: UByteArray) : constructor(key: EncryptingKey, encodeMainKey: UByteArray) :
this(key.id, key.encrypt(encodeMainKey)) this(key.id, key.encrypt(encodeMainKey))
constructor(sender: SecretKey?, recipient: PublicKey, encodeMainKey: UByteArray) : constructor(sender: DecryptingSecretKey?, recipient: EncryptingPublicKey, encodeMainKey: UByteArray) :
this( this(
recipient.id, recipient.id,
recipient.encryptMessage( recipient.encryptMessage(
encodeMainKey, encodeMainKey,
senderKey = sender ?: SecretKey.new(), senderKey = sender ?: DecryptingSecretKey.new(),
).encoded ).encoded
) )
} }
@ -294,7 +304,7 @@ sealed class Container {
throw InvalidContainerException() throw InvalidContainerException()
decryptedWithKeyId = key.id decryptedWithKeyId = key.id
mainKey = k mainKey = k
if( key is SecretKey) { if(key is DecryptingSecretKey) {
authorisedByKey = Asymmetric.Message.decode(encryptedKey.cipherData).senderPublicKey authorisedByKey = Asymmetric.Message.decode(encryptedKey.cipherData).senderPublicKey
} }
} }
@ -358,8 +368,8 @@ sealed class Container {
} }
/** /**
* Add one or more [SecretKey] as sender authority coupled with [PublicKey] as * Add one or more [DecryptingSecretKey] as sender authority coupled with [EncryptingPublicKey] as
* a recipient. This is faster than anonymous usage of [PublicKey] only * a recipient. This is faster than anonymous usage of [EncryptingPublicKey] only
*/ */
fun key(vararg pairs: AsymmetricEncryptionPair) { fun key(vararg pairs: AsymmetricEncryptionPair) {
keyPairs.addAll(pairs) keyPairs.addAll(pairs)
@ -368,7 +378,7 @@ sealed class Container {
/** /**
* Add one or more public keys as recipients. This is slower than using pairs of sender -> recipient. * Add one or more public keys as recipients. This is slower than using pairs of sender -> recipient.
*/ */
fun key(vararg publicKeys: PublicKey) { fun key(vararg publicKeys: EncryptingPublicKey) {
keyPairs.addAll(publicKeys.map { null to it }) keyPairs.addAll(publicKeys.map { null to it })
} }
@ -429,7 +439,7 @@ sealed class Container {
Single( Single(
pk.id, pk.encryptMessage( pk.id, pk.encryptMessage(
plainData, plainData,
senderKey = sk ?: SecretKey.new(), senderKey = sk ?: DecryptingSecretKey.new(),
randomFill = fillRange randomFill = fillRange
).encoded, ).encoded,
plainData, plainData,

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import net.sergeych.bintools.CRC import net.sergeych.bintools.CRC

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import com.ionspin.kotlin.crypto.util.decodeFromUByteArray import com.ionspin.kotlin.crypto.util.decodeFromUByteArray
@ -8,7 +18,7 @@ import net.sergeych.crypto2.SymmetricKey.WithNonce
/** /**
* Some key able to perform decrypting. It is not serializable by purpose, as not all such * Some key able to perform decrypting. It is not serializable by purpose, as not all such
* keys are wise to transfer/save. Concrete implementations are, like [SymmetricKey] or * keys are wise to transfer/save. Concrete implementations are, like [SymmetricKey] or
* [SecretKey]. * [DecryptingSecretKey].
*/ */
interface DecryptingKey : NonceBased, KeyInstance { interface DecryptingKey : NonceBased, KeyInstance {
/** /**

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import com.ionspin.kotlin.crypto.util.encodeToUByteArray import com.ionspin.kotlin.crypto.util.encodeToUByteArray

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import com.ionspin.kotlin.crypto.generichash.GenericHash import com.ionspin.kotlin.crypto.generichash.GenericHash

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import com.ionspin.kotlin.crypto.LibsodiumInitializer import com.ionspin.kotlin.crypto.LibsodiumInitializer

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -10,7 +20,7 @@ import kotlinx.serialization.Serializable
* Important. `KeyId` of matching keys are the same, so you can use it to identify * 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: * and find matching keys in the [UniversalRing], etc. For example:
* *
* - [SecretKey] and [PublicKey] from the same pair have the same `KeyId`, thus the former * - [DecryptingSecretKey] and [EncryptingPublicKey] from the same pair have the same `KeyId`, thus the former
* can decrypt what was encrypted with the latter. * can decrypt what was encrypted with the latter.
* *
* - [SigningSecretKey] and corresponding [VerifyingKey] have the same `KeyId`. Use it to pick a proper key for * - [SigningSecretKey] and corresponding [VerifyingKey] have the same `KeyId`. Use it to pick a proper key for
@ -18,7 +28,7 @@ import kotlinx.serialization.Serializable
* *
* See [PBKD.Params.deriveKey] for deriving keys from id. * See [PBKD.Params.deriveKey] for deriving keys from id.
* *
* See [id], and [BinaryId] class for more. Note that for [PublicKey] and [VerifyingPublicKey] [BinaryId.asPublicKey] * See [id], and [BinaryId] class for more. Note that for [EncryptingPublicKey] and [VerifyingPublicKey] [BinaryId.asPublicKey]
* and [BinaryId.asVerifyingKey] restore actual keys, providing [BinaryId.magic] has proper value, see [KeysmagicNumber]] * and [BinaryId.asVerifyingKey] restore actual keys, providing [BinaryId.magic] has proper value, see [KeysmagicNumber]]
* *
* @param id actual id used in equality test amd hash code generation. `Id` of the matching keys is the same. * @param id actual id used in equality test amd hash code generation. `Id` of the matching keys is the same.

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
/** /**

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
enum class KeysmagicNumber(val label: String) { enum class KeysmagicNumber(val label: String) {

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
interface NonceBased { interface NonceBased {

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
/** /**

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import com.ionspin.kotlin.crypto.util.encodeToUByteArray import com.ionspin.kotlin.crypto.util.encodeToUByteArray

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
@ -7,20 +17,22 @@ import net.sergeych.bipack.decodeFromBipack
import net.sergeych.crypto2.VerifyingPublicKey.Companion.toString import net.sergeych.crypto2.VerifyingPublicKey.Companion.toString
import net.sergeych.mp_tools.decodeBase64Url import net.sergeych.mp_tools.decodeBase64Url
@Deprecated("Use EncryptingPublicKey",ReplaceWith("EncryptingPublicKey"))
typealias PublicKey = EncryptingPublicKey
/** /**
* The public for public-key encryption. It encrypts messages that can only be decrypted with corresponding * The public for public-key encryption. It encrypts messages that can only be decrypted with corresponding
* [SecretKey]. * [DecryptingSecretKey].
*/ */
@Serializable @Serializable
@SerialName("encp") @SerialName("encp")
class PublicKey(override val keyBytes: UByteArray) : UniversalKey(), EncryptingKey { class EncryptingPublicKey(override val keyBytes: UByteArray) : UniversalKey(), EncryptingKey {
override val magic: KeysmagicNumber = KeysmagicNumber.defaultAssymmetric override val magic: KeysmagicNumber = KeysmagicNumber.defaultAssymmetric
@Transient @Transient
override val label: String = "pub" override val label: String = "pub"
/** /**
* Create an anonymous message that could be decrypted only with the [SecretKey] that corresponds this. * Create an anonymous message that could be decrypted only with the [DecryptingSecretKey] that corresponds this.
* Anonymous message uses one-time secret key, the public part of which is included into the * Anonymous message uses one-time secret key, the public part of which is included into the
* [Asymmetric.Message], so the sender could not be identified. * [Asymmetric.Message], so the sender could not be identified.
* *
@ -57,18 +69,18 @@ class PublicKey(override val keyBytes: UByteArray) : UniversalKey(), EncryptingK
fun encryptMessage( fun encryptMessage(
plainData: UByteArray, plainData: UByteArray,
nonce: UByteArray = randomNonce(), nonce: UByteArray = randomNonce(),
senderKey: SecretKey = newSecretKey(), senderKey: DecryptingSecretKey = newSecretKey(),
randomFill: IntRange? = null, randomFill: IntRange? = null,
) = Asymmetric.createMessage(senderKey, this, WithFill.encode(plainData, randomFill), nonce) ) = Asymmetric.createMessage(senderKey, this, WithFill.encode(plainData, randomFill), nonce)
/** /**
* Encrypt message using the specified secret key as sender authentication. Recipient, the party having * Encrypt message using the specified secret key as sender authentication. Recipient, the party having
* [SecretKey] corresponding to this one, will be able to decrypt the message and be sure that [senderKey] * [DecryptingSecretKey] corresponding to this one, will be able to decrypt the message and be sure that [senderKey]
* was the author and the message was not altered. * was the author and the message was not altered.
*/ */
fun encryptMessage( fun encryptMessage(
plainData: UByteArray, plainData: UByteArray,
senderKey: SecretKey, senderKey: DecryptingSecretKey,
randomFill: IntRange? = null, randomFill: IntRange? = null,
): Asymmetric.Message = ): Asymmetric.Message =
Asymmetric.createMessage(senderKey, this, WithFill.encode(plainData, randomFill)) Asymmetric.createMessage(senderKey, this, WithFill.encode(plainData, randomFill))
@ -81,12 +93,12 @@ class PublicKey(override val keyBytes: UByteArray) : UniversalKey(), EncryptingK
* possible) * possible)
* @throws IllegalArgumentException the public key isn't recognized * @throws IllegalArgumentException the public key isn't recognized
*/ */
fun parse(text: String): PublicKey { fun parse(text: String): EncryptingPublicKey {
val s = text.trim() val s = text.trim()
fun parseId(t: String): PublicKey{ fun parseId(t: String): EncryptingPublicKey {
val id = BinaryId.restoreFromString(t) val id = BinaryId.restoreFromString(t)
if( id.magic != KeysmagicNumber.defaultAssymmetric.ordinal) if (id.magic != KeysmagicNumber.defaultAssymmetric.ordinal)
throw IllegalArgumentException("invalid magick ${id.magic} for PublicKey") throw IllegalArgumentException("invalid magick ${id.magic} for PublicKey")
return id.asPublicKey return id.asPublicKey
} }
@ -100,10 +112,10 @@ class PublicKey(override val keyBytes: UByteArray) : UniversalKey(), EncryptingK
// consider it is serialized key in base64 format // consider it is serialized key in base64 format
val data = s.decodeBase64Url().asUByteArray() val data = s.decodeBase64Url().asUByteArray()
if (data.size == 32) if (data.size == 32)
PublicKey(data) EncryptingPublicKey(data)
else { else {
runCatching { data.decodeFromBipack<PublicKey>() }.getOrNull() runCatching { data.decodeFromBipack<EncryptingPublicKey>() }.getOrNull()
?: kotlin.runCatching { data.decodeFromBipack<UniversalKey>() as PublicKey } ?: kotlin.runCatching { data.decodeFromBipack<UniversalKey>() as EncryptingPublicKey }
.getOrElse { throw IllegalArgumentException("can't parse verifying key") } .getOrElse { throw IllegalArgumentException("can't parse verifying key") }
} }
} }

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import com.ionspin.kotlin.crypto.keyexchange.KeyExchange import com.ionspin.kotlin.crypto.keyexchange.KeyExchange
@ -10,7 +20,7 @@ import net.sergeych.crypto2.SafeKeyExchange.SessionKey
* Usage: * Usage:
* *
* 1. Create [SafeKeyExchange] on both server and client sides * 1. Create [SafeKeyExchange] on both server and client sides
* 2. Exchange [publicKey] instances * 2. Exchange [EncryptingPublicKey] instances
* 3. Create [serverSessionKey] and [clientSessionKey] respectively * 3. Create [serverSessionKey] and [clientSessionKey] respectively
* 4. Use [SessionKey.sendingKey] and [SessionKey.receivingKey] to send and receive encrypted data. * 4. Use [SessionKey.sendingKey] and [SessionKey.receivingKey] to send and receive encrypted data.
* *
@ -20,7 +30,7 @@ import net.sergeych.crypto2.SafeKeyExchange.SessionKey
* instances as often as performance considerations allow. * instances as often as performance considerations allow.
* - while it is possible to generate several keys "ahead", the care should be taken when storing them, * - while it is possible to generate several keys "ahead", the care should be taken when storing them,
* encrypt it with some other key to maintain safety. * encrypt it with some other key to maintain safety.
* - do not use [publicKey] for anything but creating session keys. * - do not use [EncryptingPublicKey] for anything but creating session keys.
*/ */
class SafeKeyExchange { class SafeKeyExchange {
private val pair = KeyExchange.keypair() private val pair = KeyExchange.keypair()

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import kotlinx.datetime.Instant import kotlinx.datetime.Instant
@ -6,6 +16,7 @@ import net.sergeych.bipack.BipackEncoder
import net.sergeych.bipack.decodeFromBipack import net.sergeych.bipack.decodeFromBipack
import net.sergeych.crypto2.Seal.Companion.create import net.sergeych.crypto2.Seal.Companion.create
import net.sergeych.utools.now import net.sergeych.utools.now
import kotlin.time.Duration.Companion.seconds
/** /**
* Extended public-key signature. * Extended public-key signature.
@ -67,7 +78,7 @@ class Seal(
*/ */
fun verify(message: UByteArray) { fun verify(message: UByteArray) {
val n = now() val n = now()
if (createdAt > n) throw IllegalSignatureException("signature's timestamp in the future") if (createdAt - 45.seconds > n) throw IllegalSignatureException("signature's timestamp in the future: $createdAt / $n")
expiresAt?.let { expiresAt?.let {
if (n >= it) throw ExpiredSignatureException("signature expired at $it") if (n >= it) throw ExpiredSignatureException("signature expired at $it")
} }
@ -98,7 +109,7 @@ class Seal(
* to check the authenticity of the arbitrary [message] using a public key, [VerifyingPublicKey] * to check the authenticity of the arbitrary [message] using a public key, [VerifyingPublicKey]
* instance, using public-key signing algorithms. * instance, using public-key signing algorithms.
* *
* Unlike a regular binary signature, Seal contains the signer's [publicKey], and also * Unlike a regular binary signature, Seal contains the signer's [EncryptingPublicKey], and also
* [createdAt] and [expiresAt] fields which are also signed and are guaranteed to be non-tampered * [createdAt] and [expiresAt] fields which are also signed and are guaranteed to be non-tampered
* if the [isValid] returns true (or [verify] does not throw). See [isExpired]. * if the [isValid] returns true (or [verify] does not throw). See [isExpired].
* *

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import kotlinx.datetime.Instant import kotlinx.datetime.Instant
@ -82,6 +92,7 @@ class SealedBox(
/** /**
* Unpack bipack-encoded payload * Unpack bipack-encoded payload
*/ */
@Suppress("unused")
inline fun <reified T>unpack(): T = BipackDecoder.decode(message) inline fun <reified T>unpack(): T = BipackDecoder.decode(message)
init { init {

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import com.ionspin.kotlin.crypto.box.Box import com.ionspin.kotlin.crypto.box.Box
@ -6,24 +16,28 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient import kotlinx.serialization.Transient
@Deprecated("Use DecryptingSecretKey instead",ReplaceWith("DecryptingSecretKey"))
typealias SecretKey = DecryptingSecretKey
/** /**
* The secret key used in public-key encryption; it is used to _decrypt_ data encrypted with its * The secret key used in public-key encryption; it is used to _decrypt_ data encrypted with its
* public counterpart, see [publicKey]. * public counterpart, see [EncryptingPublicKey].
*/ */
@Serializable @Serializable
@SerialName("encs") @SerialName("encs")
class SecretKey( class DecryptingSecretKey(
override val keyBytes: UByteArray, override val keyBytes: UByteArray,
@Transient @Transient
val _cachedPublicKey: PublicKey? = null, val _cachedPublicKey: EncryptingPublicKey? = null,
) : DecryptingKey, UniversalKey() { ) : DecryptingKey, UniversalKey() {
@Transient @Transient
override val label: String = "sec" override val label: String = "sec"
/** /**
* Decrypt with authentication checks the message which must have [Asymmetric.Message.senderPublicKey] set. * Decrypt with authentication checks the message which must have [Asymmetric.Message.senderPublicKey] set.
* Use [decryptWithSenderKey] otherwise. Note that the authenticated encryption is always use, even if * Use [decryptWithSenderKey] otherwise. Note that the authenticated encryption is always use, even if
* the [PublicKey.encryptAnonymousMessage] was used to create a message, if it is successfully decrypted, * the [EncryptingPublicKey.encryptAnonymousMessage] was used to create a message, if it is successfully decrypted,
* it is guaranteed that the message was not altered after creation. * it is guaranteed that the message was not altered after creation.
* *
* @throws DecryptionFailedException If the message is tampered (changed after creation) or was not intended for us, * @throws DecryptionFailedException If the message is tampered (changed after creation) or was not intended for us,
@ -35,20 +49,20 @@ class SecretKey(
* Decrypt using [senderPublicKey] as a sender key (overriding the [Asymmetric.Message.senderPublicKey] if set). * Decrypt using [senderPublicKey] as a sender key (overriding the [Asymmetric.Message.senderPublicKey] if set).
* See [decrypt] for more. * See [decrypt] for more.
*/ */
fun decryptWithSenderKey(message: Asymmetric.Message, senderPublicKey: PublicKey): UByteArray = fun decryptWithSenderKey(message: Asymmetric.Message, senderPublicKey: EncryptingPublicKey): UByteArray =
message.decryptWithSenderKey(senderPublicKey, this) message.decryptWithSenderKey(senderPublicKey, this)
@Transient @Transient
private var cachedPublicKey: PublicKey? = _cachedPublicKey private var cachedPublicKey: EncryptingPublicKey? = _cachedPublicKey
/** /**
* The corresponding public key * The corresponding public key
*/ */
val publicKey: PublicKey by lazy { val publicKey: EncryptingPublicKey by lazy {
if (cachedPublicKey != null) if (cachedPublicKey != null)
cachedPublicKey!! cachedPublicKey!!
else else
PublicKey(ScalarMultiplication.scalarMultiplicationBase(keyBytes)) EncryptingPublicKey(ScalarMultiplication.scalarMultiplicationBase(keyBytes))
.also { cachedPublicKey = it } .also { cachedPublicKey = it }
} }
@ -71,18 +85,18 @@ class SecretKey(
get() = 0 get() = 0
companion object { companion object {
data class KeyPair(val secretKey: SecretKey, val publicKey: PublicKey) data class KeyPair(val secretKey: DecryptingSecretKey, val publicKey: EncryptingPublicKey)
/** /**
* Generate a new random pair of public and secret keys. * Generate a new random pair of public and secret keys.
*/ */
fun generateKeys(): KeyPair { fun generateKeys(): KeyPair {
val p = Box.keypair() val p = Box.keypair()
val pk = PublicKey(p.publicKey) val pk = EncryptingPublicKey(p.publicKey)
return KeyPair(SecretKey(p.secretKey, pk), pk) return KeyPair(DecryptingSecretKey(p.secretKey, pk), pk)
} }
fun new(): SecretKey = generateKeys().secretKey fun new(): DecryptingSecretKey = generateKeys().secretKey
} }
} }

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import kotlinx.datetime.Instant import kotlinx.datetime.Instant

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import com.ionspin.kotlin.crypto.signature.Signature import com.ionspin.kotlin.crypto.signature.Signature

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import com.ionspin.kotlin.crypto.secretbox.SecretBox import com.ionspin.kotlin.crypto.secretbox.SecretBox

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -17,7 +27,7 @@ sealed class UniversalKey : KeyInstance {
/** /**
* Key ID positively identify key from the point of view of _decrypting or verifying_. So matching [VerifyingKey] * Key ID positively identify key from the point of view of _decrypting or verifying_. So matching [VerifyingKey]
* and [SigningKey] will have the same id, same as matching [PublicKey] and [SecretKey]. * and [SigningKey] will have the same id, same as matching [EncryptingPublicKey] and [DecryptingSecretKey].
* *
* KeyId is based on [BinaryId] which includes checksum (crc8) and magick number for additional security, * KeyId is based on [BinaryId] which includes checksum (crc8) and magick number for additional security,
* see [KeysmagicNumber]. * see [KeysmagicNumber].
@ -43,7 +53,7 @@ sealed class UniversalKey : KeyInstance {
} }
companion object { companion object {
fun newSecretKey() = SecretKey.new() fun newSecretKey() = DecryptingSecretKey.new()
fun newSigningKey() = SigningSecretKey.new() fun newSigningKey() = SigningSecretKey.new()
@Suppress("unused") @Suppress("unused")
@ -57,7 +67,7 @@ sealed class UniversalKey : KeyInstance {
val s = text.trim() val s = text.trim()
return when { return when {
s.startsWith("\uD83D\uDDDDpub#") || s.startsWith("pub#") -> s.startsWith("\uD83D\uDDDDpub#") || s.startsWith("pub#") ->
PublicKey.parse(s) EncryptingPublicKey.parse(s)
s.startsWith("\uD83D\uDDDDver#") || s.startsWith("ver#") -> s.startsWith("\uD83D\uDDDDver#") || s.startsWith("ver#") ->
VerifyingPublicKey.parse(s) VerifyingPublicKey.parse(s)
else -> { else -> {

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
@ -14,7 +24,7 @@ import kotlinx.serialization.Transient
@SerialName("uprv") @SerialName("uprv")
class UniversalPrivateKey( class UniversalPrivateKey(
val signingKey: SigningSecretKey, val signingKey: SigningSecretKey,
val decryptingKey: SecretKey val decryptingKey: DecryptingSecretKey
) : UniversalKey(), DecryptingKey by decryptingKey, SigningKey by signingKey { ) : UniversalKey(), DecryptingKey by decryptingKey, SigningKey by signingKey {
override val keyBytes by lazy { signingKey.keyBytes + decryptingKey.keyBytes } override val keyBytes by lazy { signingKey.keyBytes + decryptingKey.keyBytes }
@ -42,6 +52,6 @@ class UniversalPrivateKey(
* Generate 2 new random keys (4 key pairs under the hood) to securely signd and * Generate 2 new random keys (4 key pairs under the hood) to securely signd and
* decrypt data. * decrypt data.
*/ */
fun new() = UniversalPrivateKey(SigningSecretKey.new(), SecretKey.new()) fun new() = UniversalPrivateKey(SigningSecretKey.new(), DecryptingSecretKey.new())
} }
} }

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
@ -15,7 +25,7 @@ import kotlinx.serialization.Transient
@SerialName("upub") @SerialName("upub")
class UniversalPublicKey( class UniversalPublicKey(
val verifyingKey: VerifyingPublicKey, val verifyingKey: VerifyingPublicKey,
val encryptingKey: PublicKey val encryptingKey: EncryptingPublicKey
): UniversalKey(), VerifyingKey by verifyingKey, EncryptingKey by encryptingKey{ ): UniversalKey(), VerifyingKey by verifyingKey, EncryptingKey by encryptingKey{
override val keyBytes by lazy { verifyingKey.keyBytes + encryptingKey.keyBytes } override val keyBytes by lazy { verifyingKey.keyBytes + encryptingKey.keyBytes }

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -38,7 +48,7 @@ class UniversalRing(
/** /**
* Find a key of the specified type that matches the id. In general, you require key implementations like * Find a key of the specified type that matches the id. In general, you require key implementations like
* [SecretKey], [PublicKey], [VerifyingPublicKey], [SigningSecretKey] and [SymmetricKey], * [DecryptingSecretKey], [EncryptingPublicKey], [VerifyingPublicKey], [SigningSecretKey] and [SymmetricKey],
* or just key interfaces: [EncryptingKey], [DecryptingKey], [SigningKey] and [VerifyingKey]. * or just key interfaces: [EncryptingKey], [DecryptingKey], [SigningKey] and [VerifyingKey].
* *
* Note that key interfaces are not serializable as for now, you should try to cast to a serializable * Note that key interfaces are not serializable as for now, you should try to cast to a serializable

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
interface VerifyingKey: KeyInstance { interface VerifyingKey: KeyInstance {

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import com.ionspin.kotlin.crypto.signature.InvalidSignatureException import com.ionspin.kotlin.crypto.signature.InvalidSignatureException

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
/** /**

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.crypto2 package net.sergeych.crypto2
import com.ionspin.kotlin.crypto.pwhash.* import com.ionspin.kotlin.crypto.pwhash.*

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
@file:Suppress("unused") @file:Suppress("unused")
package net.sergeych.crypto2 package net.sergeych.crypto2

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
@file:Suppress("unused") @file:Suppress("unused")
package net.sergeych.crypto2 package net.sergeych.crypto2

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.tools package net.sergeych.tools
@Suppress("unused") @Suppress("unused")

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.tools package net.sergeych.tools
import net.sergeych.synctools.ProtectedOp import net.sergeych.synctools.ProtectedOp
@ -5,7 +15,7 @@ import net.sergeych.synctools.invoke
/** /**
* Multiplatform (JS and battery included) atomically mutable value. * Multiplatform (JS and battery included) atomically mutable value.
* Actual value can be either changed in a block of [mutuate] when * Actual value can be either changed in a block of [mutate] when
* new value _depends on the current value_ or use a same [value] * new value _depends on the current value_ or use a same [value]
* property that is thread-safe where there are threads and just safe * property that is thread-safe where there are threads and just safe
* otherwise ;) * otherwise ;)

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
@file:Suppress("unused") @file:Suppress("unused")
package net.sergeych.tools package net.sergeych.tools

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.tools package net.sergeych.tools
import net.sergeych.bipack.BipackDecoder import net.sergeych.bipack.BipackDecoder

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
@file:Suppress("unused") @file:Suppress("unused")
package net.sergeych.utools package net.sergeych.utools

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package net.sergeych.utools package net.sergeych.utools
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
@file:Suppress("unused") @file:Suppress("unused")
package net.sergeych.utools package net.sergeych.utools

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package org.komputing.khash.keccak package org.komputing.khash.keccak
import com.ionspin.kotlin.bignum.integer.BigInteger import com.ionspin.kotlin.bignum.integer.BigInteger

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
@file:Suppress("unused") @file:Suppress("unused")
package org.komputing.khash.keccak package org.komputing.khash.keccak

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
package org.komputing.khash.keccak.extensions package org.komputing.khash.keccak.extensions
/** /**

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
@file:Suppress("unused") @file:Suppress("unused")
package org.komputing.khash.keccak.extensions package org.komputing.khash.keccak.extensions

View File

@ -1,5 +1,21 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
import kotlinx.coroutines.test.runTest
import net.sergeych.bintools.toDump
import net.sergeych.bipack.BipackEncoder
import net.sergeych.crypto2.BinaryId import net.sergeych.crypto2.BinaryId
import net.sergeych.crypto2.ByteChunk
import net.sergeych.crypto2.initCrypto
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals import kotlin.test.assertEquals
class BinaryIdTest { class BinaryIdTest {
@ -13,4 +29,16 @@ class BinaryIdTest {
assertEquals(4, a.id.size) assertEquals(4, a.id.size)
} }
@Test
fun testByteChunkSizes() = runTest {
initCrypto()
val x = ByteChunk.random(3)
assertEquals(3, x.data.size)
assertEquals(3, x.toByteArray().size)
assertEquals(3, x.toUByteArray().size)
println(BipackEncoder.encode(x).toDump())
assertEquals(4, BipackEncoder.encode(x).size)
assertContentEquals(BipackEncoder.encode(x.toByteArray()), BipackEncoder.encode(x))
}
} }

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
import com.ionspin.kotlin.crypto.util.encodeToUByteArray import com.ionspin.kotlin.crypto.util.encodeToUByteArray
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import kotlinx.datetime.Clock import kotlinx.datetime.Clock

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import net.sergeych.crypto2.KDF import net.sergeych.crypto2.KDF
import net.sergeych.crypto2.initCrypto import net.sergeych.crypto2.initCrypto

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
import com.ionspin.kotlin.crypto.util.decodeFromUByteArray import com.ionspin.kotlin.crypto.util.decodeFromUByteArray
import com.ionspin.kotlin.crypto.util.encodeToUByteArray import com.ionspin.kotlin.crypto.util.encodeToUByteArray
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
@ -177,7 +187,7 @@ class KeysTest {
// println(sk0.publicKey) // println(sk0.publicKey)
val j = Json { prettyPrint = true } val j = Json { prettyPrint = true }
val sk1 = j.decodeFromString<SecretKey>(j.encodeToString(sk0)) val sk1 = j.decodeFromString<DecryptingSecretKey>(j.encodeToString(sk0))
assertEquals(sk0, sk1) assertEquals(sk0, sk1)
assertEquals(pk0, sk1.publicKey) assertEquals(pk0, sk1.publicKey)
// println(j.encodeToString(sk1)) // println(j.encodeToString(sk1))
@ -206,9 +216,9 @@ class KeysTest {
assertEquals(usy2, usy1) assertEquals(usy2, usy1)
assertFalse { usy1 == usy3 } assertFalse { usy1 == usy3 }
val sk1 = SecretKey.new() val sk1 = DecryptingSecretKey.new()
val sk2 = SecretKey(sk1.keyBytes) val sk2 = DecryptingSecretKey(sk1.keyBytes)
val sk3 = SecretKey.new() val sk3 = DecryptingSecretKey.new()
assertEquals(sk1, sk2) assertEquals(sk1, sk2)
assertEquals(sk2, sk1) assertEquals(sk2, sk1)
@ -408,13 +418,13 @@ class KeysTest {
@Test @Test
fun testEncodedSizes2() = runTest { fun testEncodedSizes2() = runTest {
initCrypto() initCrypto()
val x = SecretKey.new() val x = DecryptingSecretKey.new()
// println("key bytes: ${x.keyBytes.size}:\n${x.keyBytes.toDump()}") // println("key bytes: ${x.keyBytes.size}:\n${x.keyBytes.toDump()}")
val y = BipackEncoder.encode(x) val y = BipackEncoder.encode(x)
// println("packed: ${y.size}: ${y.toDump()}") // println("packed: ${y.size}: ${y.toDump()}")
assertTrue { x.keyBytes.size + 5 > y.size } assertTrue { x.keyBytes.size + 5 > y.size }
assertEquals(x, BipackDecoder.decode<SecretKey>(y)) assertEquals(x, BipackDecoder.decode<DecryptingSecretKey>(y))
assertContentEquals(x.keyBytes, BipackDecoder.decode<SecretKey>(y).keyBytes) assertContentEquals(x.keyBytes, BipackDecoder.decode<DecryptingSecretKey>(y).keyBytes)
} }
@Test @Test
@ -422,7 +432,7 @@ class KeysTest {
initCrypto() initCrypto()
val k1 = SigningSecretKey.new() val k1 = SigningSecretKey.new()
val k2 = k1.verifyingKey val k2 = k1.verifyingKey
val k3 = SecretKey.new() val k3 = DecryptingSecretKey.new()
val k4 = k3.publicKey val k4 = k3.publicKey
val k5 = UniversalPrivateKey.new() val k5 = UniversalPrivateKey.new()

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import net.sergeych.crypto2.PBKD import net.sergeych.crypto2.PBKD
import net.sergeych.crypto2.initCrypto import net.sergeych.crypto2.initCrypto

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import kotlinx.datetime.Instant import kotlinx.datetime.Instant
import net.sergeych.crypto2.initCrypto import net.sergeych.crypto2.initCrypto

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
import com.ionspin.kotlin.crypto.util.encodeToUByteArray import com.ionspin.kotlin.crypto.util.encodeToUByteArray
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import net.sergeych.bintools.toDump import net.sergeych.bintools.toDump
@ -17,7 +27,7 @@ class RingTest {
assertEquals(y1, y2) assertEquals(y1, y2)
val e1 = Asymmetric.newSecretKey() val e1 = Asymmetric.newSecretKey()
val e2: SecretKey = BipackDecoder.decode(BipackEncoder.encode(e1)) val e2: DecryptingSecretKey = BipackDecoder.decode(BipackEncoder.encode(e1))
assertEquals(e1, e2) assertEquals(e1, e2)
val k1 = SymmetricKey("1234567890Hello,dolly.here-we-go".encodeToUByteArray()) as UniversalKey val k1 = SymmetricKey("1234567890Hello,dolly.here-we-go".encodeToUByteArray()) as UniversalKey
@ -154,14 +164,14 @@ class RingTest {
var r1 = ra + rb + rc + rd var r1 = ra + rb + rc + rd
assertEquals(a, r1.findKey<SecretKey>(a.id)) assertEquals(a, r1.findKey<DecryptingSecretKey>(a.id))
assertEquals(a, r1.keyByTag<UniversalKey>("foo_a")) assertEquals(a, r1.keyByTag<UniversalKey>("foo_a"))
assertEquals(b, r1.findKey<SigningKey>(b.id)) assertEquals(b, r1.findKey<SigningKey>(b.id))
assertEquals(c, r1.findById(c.id).first()) assertEquals(c, r1.findById(c.id).first())
r1 = UniversalRing.join(listOf(ra, rb, rc, rd)) r1 = UniversalRing.join(listOf(ra, rb, rc, rd))
assertEquals(a, r1.findKey<SecretKey>(a.id)) assertEquals(a, r1.findKey<DecryptingSecretKey>(a.id))
assertEquals(a, r1.keyByTag<UniversalKey>("foo_a")) assertEquals(a, r1.keyByTag<UniversalKey>("foo_a"))
assertEquals(b, r1.findKey<SigningKey>(b.id)) assertEquals(b, r1.findKey<SigningKey>(b.id))
assertEquals(c, r1.findById(c.id).first()) assertEquals(c, r1.findById(c.id).first())

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import net.sergeych.bintools.encodeToHex import net.sergeych.bintools.encodeToHex
import net.sergeych.crypto2.BinaryId import net.sergeych.crypto2.BinaryId

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
import kotlin.test.fail import kotlin.test.fail
inline fun <reified T: Throwable>assertThrows(f: ()->Unit): T { inline fun <reified T: Throwable>assertThrows(f: ()->Unit): T {

View File

@ -1,3 +1,13 @@
/*
* Copyright (c) 2025. Sergey S. Chernov - All Rights Reserved
*
* You may use, distribute and modify this code under the
* terms of the private license, which you must obtain from the author
*
* To obtain the license, contact the author: https://t.me/real_sergeych or email to
* real dot sergeych at gmail.
*/
import net.sergeych.bipack.BipackDecoder import net.sergeych.bipack.BipackDecoder
import net.sergeych.bipack.BipackEncoder import net.sergeych.bipack.BipackEncoder