add class for password-based key derivation

This commit is contained in:
2025-11-25 21:05:37 +03:00
parent 384a303a1d
commit 3492fa1cd0
3 changed files with 51 additions and 2 deletions

View File

@@ -0,0 +1,42 @@
using System;
using System.Security.Cryptography;
namespace KeyKeeper.PasswordStore.Crypto.KeyDerivation;
public class AesKdf : MasterKeyDerivationFunction
{
public const int MIN_ROUNDS = 10;
public const int MAX_ROUNDS = 25_000_000;
public const int SEED_LENGTH = 32;
private int rounds;
private byte[] seed;
public AesKdf(int rounds, byte[] seed)
{
if (rounds < MIN_ROUNDS || rounds > MAX_ROUNDS)
throw new ArgumentOutOfRangeException(nameof(rounds));
if (seed.Length != SEED_LENGTH)
throw new ArgumentException("seed length must be " + SEED_LENGTH);
this.rounds = rounds;
this.seed = seed;
}
public override byte[] Derive(CompositeKey source, int keySizeBytes)
{
if (keySizeBytes > SEED_LENGTH)
throw new ArgumentOutOfRangeException(nameof(keySizeBytes));
byte[] key = source.Hash()[..SEED_LENGTH];
byte[] nextKey = new byte[SEED_LENGTH];
Aes cipher = Aes.Create();
cipher.KeySize = SEED_LENGTH;
for (int i = 0; i < rounds; ++i)
{
cipher.Key = key;
cipher.EncryptEcb(seed, nextKey, PaddingMode.None);
(nextKey, key) = (key, nextKey);
}
return key;
}
}

View File

@@ -0,0 +1,6 @@
namespace KeyKeeper.PasswordStore.Crypto;
public abstract class MasterKeyDerivationFunction
{
public abstract byte[] Derive(CompositeKey source, int keySizeBytes);
}

View File

@@ -1,4 +1,5 @@
using System.Security.Cryptography;
using KeyKeeper.PasswordStore.Crypto.KeyDerivation;
namespace KeyKeeper.PasswordStore;
@@ -6,8 +7,8 @@ static class FileFormatConstants
{
public const int MIN_MASTER_SALT_LEN = 8;
public const int MAX_MASTER_SALT_LEN = 40;
public const int MIN_AESKDF_ROUNDS = 10;
public const int MAX_AESKDF_ROUNDS = 65536;
public const int MIN_AESKDF_ROUNDS = AesKdf.MIN_ROUNDS;
public const int MAX_AESKDF_ROUNDS = AesKdf.MAX_ROUNDS;
public const byte ENCRYPT_ALGO_AES = 14;
public const byte KDF_TYPE_AESKDF = 195;
public const int HMAC_SIZE = HMACSHA3_512.HashSizeInBytes;