Container started
This commit is contained in:
parent
e4e3b5ba8b
commit
e2916d0fe2
@ -7,6 +7,7 @@ import com.ionspin.kotlin.crypto.scalarmult.ScalarMultiplication
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
import net.sergeych.bipack.BipackDecoder
|
||||
import net.sergeych.bipack.BipackEncoder
|
||||
import net.sergeych.crypto2.Asymmetric.Message
|
||||
import net.sergeych.crypto2.Asymmetric.PublicKey
|
||||
import net.sergeych.crypto2.Asymmetric.SecretKey
|
||||
@ -32,7 +33,7 @@ object Asymmetric {
|
||||
/**
|
||||
* Encrypted message holder.
|
||||
*
|
||||
* Do not instantiate it directly, use [SecretKey.encrypt], [PublicKey.encryptAnonymously] or [createMessage]
|
||||
* Do not instantiate it directly, use [PublicKey.encryptMessage], [PublicKey.encryptAnonymousMessage], etc.
|
||||
* instead. Also [SecretKey.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.
|
||||
@ -42,13 +43,12 @@ object Asymmetric {
|
||||
class Message(
|
||||
private val nonce: UByteArray,
|
||||
private val encryptedMessage: UByteArray,
|
||||
val senderPublicKey: PublicKey? = null,
|
||||
val senderPublicKey: PublicKey,
|
||||
) {
|
||||
/**
|
||||
* Decrypt the message, same as [SecretKey.decrypt]
|
||||
*/
|
||||
fun decrypt(recipientKey: SecretKey): UByteArray {
|
||||
check(senderPublicKey != null)
|
||||
return decryptWithSenderKey(senderPublicKey, recipientKey)
|
||||
}
|
||||
|
||||
@ -58,11 +58,15 @@ object Asymmetric {
|
||||
*/
|
||||
fun decryptWithSenderKey(senderKey: PublicKey, recipientKey: SecretKey): UByteArray {
|
||||
return try {
|
||||
Box.openEasy(encryptedMessage, nonce, senderKey.keyBytes, recipientKey.keyBytes)
|
||||
WithFill.decode(
|
||||
Box.openEasy(encryptedMessage, nonce, senderKey.keyBytes, recipientKey.keyBytes)
|
||||
)
|
||||
} catch (_: BoxCorruptedOrTamperedDataException) {
|
||||
throw DecryptionFailedException()
|
||||
}
|
||||
}
|
||||
|
||||
val encoded: UByteArray by lazy { BipackEncoder.encode(this).toUByteArray() }
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,30 +76,27 @@ object Asymmetric {
|
||||
* 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.
|
||||
*
|
||||
* When it is important not to provide senders' key, use [PublicKey.encryptAnonymously].
|
||||
* When it is important not to provide senders' key, use [PublicKey.encryptAnonymousMessage].
|
||||
*
|
||||
* @param from the senders' secret key.
|
||||
* @param recipient the recipients' public key.
|
||||
* @param plainData data to encrypt
|
||||
* @param excludeSenderKey if set to true, senders' public key will not be included in the message.
|
||||
* In this case, the recipient must know it from other sources to be able to decrypt the message.
|
||||
*/
|
||||
fun createMessage(
|
||||
private fun createMessage(
|
||||
from: SecretKey, recipient: PublicKey, plainData: UByteArray,
|
||||
excludeSenderKey: Boolean = false,
|
||||
nonce: UByteArray = randomNonce(),
|
||||
): Message {
|
||||
val nonce = randomNonce()
|
||||
return Message(
|
||||
nonce,
|
||||
Box.easy(plainData, nonce, recipient.keyBytes, from.keyBytes),
|
||||
if (excludeSenderKey) null else from.publicKey
|
||||
from.publicKey
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* The generated key pair. See [generateKeys]
|
||||
*/
|
||||
data class KeyPair(val secretKey: SecretKey, val senderKey: PublicKey)
|
||||
data class KeyPair(val secretKey: SecretKey, val publicKey: PublicKey)
|
||||
|
||||
/**
|
||||
* Generate a new random pair of public and secret keys.
|
||||
@ -114,11 +115,18 @@ object Asymmetric {
|
||||
val nonceBytesLength = crypto_box_NONCEBYTES
|
||||
|
||||
/**
|
||||
* The public key used as the recipient for [Message] (see [SecretKey.encrypt], etc.). It also
|
||||
* could be used to encrypt anonymous messages with [encryptAnonymously]
|
||||
* The public key: [encryptMessage] so only a secret key owner can read it. Allows
|
||||
* anonymous [encryptAnonymousMessage] and signed [encryptMessage] encryption.
|
||||
*
|
||||
* Anonymous encryption is very slow in comparison.
|
||||
*/
|
||||
@Serializable
|
||||
class PublicKey(val keyBytes: UByteArray) {
|
||||
|
||||
val tag: KeyTag by lazy {
|
||||
KeyTag(KeysMagickNumbers.defaultAssymmetric, blake2b(keyBytes))
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is PublicKey) return false
|
||||
@ -126,19 +134,57 @@ object Asymmetric {
|
||||
return keyBytes contentEquals other.keyBytes
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return keyBytes.hashCode()
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an anonymous message that could be decrypted only with the [SecretKey] that corresponds this.
|
||||
* Anonymous message uses one-time secret key, the public part of which is included into the
|
||||
* [Message], so the sender could not be identified.
|
||||
*
|
||||
* __Anonymous encryption is much slower__ as it generates new keys every time, use [encryptMessage]
|
||||
* when possible
|
||||
*
|
||||
* The authentication is used despite the anonymity, and the fact of the successful decryption
|
||||
* proves that the message was not altered after creation.
|
||||
*/
|
||||
fun encryptAnonymously(plainData: UByteArray): Message =
|
||||
createMessage(generateKeys().secretKey, this, plainData)
|
||||
fun encryptAnonymousMessage(plainData: UByteArray, randomFill: IntRange? = null): Message =
|
||||
encryptMessage(plainData,randomFill=randomFill)
|
||||
|
||||
/**
|
||||
* Anonymous encryption, see [encryptAnonymousMessage], to binary data. Sender could not be identified.
|
||||
*/
|
||||
@Suppress("unused")
|
||||
fun encrypt(plainData: UByteArray, randomFill: IntRange? = null): UByteArray =
|
||||
encryptMessage(plainData, randomFill = randomFill).encoded
|
||||
|
||||
/**
|
||||
* Universal public-key encryption. Note that message authenticity is guaranteed if the decryption is successful
|
||||
* whether [senderKey] is provider, the latter only allow to positively identify the sender.
|
||||
*
|
||||
* @param plainData data to encrypt
|
||||
* @param nonce allows specifying exact nonce, default to random (safe)
|
||||
* @param senderKey key to authenticate sending party. It is safe and much faster to specify it,
|
||||
* otherwise an anonymous key will be created for each encryption, also safe and anonymous, but slow.
|
||||
*/
|
||||
fun encryptMessage(
|
||||
plainData: UByteArray,
|
||||
nonce: UByteArray = randomNonce(),
|
||||
senderKey: SecretKey = randomSecretKey(),
|
||||
randomFill: IntRange? = null,
|
||||
) = createMessage(senderKey, this, WithFill.encode(plainData, randomFill), nonce)
|
||||
|
||||
/**
|
||||
* 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]
|
||||
* was the author and the message was not altered.
|
||||
*/
|
||||
fun encryptMessage(plainData: UByteArray,
|
||||
senderKey: SecretKey,
|
||||
randomFill: IntRange? = null): Message =
|
||||
createMessage(senderKey, this, WithFill.encode(plainData, randomFill))
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return keyBytes.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -151,19 +197,10 @@ object Asymmetric {
|
||||
val _cachedPublicKey: PublicKey? = null,
|
||||
) : DecryptingKey {
|
||||
|
||||
/**
|
||||
* Encrypt the message for [recipient]. The [Message] will include the our [publicKey]
|
||||
* and thus ready to be decrypted.
|
||||
*
|
||||
* The message is authenticated by this secret key.
|
||||
*/
|
||||
fun encrypt(plainData: UByteArray, recipient: PublicKey): Message =
|
||||
createMessage(this, recipient, plainData)
|
||||
|
||||
/**
|
||||
* Decrypt with authentication checks the message which must have [Message.senderPublicKey] set.
|
||||
* Use [decryptWithSenderKey] otherwise. Note that the authenticated encryption is always use, even if
|
||||
* the [PublicKey.encryptAnonymously] was used to create a message, if it is successfully decrypted,
|
||||
* the [PublicKey.encryptAnonymousMessage] was used to create a message, if it is successfully decrypted,
|
||||
* 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,
|
||||
@ -213,9 +250,7 @@ object Asymmetric {
|
||||
return message.decrypt(this)
|
||||
}
|
||||
|
||||
override val decryptingTag: KeyTag by lazy {
|
||||
KeyTag(KeysMagickNumbers.defaultAssymmetric, blake2b(publicKey.keyBytes))
|
||||
}
|
||||
override val tag: KeyTag by lazy { publicKey.tag }
|
||||
|
||||
override val nonceBytesLength: Int
|
||||
get() = 0
|
@ -1,9 +1,148 @@
|
||||
//package net.sergeych.crypto2
|
||||
//
|
||||
//import kotlinx.serialization.Serializable
|
||||
//
|
||||
//@Serializable
|
||||
//sealed class Container {
|
||||
package net.sergeych.crypto2
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
import net.sergeych.bipack.BipackDecoder
|
||||
import net.sergeych.bipack.BipackEncoder
|
||||
|
||||
/*
|
||||
The problem with container is the following. When we encrypt it with asymmetric key,
|
||||
we provide public key as the recipient. But public key alone is not effective
|
||||
as it is restricted to anonymous encryption which is very slow.
|
||||
|
||||
We might need an alternative to specify the (sender key,recipient key) pair also. We need a good
|
||||
solution for it.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@Serializable
|
||||
sealed class Container {
|
||||
|
||||
class InvalidContainerException : Crypto2Exception("the container is invalid")
|
||||
|
||||
abstract fun decryptWith(keyRing: UniversalRing): UByteArray?
|
||||
|
||||
fun decryptWith(vararg decryptingKeys: DecryptingKey): UByteArray? =
|
||||
decryptWith(UniversalRing(*decryptingKeys))
|
||||
|
||||
@Transient
|
||||
var decryptedData: UByteArray? = null
|
||||
|
||||
val isDecrypted: Boolean get() = decryptedData != null
|
||||
|
||||
@Serializable
|
||||
@SerialName("1")
|
||||
class Single(val keyTag: KeyTag, val encryptedMessage: UByteArray) : Container() {
|
||||
override fun decryptWith(keyRing: UniversalRing): UByteArray? {
|
||||
decryptedData?.let { return it }
|
||||
for (k in keyRing) {
|
||||
if (k.tag == keyTag) {
|
||||
kotlin.runCatching { k.decrypt(encryptedMessage) }.getOrNull()?.let {
|
||||
decryptedData = it
|
||||
return it
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@SerialName("*")
|
||||
class Multi(val encryptedKeys: List<EncryptedKey>, val encryptedMessage: UByteArray) : Container() {
|
||||
@Serializable
|
||||
class EncryptedKey(val tag: KeyTag, val cipherData: UByteArray)
|
||||
|
||||
private var mainKey: SymmetricKey? = null
|
||||
|
||||
override fun decryptWith(keyRing: UniversalRing): UByteArray? {
|
||||
decryptedData?.let { return it }
|
||||
for (key in keyRing) {
|
||||
val tag = key.tag
|
||||
for (encryptedKey in encryptedKeys) {
|
||||
if (tag == encryptedKey.tag) {
|
||||
kotlin.runCatching {
|
||||
BipackDecoder.decode<SymmetricKey>(
|
||||
key.decrypt(encryptedKey.cipherData).toByteArray()
|
||||
)
|
||||
}.getOrNull()?.let { k ->
|
||||
if (kotlin.runCatching { decryptedData = k.decrypt(encryptedKey.cipherData) }.isFailure)
|
||||
throw InvalidContainerException()
|
||||
mainKey = k
|
||||
}
|
||||
if (decryptedData != null) return decryptedData
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val encoded: UByteArray by lazy {
|
||||
BipackEncoder.encode(this).toUByteArray()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
class Builder internal constructor(private val plainData: UByteArray) {
|
||||
private val plainKeys = mutableListOf<EncryptingKey>()
|
||||
private val keyPairs = mutableListOf<Pair<Asymmetric.SecretKey?,Asymmetric.PublicKey>>()
|
||||
private var fillRange: IntRange? = null
|
||||
|
||||
fun key(vararg keys: EncryptingKey) { plainKeys.addAll(keys) }
|
||||
|
||||
fun key(vararg pairs: Pair<Asymmetric.SecretKey,Asymmetric.PublicKey>) {
|
||||
keyPairs.addAll(pairs)
|
||||
}
|
||||
|
||||
fun key(vararg publicKeys: Asymmetric.PublicKey) {
|
||||
keyPairs.addAll(publicKeys.map { null to it })
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
fun fill(range: IntRange) {
|
||||
require(range.first >= 0 ) { "range must be positive"}
|
||||
fillRange = range
|
||||
}
|
||||
|
||||
fun build(): Container {
|
||||
return when( plainKeys.size + keyPairs.size ) {
|
||||
0 -> throw IllegalArgumentException("Container needs at least one key")
|
||||
1 -> {
|
||||
plainKeys.firstOrNull()?.let {
|
||||
Single(it.tag, it.encrypt(plainData, fillRange))
|
||||
} ?: run {
|
||||
val (sk, pk) = keyPairs.first()
|
||||
Single(pk.tag, pk.encryptMessage(plainData,
|
||||
senderKey = sk ?: Asymmetric.randomSecretKey(),
|
||||
randomFill = fillRange).encoded)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
TODO("multikey")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun create(plainData: UByteArray,builder: Builder.()->Unit) =
|
||||
Builder(plainData).also { it.builder() }.build()
|
||||
|
||||
fun create(plainData: UByteArray, vararg keys: EncryptingKey): Container =
|
||||
create(plainData) { key(*keys) }
|
||||
|
||||
fun create(plainData: UByteArray, vararg keys: Pair<Asymmetric.SecretKey,Asymmetric.PublicKey>) =
|
||||
create(plainData) { key(*keys) }
|
||||
|
||||
fun decode(encoded: UByteArray): Container {
|
||||
return BipackDecoder.decode(encoded.toByteArray())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//
|
||||
//
|
||||
// /**
|
||||
|
@ -28,7 +28,7 @@ interface DecryptingKey : NonceBased {
|
||||
|
||||
fun decryptString(cipherData: UByteArray): String = decrypt(cipherData).decodeFromUByteArray()
|
||||
|
||||
val decryptingTag: KeyTag
|
||||
val tag: KeyTag
|
||||
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ interface EncryptingKey : NonceBased {
|
||||
fun encrypt(plainText: String,randomFill: IntRange? = null): UByteArray =
|
||||
encrypt(plainText.encodeToUByteArray(),randomFill)
|
||||
|
||||
val encryptingTag: KeyTag
|
||||
val tag: KeyTag
|
||||
|
||||
fun encryptWithNonce(plainData: UByteArray, nonce: UByteArray, randomFill: IntRange? = null): UByteArray
|
||||
}
|
||||
|
@ -47,11 +47,14 @@ class SafeKeyExchange {
|
||||
@Suppress("unused")
|
||||
val sessionTag: UByteArray by lazy {
|
||||
if (!isClient)
|
||||
blake2b(decryptingTag.tag + encryptingTag.tag)
|
||||
blake2b(tag.tag + tag.tag)
|
||||
else
|
||||
blake2b(encryptingTag.tag + decryptingTag.tag)
|
||||
blake2b(tag.tag + tag.tag)
|
||||
}
|
||||
|
||||
override val tag: KeyTag
|
||||
get() = if( isClient ) sendingKey.tag else receivingKey.tag
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is SessionKey) return false
|
||||
|
@ -3,8 +3,6 @@ package net.sergeych.crypto2
|
||||
import com.ionspin.kotlin.crypto.secretbox.SecretBox
|
||||
import com.ionspin.kotlin.crypto.secretbox.crypto_secretbox_NONCEBYTES
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.sergeych.bipack.BipackDecoder
|
||||
import net.sergeych.bipack.BipackEncoder
|
||||
|
||||
/**
|
||||
* Symmetric key implements authenticated encrypting with random nonce and optional fill.
|
||||
@ -32,36 +30,18 @@ class SymmetricKey(
|
||||
val nonce: UByteArray,
|
||||
)
|
||||
|
||||
/**
|
||||
* @suppress
|
||||
* add some random data to the end of the plain message
|
||||
*/
|
||||
@Serializable
|
||||
data class WithFill(
|
||||
val data: UByteArray,
|
||||
val safetyFill: UByteArray? = null,
|
||||
)
|
||||
|
||||
override fun encryptWithNonce(plainData: UByteArray, nonce: UByteArray, randomFill: IntRange?): UByteArray {
|
||||
require(nonce.size == nonceByteLength)
|
||||
|
||||
val fill = randomFill?.let {
|
||||
require(it.start >= 0)
|
||||
randomUBytes(randomInt(it))
|
||||
}
|
||||
val filled = BipackEncoder.encode(WithFill(plainData, fill))
|
||||
return SecretBox.easy(filled.toUByteArray(), nonce, keyBytes)
|
||||
return SecretBox.easy(WithFill.encode(plainData, randomFill), nonce, keyBytes)
|
||||
}
|
||||
|
||||
override val nonceBytesLength: Int = nonceByteLength
|
||||
|
||||
override val encryptingTag by lazy { KeyTag(KeysMagickNumbers.defaultSymmetric,blake2b3l(keyBytes)) }
|
||||
override val decryptingTag get() = encryptingTag
|
||||
override val tag by lazy { KeyTag(KeysMagickNumbers.defaultSymmetric,blake2b3l(keyBytes)) }
|
||||
|
||||
override fun decryptWithNonce(cipherData: UByteArray, nonce: UByteArray): UByteArray =
|
||||
protectDecryption {
|
||||
BipackDecoder.decode<WithFill>(SecretBox.openEasy(cipherData, nonce, keyBytes).toByteArray())
|
||||
.data
|
||||
WithFill.decode(SecretBox.openEasy(cipherData, nonce, keyBytes))
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
|
@ -7,7 +7,7 @@ import kotlinx.serialization.Transient
|
||||
@Serializable
|
||||
sealed class UniversalKey : DecryptingKey {
|
||||
|
||||
abstract val tag: KeyTag
|
||||
// abstract val tag: KeyTag
|
||||
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ sealed class UniversalKey : DecryptingKey {
|
||||
@SerialName("sy")
|
||||
data class Symmetric(val key: SymmetricKey) : UniversalKey(), EncryptingKey by key, DecryptingKey by key {
|
||||
@Transient
|
||||
override val tag: KeyTag = key.encryptingTag
|
||||
override val tag: KeyTag = key.tag
|
||||
|
||||
@Transient
|
||||
override val nonceBytesLength: Int = key.nonceBytesLength
|
||||
@ -28,7 +28,7 @@ sealed class UniversalKey : DecryptingKey {
|
||||
data class Session(val key: SafeKeyExchange.SessionKey) : UniversalKey(), EncryptingKey by key,
|
||||
DecryptingKey by key {
|
||||
@Transient
|
||||
override val tag: KeyTag = key.encryptingTag
|
||||
override val tag: KeyTag = key.tag
|
||||
@Transient
|
||||
override val nonceBytesLength: Int = key.nonceBytesLength
|
||||
}
|
||||
@ -36,7 +36,7 @@ sealed class UniversalKey : DecryptingKey {
|
||||
@Serializable
|
||||
@SerialName("se")
|
||||
data class Secret(val key: Asymmetric.SecretKey) : UniversalKey(), DecryptingKey by key {
|
||||
override val tag: KeyTag by lazy { key.decryptingTag }
|
||||
override val tag: KeyTag by lazy { key.tag }
|
||||
override fun toString() = "U.Sec:$tag"
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ 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()
|
||||
|
||||
|
37
src/commonMain/kotlin/net/sergeych/crypto2/WithFill.kt
Normal file
37
src/commonMain/kotlin/net/sergeych/crypto2/WithFill.kt
Normal file
@ -0,0 +1,37 @@
|
||||
package net.sergeych.crypto2
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.sergeych.bipack.BipackDecoder
|
||||
import net.sergeych.bipack.BipackEncoder
|
||||
import net.sergeych.crypto2.WithFill.Companion.decode
|
||||
import net.sergeych.crypto2.WithFill.Companion.encode
|
||||
|
||||
/**
|
||||
* Utility class to optionally extend a message with random bytes added _before the message bytes_ that
|
||||
* reduces chances to effective cryptanalysis from the first block. Use
|
||||
* [encode] and [decode] to process filled data.
|
||||
*/
|
||||
@Serializable
|
||||
class WithFill private constructor(
|
||||
@Suppress("unused")
|
||||
val safetyFill: UByteArray = ubyteArrayOf(),
|
||||
val data: UByteArray,
|
||||
) {
|
||||
companion object {
|
||||
|
||||
/**
|
||||
* Create binary data with specified fill
|
||||
*/
|
||||
fun encode(data: UByteArray,range: IntRange? = null) =
|
||||
BipackEncoder.encode(WithFill(range?.let {
|
||||
require(range.first >= 0) { "range should not be negative" }
|
||||
randomUBytes(randomInt(it))
|
||||
} ?: ubyteArrayOf(), data)).toUByteArray()
|
||||
|
||||
/**
|
||||
* extract binary data from filled
|
||||
*/
|
||||
fun decode(data: UByteArray): UByteArray =
|
||||
BipackDecoder.decode<WithFill>(data.toByteArray()).data
|
||||
}
|
||||
}
|
86
src/commonTest/kotlin/ContainerTest.kt
Normal file
86
src/commonTest/kotlin/ContainerTest.kt
Normal file
@ -0,0 +1,86 @@
|
||||
import com.ionspin.kotlin.crypto.util.encodeToUByteArray
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import net.sergeych.crypto2.Asymmetric
|
||||
import net.sergeych.crypto2.Container
|
||||
import net.sergeych.crypto2.SymmetricKey
|
||||
import net.sergeych.crypto2.initCrypto
|
||||
import kotlin.test.*
|
||||
|
||||
class ContainerTest {
|
||||
@Test
|
||||
fun testSingle() = runTest {
|
||||
initCrypto()
|
||||
val syk1 = SymmetricKey.random()
|
||||
val syk2 = SymmetricKey.random()
|
||||
val data = "sergeych, ohm many.".encodeToUByteArray()
|
||||
|
||||
val c = Container.create(data, syk1)
|
||||
assertFalse { c.isDecrypted }
|
||||
val c1 = Container.decode(c.encoded)
|
||||
assertFalse { c.isDecrypted }
|
||||
assertIs<Container.Single>(c)
|
||||
|
||||
assertNull(c1.decryptWith(syk2))
|
||||
val d = c1.decryptWith(syk2, syk1)
|
||||
assertNotNull(d)
|
||||
assertContentEquals(data, d)
|
||||
assertTrue { c1.isDecrypted }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSinglePair() = runTest {
|
||||
initCrypto()
|
||||
val p1 = Asymmetric.generateKeys()
|
||||
val p2 = Asymmetric.generateKeys()
|
||||
val p3 = Asymmetric.generateKeys()
|
||||
val data = "sergeych, ohm many.".encodeToUByteArray()
|
||||
|
||||
val c = Container.create(data, p1.secretKey to p2.publicKey)
|
||||
assertFalse { c.isDecrypted }
|
||||
val c1 = Container.decode(c.encoded)
|
||||
assertFalse { c.isDecrypted }
|
||||
assertIs<Container.Single>(c)
|
||||
|
||||
assertNull(c1.decryptWith(p3.secretKey))
|
||||
val d = c1.decryptWith(p3.secretKey, p2.secretKey)
|
||||
assertNotNull(d)
|
||||
assertContentEquals(data, d)
|
||||
assertTrue { c1.isDecrypted }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSingleAsymmetric() = runTest {
|
||||
initCrypto()
|
||||
// val p1 = Asymmetric.generateKeys()
|
||||
val p2 = Asymmetric.generateKeys()
|
||||
val p3 = Asymmetric.generateKeys()
|
||||
val data = "sergeych, ohm many.".encodeToUByteArray()
|
||||
|
||||
val c = Container.create(data) { key(p2.publicKey) }
|
||||
assertFalse { c.isDecrypted }
|
||||
val c1 = Container.decode(c.encoded)
|
||||
assertFalse { c.isDecrypted }
|
||||
assertIs<Container.Single>(c)
|
||||
|
||||
assertNull(c1.decryptWith(p3.secretKey))
|
||||
val d = c1.decryptWith(p3.secretKey, p2.secretKey)
|
||||
assertNotNull(d)
|
||||
assertContentEquals(data, d)
|
||||
assertTrue { c1.isDecrypted }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMultipleSymmetric() = runTest {
|
||||
initCrypto()
|
||||
val syk1 = SymmetricKey.random()
|
||||
val syk2 = SymmetricKey.random()
|
||||
// val syk3 = SymmetricKey.random()
|
||||
val data = "Translating the name 'Sergey Chernov' from Russian to archaic Sanskrit would be 'Ramo Krishna'"
|
||||
.encodeToUByteArray()
|
||||
|
||||
val c = Container.create(data, syk1, syk2)
|
||||
assertFalse { c.isDecrypted }
|
||||
val c1 = Container.decode(c.encoded)
|
||||
assertFalse { c1.isDecrypted }
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@ import com.ionspin.kotlin.crypto.util.encodeToUByteArray
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import net.sergeych.bipack.BipackEncoder
|
||||
import net.sergeych.crypto2.*
|
||||
import net.sergeych.utools.now
|
||||
import net.sergeych.utools.pack
|
||||
@ -140,25 +139,24 @@ class KeysTest {
|
||||
|
||||
val plain = "The fake vaccine kills".encodeToUByteArray()
|
||||
|
||||
var m = Asymmetric.createMessage(sk0, pk1, plain)
|
||||
var m = pk1.encryptMessage(plain, sk1)
|
||||
assertContentEquals(plain, m.decrypt(sk1))
|
||||
assertThrows<DecryptionFailedException> {
|
||||
assertContentEquals(plain, m.decrypt(sk2))
|
||||
}
|
||||
|
||||
m = pk2.encryptAnonymously(plain)
|
||||
m = pk2.encryptAnonymousMessage(plain)
|
||||
assertContentEquals(plain, m.decrypt(sk2))
|
||||
assertContentEquals(plain, sk2.decrypt(m))
|
||||
assertContentEquals(plain, sk2.decrypt(sk1.encrypt(plain, pk2)))
|
||||
// assertContentEquals(plain, sk2.decrypt(sk1.encrypt(plain, pk2)))
|
||||
assertThrows<DecryptionFailedException> {
|
||||
assertContentEquals(plain, m.decrypt(sk1))
|
||||
}
|
||||
|
||||
val x1 = BipackEncoder.encode(Asymmetric.createMessage(sk0, pk1, plain))
|
||||
val x2 = BipackEncoder.encode(Asymmetric.createMessage(sk0, pk1, plain))
|
||||
val x1 = pk1.encryptMessage(plain, sk1).encoded
|
||||
val x2 = pk1.encryptMessage(plain, sk1).encoded
|
||||
|
||||
assertFalse { x1 contentEquals x2 }
|
||||
|
||||
}
|
||||
@Test
|
||||
fun asymmetricKeySerializationTest() = runTest {
|
||||
|
@ -52,4 +52,9 @@ class RingTest {
|
||||
assertEquals(r, r2)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
fun testKeysWithSameTags() {
|
||||
// it should be able to keep keys with same tags
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user