forked from sergeych/crypto2
PBKD semi ready, before key refactoring
This commit is contained in:
parent
2cd4eaccab
commit
5c97e857fc
@ -2,7 +2,6 @@ package net.sergeych.crypto2
|
|||||||
|
|
||||||
import com.ionspin.kotlin.crypto.util.encodeToUByteArray
|
import com.ionspin.kotlin.crypto.util.encodeToUByteArray
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.Transient
|
|
||||||
import net.sergeych.bipack.BipackEncoder
|
import net.sergeych.bipack.BipackEncoder
|
||||||
import net.sergeych.bipack.Unsigned
|
import net.sergeych.bipack.Unsigned
|
||||||
import net.sergeych.synctools.ProtectedOp
|
import net.sergeych.synctools.ProtectedOp
|
||||||
@ -10,17 +9,31 @@ import net.sergeych.synctools.invoke
|
|||||||
|
|
||||||
object PBKD {
|
object PBKD {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameters to generate a reasonably secure data bytes with [deriveUBytes] or a [SymmetricKey]
|
||||||
|
* with [deriveKey]
|
||||||
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
class Params(
|
class Params(
|
||||||
val kdf: KDF,
|
val kdf: KDF,
|
||||||
@Unsigned
|
@Unsigned
|
||||||
val startOffset: Int,
|
val startOffset: Int,
|
||||||
@Transient
|
@Unsigned
|
||||||
private var precalculatedKey: SymmetricKey?=null
|
val length: Int,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Derive a key from the password in the idempotent manner.
|
* Derive UByteArray from the password in the idempotent way.
|
||||||
|
* Could be used to construct keys, IVs, tokens, whatever.
|
||||||
|
* Most often [deriveKey] is used instead which derives the key.
|
||||||
|
*/
|
||||||
|
fun deriveUBytes(password: String): UByteArray {
|
||||||
|
val bytes = generate(kdf, password)
|
||||||
|
return bytes.sliceArray(startOffset..<startOffset + length)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derive a new key from the password in the idempotent manner.
|
||||||
* If the [keyId] is provided, it will be used to determine key type (otherwise default asymmetric)
|
* If the [keyId] is provided, it will be used to determine key type (otherwise default asymmetric)
|
||||||
* and to check the result, and the exception will be thrown.
|
* and to check the result, and the exception will be thrown.
|
||||||
*
|
*
|
||||||
@ -31,10 +44,7 @@ object PBKD {
|
|||||||
* @param keyId optional key id, to get a key type from and check the result
|
* @param keyId optional key id, to get a key type from and check the result
|
||||||
* @throws IncorrectPasswordException if [keyId] is provided and does not match the derivation result
|
* @throws IncorrectPasswordException if [keyId] is provided and does not match the derivation result
|
||||||
*/
|
*/
|
||||||
fun derive(password: String, keyId: KeyId? = null): SymmetricKey {
|
fun deriveKey(password: String, keyId: KeyId? = null): SymmetricKey {
|
||||||
// could be already calculated
|
|
||||||
precalculatedKey?.let { return it }
|
|
||||||
|
|
||||||
// check key id sanity
|
// check key id sanity
|
||||||
keyId?.let {
|
keyId?.let {
|
||||||
if (it.id.magick != KeysMagickNumber.defaultSymmetric.number) {
|
if (it.id.magick != KeysMagickNumber.defaultSymmetric.number) {
|
||||||
@ -42,28 +52,36 @@ object PBKD {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// this will not be ok when we support other key types:
|
// this will not be ok when we support other key types:
|
||||||
val keySize = SymmetricKey.keyLength
|
if (SymmetricKey.keyLength != length)
|
||||||
|
throw NotSupportedException("can't create key from $length byte(s), required ${SymmetricKey.keyLength}")
|
||||||
|
|
||||||
// derive
|
// derive
|
||||||
val bytes = generate(kdf, password)
|
val key = SymmetricKey(
|
||||||
val key = SymmetricKey(bytes.sliceArray(startOffset..<startOffset + keySize), this)
|
deriveUBytes(password)
|
||||||
|
.sliceArray(startOffset..<startOffset + SymmetricKey.keyLength),
|
||||||
|
this
|
||||||
|
)
|
||||||
|
|
||||||
// check if we can checking
|
// check if we can
|
||||||
if( keyId != null && keyId != key.id )
|
if (keyId != null && keyId != key.id)
|
||||||
throw IncorrectPasswordException()
|
throw IncorrectPasswordException()
|
||||||
|
|
||||||
// save for later
|
|
||||||
precalculatedKey = key
|
|
||||||
|
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create [PBKD.Params] to derive several keys from the single password
|
* Derive several keys-suitable params
|
||||||
*/
|
*/
|
||||||
fun createMutlipleParams(complexity: KDF.Complexity,keysCount: Int): List<Params> {
|
fun deriveMultipleKeys(password: String,keysCount: Int,
|
||||||
TODO()
|
complexity: KDF.Complexity = KDF.Complexity.Moderate,
|
||||||
|
salt: UByteArray = KDF.Argon.randomSalt()
|
||||||
|
): List<SymmetricKey> {
|
||||||
|
require(keysCount > 0) { "keysCount must be positive" }
|
||||||
|
val keyLength = SymmetricKey.keyLength
|
||||||
|
val totalSize = keysCount * keyLength
|
||||||
|
val kdf = KDF.Argon.create(complexity, salt, totalSize)
|
||||||
|
return (0 ..< keysCount).map { Params(kdf, it*keyLength, keyLength).deriveKey(password) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private val op = ProtectedOp()
|
private val op = ProtectedOp()
|
||||||
|
@ -55,10 +55,8 @@ sealed class KDF {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun derive(password: String): UByteArray {
|
override fun derive(password: String): UByteArray =
|
||||||
TODO()
|
PasswordHash.pwhash(keySize, password, salt, instructionsComplexity, memComplexity, algorithm.code)
|
||||||
//PasswordHash.pwhash(keySize, )
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user