extending to be more convenient
This commit is contained in:
parent
640ceb448e
commit
9f7babdf58
@ -8,7 +8,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "net.sergeych"
|
group = "net.sergeych"
|
||||||
version = "0.6.1-SNAPSHOT"
|
version = "0.6.2-SNAPSHOT"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -60,6 +60,8 @@ class ByteChunk(val data: UByteArray): Comparable<ByteChunk> {
|
|||||||
*/
|
*/
|
||||||
val hex by lazy { data.encodeToHex() }
|
val hex by lazy { data.encodeToHex() }
|
||||||
|
|
||||||
|
val base64Url by lazy { data.encodeToBase64Url() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* human-readable dump
|
* human-readable dump
|
||||||
*/
|
*/
|
||||||
@ -75,9 +77,14 @@ class ByteChunk(val data: UByteArray): Comparable<ByteChunk> {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun fromHex(hex: String): ByteChunk = ByteChunk(hex.decodeHex().asUByteArray())
|
fun fromHex(hex: String): ByteChunk = ByteChunk(hex.decodeHex().asUByteArray())
|
||||||
|
fun random(sizeInBytes: Int=16) = randomUBytes(sizeInBytes).toChunk()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun UByteArray.toChunk(): ByteChunk = ByteChunk(this)
|
||||||
|
@Suppress("unused")
|
||||||
|
private fun ByteArray.toChunk(): ByteChunk = ByteChunk(this.asUByteArray())
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
fun ByteArray.asChunk() = ByteChunk(toUByteArray())
|
fun ByteArray.asChunk() = ByteChunk(toUByteArray())
|
||||||
fun UByteArray.asChunk(): ByteChunk = ByteChunk(this)
|
fun UByteArray.asChunk(): ByteChunk = ByteChunk(this)
|
@ -155,6 +155,11 @@ sealed class Container {
|
|||||||
var authorisedByKey: PublicKey? = null
|
var authorisedByKey: PublicKey? = null
|
||||||
protected set
|
protected set
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of [KeyId] of the keys that unlocked the container, in the same order used for encryption..
|
||||||
|
*/
|
||||||
|
abstract val keyIds: List<KeyId>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @suppress
|
* @suppress
|
||||||
@ -175,6 +180,8 @@ sealed class Container {
|
|||||||
override val decryptedWithKeyId: KeyId?
|
override val decryptedWithKeyId: KeyId?
|
||||||
get() = decryptedWithKey?.id
|
get() = decryptedWithKey?.id
|
||||||
|
|
||||||
|
override val keyIds: List<KeyId> = listOf(keyId)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
decryptedData = creationData
|
decryptedData = creationData
|
||||||
}
|
}
|
||||||
@ -270,6 +277,8 @@ sealed class Container {
|
|||||||
override var decryptedWithKeyId: KeyId? = null
|
override var decryptedWithKeyId: KeyId? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
override val keyIds: List<KeyId> = encryptedKeys.map { it.tag }
|
||||||
|
|
||||||
override fun decryptWith(keyRing: UniversalRing): UByteArray? {
|
override fun decryptWith(keyRing: UniversalRing): UByteArray? {
|
||||||
decryptedData?.let { return it }
|
decryptedData?.let { return it }
|
||||||
for (key in keyRing.decryptingKeys) {
|
for (key in keyRing.decryptingKeys) {
|
||||||
|
@ -46,7 +46,7 @@ class SymmetricKey(
|
|||||||
override val nonceBytesLength: Int = nonceLength
|
override val nonceBytesLength: Int = nonceLength
|
||||||
|
|
||||||
override val id by lazy {
|
override val id by lazy {
|
||||||
KeyId(KeysmagicNumber.defaultSymmetric,blake2b3l(keyBytes), pbkdfParams)
|
KeyId(KeysmagicNumber.defaultSymmetric,blake2b3l(keyBytes),pbkdfParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun decryptWithNonce(cipherData: UByteArray, nonce: UByteArray): UByteArray =
|
override fun decryptWithNonce(cipherData: UByteArray, nonce: UByteArray): UByteArray =
|
||||||
|
@ -27,10 +27,40 @@ sealed class KDF {
|
|||||||
Moderate,
|
Moderate,
|
||||||
FixedHigher,
|
FixedHigher,
|
||||||
Sensitive,
|
Sensitive,
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create [KDF] of the corresponding strength suitable to derive [numberOfKeys] symmetric keys.
|
||||||
|
*
|
||||||
|
* Random salt of proper size is used
|
||||||
|
*/
|
||||||
|
fun kdfForSize(numberOfKeys: Int): KDF = creteDefault(SymmetricKey.keyLength*numberOfKeys, this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derive multiple keys from the password. Derivation params will be included in the key ids, see
|
||||||
|
* [SymmetricKey.id] as [KeyId.kdp].
|
||||||
|
|
||||||
|
* Random salt of proper size is used
|
||||||
|
*
|
||||||
|
* ___Important: symmetric keys do not save key ids___. _Container do it, so it is possible to re-derive
|
||||||
|
* key to open the container, but in many cases you might need to save [KeyId.kdp] separately_.
|
||||||
|
* Having no [PBKD.Params] it would not be possible to recreate the key, as complexity defaults tend
|
||||||
|
* to change with time.
|
||||||
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
|
fun deriveMultiple(password: String, count: Int): List<SymmetricKey> =
|
||||||
|
kdfForSize(count).deriveMultiple(password, count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derive a single key from the password, same as [deriveMultiple] with `count==1`
|
||||||
|
*/
|
||||||
abstract fun derive(password: String): UByteArray
|
abstract fun derive(password: String): UByteArray
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derive keys from lower part of bytes derived from the password. E.g., if generated size is longer than
|
||||||
|
* required to create [count] keys, the first bytes will be used. It let use rest bytes for other purposes.
|
||||||
|
*/
|
||||||
fun deriveMultiple(password: String, count: Int): List<SymmetricKey> {
|
fun deriveMultiple(password: String, count: Int): List<SymmetricKey> {
|
||||||
val bytes = derive(password)
|
val bytes = derive(password)
|
||||||
val ks = SymmetricKey.keyLength
|
val ks = SymmetricKey.keyLength
|
||||||
@ -142,14 +172,14 @@ sealed class KDF {
|
|||||||
salt, keySize
|
salt, keySize
|
||||||
)
|
)
|
||||||
|
|
||||||
Complexity.Sensitive -> Argon(
|
Sensitive -> Argon(
|
||||||
Alg.default,
|
Alg.default,
|
||||||
crypto_pwhash_OPSLIMIT_SENSITIVE,
|
crypto_pwhash_OPSLIMIT_SENSITIVE,
|
||||||
crypto_pwhash_MEMLIMIT_SENSITIVE,
|
crypto_pwhash_MEMLIMIT_SENSITIVE,
|
||||||
salt, keySize
|
salt, keySize
|
||||||
)
|
)
|
||||||
|
|
||||||
Complexity.FixedHigher -> Argon(
|
FixedHigher -> Argon(
|
||||||
V2id_13,
|
V2id_13,
|
||||||
4UL,
|
4UL,
|
||||||
1073741824,
|
1073741824,
|
||||||
|
@ -38,4 +38,11 @@ class KDFTest {
|
|||||||
assertEquals(set2, set1)
|
assertEquals(set2, set1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun complexityTest() = runTest{
|
||||||
|
initCrypto()
|
||||||
|
val kk = KDF.Complexity.Interactive.kdfForSize(3).deriveMultiple("lala", 3)
|
||||||
|
assertEquals(3, kk.size)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user