//-----------------------------------------------------------------------
//
// Copyright (c) aliasvault. All rights reserved.
// Licensed under the AGPLv3 license. See LICENSE.md file in the project root for full license information.
//
//-----------------------------------------------------------------------
namespace AliasVault.Cryptography.Client;
using System.Text;
using System.Text.Json;
using Konscious.Security.Cryptography;
///
/// Key derivation algorithms used for encryption/decryption.
///
public static class Encryption
{
///
/// Derive a key used for encryption/decryption based on a user password and system salt.
///
/// User password.
/// The salt to use for the Argon2id hash.
/// The encryption type to use. Defaults to .
/// The encryption settings to use. Defaults to settings as defined in .
/// Key derived from plain-text password as byte array.
public static async Task DeriveKeyFromPasswordAsync(string password, string salt, string? encryptionType = null, string? encryptionSettings = null)
{
if (encryptionType is null)
{
encryptionType = Defaults.EncryptionType;
}
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
byte[] saltBytes = Encoding.UTF8.GetBytes(salt);
switch (encryptionType)
{
case "Argon2Id":
return await Argon2Id(passwordBytes, saltBytes, encryptionSettings);
default:
throw new NotSupportedException($"Encryption type {encryptionType} is not supported.");
}
}
///
/// Derive a key using Argon2id algorithm.
///
/// Password bytes.
/// Salt bytes.
/// Encryption settings JSON string.
/// Key derived from plain-text password as byte array.
private static async Task Argon2Id(byte[] passwordBytes, byte[] saltBytes, string? encryptionSettings = null)
{
var degreeOfParallelism = Defaults.Argon2IdDegreeOfParallelism;
var memorySize = Defaults.Argon2IdMemorySize;
var iterations = Defaults.Argon2IdIterations;
if (encryptionSettings is not null)
{
// Parse the encryption properties json string.
var properties = JsonSerializer.Deserialize>(encryptionSettings);
if (properties is not null)
{
if (properties.TryGetValue("DegreeOfParallelism", out int doP))
{
degreeOfParallelism = doP;
}
if (properties.TryGetValue("MemorySize", out int memSize))
{
memorySize = memSize;
}
if (properties.TryGetValue("Iterations", out int iter))
{
iterations = iter;
}
}
}
var argon2 = new Argon2id(passwordBytes)
{
Salt = saltBytes,
DegreeOfParallelism = degreeOfParallelism,
MemorySize = memorySize,
Iterations = iterations,
};
return await argon2.GetBytesAsync(32); // Generate a 256-bit key
}
}