more sugar to be like unicrypto by functions

This commit is contained in:
Sergey Chernov 2024-06-28 15:35:48 +07:00
parent a6c7dafb70
commit 78383fbece
6 changed files with 53 additions and 3 deletions

View File

@ -5,7 +5,7 @@ plugins {
}
group = "net.sergeych"
version = "0.4.1-SNAPSHOT"
version = "0.4.2-SNAPSHOT"
repositories {
mavenCentral()

View File

@ -436,6 +436,17 @@ sealed class Container {
fun create(plainData: UByteArray, builder: Builder.() -> Unit) =
Builder(plainData).also { it.builder() }.build()
@Suppress("unused")
inline fun <reified T>encrypt(plainData: T, vararg keys: EncryptingKey): UByteArray =
createWith(BipackEncoder.encode<T>(plainData).toUByteArray(), *keys).encoded
inline fun <reified T>decrypt(cipherData: UByteArray, vararg keys: DecryptingKey): T? =
decryptAsUBytes(cipherData,*keys)?.let { BipackDecoder.decode<T>(it.toByteArray())}
fun decryptAsUBytes(cipherData: UByteArray, vararg keys: DecryptingKey): UByteArray? =
decode(cipherData).decryptWith(*keys)
/**
* Create container using one or more [EncryptingKey] and a builder, see [create]
* for builder usage sample.

View File

@ -14,7 +14,7 @@ object PBKD {
* with [deriveKey]
*/
@Serializable
class Params(
data class Params(
val kdf: KDF,
@Unsigned
val startOffset: Int,
@ -76,7 +76,9 @@ object PBKD {
require(keysCount > 0) { "keysCount must be positive" }
val keyLength = SymmetricKey.keyLength
val totalSize = keysCount * keyLength
val kdf = KDF.Argon.create(complexity, salt, totalSize)
check(salt.size >= KDF.Argon.saltSize)
val salt2 = if( salt.size > KDF.Argon.saltSize) salt.sliceArray( 0 ..< KDF.Argon.saltSize) else salt
val kdf = KDF.Argon.create(complexity, salt2, totalSize)
return (0 ..< keysCount).map { Params(kdf, it*keyLength, keyLength).deriveKey(password) }
}

View File

@ -3,6 +3,7 @@ package net.sergeych.crypto2
import kotlinx.datetime.Instant
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import net.sergeych.bipack.BipackEncoder
/**
* Multi-signed data box. Do not use the constructori directly, use [SealedBox.create]
@ -65,6 +66,7 @@ class SealedBox(
}
}
val encoded: UByteArray by lazy { BipackEncoder.encode(this).toUByteArray() }
companion object {
/**
@ -80,5 +82,9 @@ class SealedBox(
fun create(data: UByteArray, vararg keys: SigningSecretKey): SealedBox {
return SealedBox(data, keys.map { it.seal(data) }, false)
}
inline fun <reified T>encode(value: T, vararg keys: SigningSecretKey): UByteArray =
create(BipackEncoder.encode(value).toUByteArray(), *keys).encoded
}
}

View File

@ -4,6 +4,7 @@ import com.ionspin.kotlin.crypto.pwhash.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import net.sergeych.bipack.Unsigned
import net.sergeych.crypto2.PBKD.Params
@Serializable
sealed class KDF {
@ -16,6 +17,16 @@ sealed class KDF {
abstract fun derive(password: String): UByteArray
fun deriveMultiple(password: String,count: Int) : List<SymmetricKey> {
val bytes = derive(password)
val ks = SymmetricKey.keyLength
check( ks * count <= bytes.size ) { "KDF is too short for $count keys: ${bytes.size} we need ${ks*count}"}
return (0 ..< count).map {
val base = it*ks
Params(this, base, ks).deriveKey(password)
}
}
@Serializable
@SerialName("argon")
data class Argon(
@ -114,6 +125,13 @@ sealed class KDF {
}
}
companion object {
@Suppress("unused")
fun creteDefault(keySize: Int, complexity: Complexity, salt: UByteArray = Argon.randomSalt()): KDF {
return Argon.create(complexity,salt,keySize)
}
}
data class Instance(val kdf: KDF,val password: String)
}

View File

@ -3,6 +3,7 @@ import net.sergeych.crypto2.PBKD
import net.sergeych.crypto2.initCrypto
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
class PBKDTest {
@ -32,5 +33,17 @@ class PBKDTest {
assertEquals(i.kdp, kx.id.kdp)
}
val (y1,y2,y3) = k1.id.kdp!!.kdf.deriveMultiple("foobar", 3)
for( (a,b) in listOf(y1,y2,y3).zip(listOf(k1,k2,k3))) {
assertEquals(a,b)
assertNotNull(a.id.kdp)
assertNotNull(b.id.kdp)
assertEquals(a.id.kdp, b.id.kdp)
assertEquals(a.id, b.id)
}
assertEquals(k1, y1)
assertEquals(k2, y2)
assertEquals(k3, y3)
}
}