fix #4 update data in container

This commit is contained in:
sergeych committed 2024-06-20 10:25:15 +07:00
1 parent a1561bc280
commit 165cd07353
2 files changed
+171 -51

No files matched your search

@@ -55,6 +55,47 @@ sealed class Container {
*/
val isDecrypted: Boolean get() = decryptedData != null
/**
* Add one or more recipients to the __decrypted__ container using a standard builder. Note that
* [Builder.fill] is not working in this case.
*/
fun addRecipients(builder: Builder.() -> Unit): Container =
if (this is Single) asOpenMulti.addRecipients(builder)
else {
Builder(this).apply(builder).build()
}
/**
* Add e key to the __decrypted__ container. The new container is also decrypted so you can add
* more keys, etc.
*/
operator fun plus(recipient: Asymmetric.PublicKey) = addRecipients { key(recipient) }
/**
* Add e key to the __decrypted__ container. The new container is also decrypted so you can add
* more keys, etc.
*/
operator fun plus(recipient: EncryptingKey) = addRecipients { key(recipient) }
/**
* Add e key to the __decrypted__ container. The new container is also decrypted so you can add
* more keys, etc.
*/
operator fun plus(pair: Pair<Asymmetric.SecretKey, Asymmetric.PublicKey>) = addRecipients { key(pair) }
abstract fun updateData(newPlainData: UByteArray,randomFill: IntRange?=null): Container
/**
* Binary encoded version. It is desirable to include [Container] as an object, though,
* especially when using custom serialization (Json, Boss, etc), it is serializable.
* Still, if you need it in binary form, this is a shortcut. You can use [decode] or call
* [BipackDecoder.decode] to deserialize the binary form.
*/
val encoded: UByteArray by lazy {
BipackEncoder.encode(this).toUByteArray()
}
/**
* @suppress
* Single-key variant, to conserve space it does not use the main key logic and just encrypts the data.
@@ -89,10 +130,10 @@ sealed class Container {
return null
}
internal val asOpenMulti: Container by lazy {
private fun reEncrypt(data: UByteArray? = null,f: Builder.()->Unit): Container {
check(isDecrypted) { "container should be decrypted" }
create(decryptedData!!) {
asOpenedMulti()
return create(data ?: decryptedData ?: throw IllegalArgumentException("no data is provided")) {
f()
// The encryption key is known if we just created the container
if (reEncryptionKey != null)
key(reEncryptionKey)
@@ -120,7 +161,17 @@ sealed class Container {
}
}
}
}
internal val asOpenMulti: Container by lazy {
reEncrypt { alwaysMulti() }
}
override fun updateData(newPlainData: UByteArray,randomFill: IntRange?): Container =
reEncrypt(newPlainData) {
randomFill?.let { fill(it) }
}
}
/**
@@ -133,7 +184,6 @@ sealed class Container {
val encryptedKeys: List<EncryptedKey>, val encryptedMessage: UByteArray,
@Transient internal var mainKey: SymmetricKey? = null,
@Transient internal var knownPlainData: UByteArray? = null,
) : Container() {
@Serializable
class EncryptedKey(val tag: KeyTag, val cipherData: UByteArray) {
@@ -176,44 +226,11 @@ sealed class Container {
}
return null
}
}
/**
* Add one or more recipients to the __decrypted__ container using a standard builder. Note that
* [Builder.fill] is not working in this case.
*/
fun addRecipients(builder: Builder.() -> Unit): Container =
if (this is Single) asOpenMulti.addRecipients(builder)
else {
Builder(this).apply(builder).build()
}
/**
* Add e key to the __decrypted__ container. The new container is also decrypted so you can add
* more keys, etc.
*/
operator fun plus(recipient: Asymmetric.PublicKey) = addRecipients { key(recipient) }
/**
* Add e key to the __decrypted__ container. The new container is also decrypted so you can add
* more keys, etc.
*/
operator fun plus(recipient: EncryptingKey) = addRecipients { key(recipient) }
/**
* Add e key to the __decrypted__ container. The new container is also decrypted so you can add
* more keys, etc.
*/
operator fun plus(pair: Pair<Asymmetric.SecretKey, Asymmetric.PublicKey>) = addRecipients { key(pair) }
/**
* Binary encoded version. It is desirable to include [Container] as an object, though,
* especially when using custom serialization (Json, Boss, etc), it is serializable.
* Still, if you need it in binary form, this is a shortcut. You can use [decode] or call
* [BipackDecoder.decode] to deserialize the binary form.
*/
val encoded: UByteArray by lazy {
BipackEncoder.encode(this).toUByteArray()
override fun updateData(newPlainData: UByteArray, randomFill: IntRange?): Container =
Builder(newPlainData, this).apply {
randomFill?.let { fill(it) }
}.build()
}
companion object {
@@ -286,14 +303,14 @@ sealed class Container {
fillRange = range
}
private var makeOpenedMulti = false
private var alwaysMulti = false
/**
* @suppress
* will produce multikey internal variant even with only one key. User internally
*/
internal fun asOpenedMulti() {
makeOpenedMulti = true
internal fun alwaysMulti() {
alwaysMulti = true
}
/**
@@ -303,8 +320,8 @@ sealed class Container {
val countNewKeys = plainKeys.size + keyPairs.size
if (parent != null) require(parent is Multi) { "parent container mut be a multikey variant" }
return when {
countNewKeys == 0 -> throw IllegalArgumentException("Container needs at least one key")
countNewKeys == 1 && makeOpenedMulti == false && parent == null -> {
countNewKeys == 0 && parent == null -> throw IllegalArgumentException("Container needs at least one key")
countNewKeys == 1 && alwaysMulti == false && parent == null -> {
createSingle()
}
@@ -354,10 +371,7 @@ sealed class Container {
val (sender, recipient) = p
eks += Multi.EncryptedKey(sender, recipient, encodedMainKey)
}
return if (makeOpenedMulti)
Multi(eks, mainKey.encrypt(plainData, fillRange), mainKey, plainData)
else
Multi(eks, mainKey.encrypt(plainData, fillRange))
return Multi(eks, mainKey.encrypt(plainData, fillRange), mainKey, plainData)
}
}