using Bit.Core.Abstractions; using Bit.Core.Enums; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Crypto.Parameters; using System; using System.Runtime.InteropServices; using Java.Lang; namespace Bit.Droid.Services { public class CryptoPrimitiveService : ICryptoPrimitiveService { public byte[] Pbkdf2(byte[] password, byte[] salt, CryptoHashAlgorithm algorithm, int iterations) { int keySize = 256; IDigest digest = null; if (algorithm == CryptoHashAlgorithm.Sha256) { keySize = 256; digest = new Sha256Digest(); } else if (algorithm == CryptoHashAlgorithm.Sha512) { keySize = 512; digest = new Sha512Digest(); } else { throw new ArgumentException("Unsupported PBKDF2 algorithm."); } var generator = new Pkcs5S2ParametersGenerator(digest); generator.Init(password, salt, iterations); return ((KeyParameter)generator.GenerateDerivedMacParameters(keySize)).GetKey(); } public byte[] Argon2id(byte[] password, byte[] salt, int iterations, int memory, int parallelism) { JavaSystem.LoadLibrary("argon2"); int keySize = 32; var key = new byte[keySize]; argon2id_hash_raw(iterations, memory, parallelism, password, password.Length, salt, salt.Length, key, key.Length); return key; } [DllImport("argon2", EntryPoint = "argon2id_hash_raw")] private static extern int argon2id_hash_raw(int timeCost, int memoryCost, int parallelism, byte[] pwd, int pwdlen, byte[] salt, int saltlen, byte[] hash, int hashlen); } }