namespace System.Security.Cryptography { /// /// HashMetadata represents the information stored in the encoded Argon2 format /// public class HashMetadata { /// /// The type of Argon2 hashing algorithm to use /// Argon2d - The memory access is dependent upon the hash value (vulnerable to side-channel attacks) /// Argon2i - The memory access is independent upon the hash value (safe from side-channel atacks) /// public Argon2Type ArgonType { get; set; } /// /// How much memory to use while hashing in kibibytes (KiB) /// public uint MemoryCost { get; set; } /// /// How many iterations of the Argon2 hash to perform /// public uint TimeCost { get; set; } /// /// How many threads to use while hashing /// public uint Parallelism { get; set; } /// /// The raw bytes of the salt /// public byte[] Salt { get; set; } /// /// The raw bytes of the hash /// public byte[] Hash { get; set; } /// /// A base-64 encoded string of the salt, minus the padding (=) characters /// public string GetBase64Salt() => Convert.ToBase64String(Salt).Replace("=", ""); /// /// A base-64 encoded string of the hash, minus the padding (=) characters /// public string GetBase64Hash() => Convert.ToBase64String(Hash).Replace("=", ""); /// /// Converts HashMetadata back into the original Argon2 formatted string. /// public override string ToString() => $"$argon2{(ArgonType == Argon2Type.Argon2i ? "i" : "d")}$v=19$m={MemoryCost},t={TimeCost},p={Parallelism}${GetBase64Salt()}${GetBase64Hash()}"; } }