/// <summary>
 /// Hash the given password to a Argon2 hash string.
 /// </summary>
 /// <param name="password">
 /// The password to hash. Gets UTF-8 encoded before hashing.
 /// </param>
 /// <param name="timeCost">
 /// The time cost to use. Defaults to 3.
 /// </param>
 /// <param name="memoryCost">
 /// The memory cost to use. Defaults to 65536 (64K).
 /// </param>
 /// <param name="parallelism">
 /// The parallelism to use. Default to 1 (single threaded).
 /// </param>
 /// <param name="type">
 /// Data-dependent or data-independent. Defaults to data-independent
 /// (as recommended for password hashing).
 /// </param>
 /// <param name="hashLength">
 /// The length of the hash in bytes. Note, the string returned base-64
 /// encodes this with other parameters so the resulting string is
 /// significantly longer.
 /// </param>
 /// <returns>
 /// The Argon2 hash of the given password.
 /// </returns>
 public static string Hash(
     string password,
     int timeCost    = 3,
     int memoryCost  = 65536,
     int parallelism = 1,
     Argon2Type type = Argon2Type.DataIndependentAddressing,
     int hashLength  = 32)
 {
     using (var passwordBuf = new SecureArray <byte>(Encoding.UTF8.GetByteCount(password)))
     {
         byte[] salt = new byte[16];
         System.Security.Cryptography.RandomNumberGenerator.Create().GetBytes(salt);
         Encoding.UTF8.GetBytes(password, 0, password.Length, passwordBuf.Buffer, 0);
         var argon2 =
             new Argon2(
                 new Argon2Config
         {
             TimeCost   = timeCost,
             MemoryCost = memoryCost,
             Threads    = parallelism,
             Lanes      = parallelism,
             Password   = passwordBuf.Buffer,
             Salt       = salt,
             HashLength = hashLength,
             Version    = Argon2Version.Nineteen
         });
         using (var hash = argon2.Hash())
         {
             return(argon2.config.EncodeString(hash.Buffer));
         }
     }
 }
        /// <summary>
        /// Verify the given Argon2 hash as being that of the given password.
        /// </summary>
        /// <param name="encoded">
        /// The Argon2 hash string. This has the actual hash along with other parameters used in the hash.
        /// </param>
        /// <param name="password">
        /// The password to verify
        /// </param>
        /// <returns>
        /// True on success; false otherwise.
        /// </returns>
        public static bool Verify(
            string encoded,
            byte[] password)
        {
            SecureArray <byte> hash = null;

            try
            {
                var configToVerify = new Argon2Config {
                    Password = password
                };
                if (!configToVerify.DecodeString(encoded, out hash) || hash == null)
                {
                    return(false);
                }

                var hasherToVerify = new Argon2(configToVerify);
                var hashToVerify   = hasherToVerify.Hash();
                return(!hash.Buffer.Where((b, i) => b != hashToVerify[i]).Any());
            }
            finally
            {
                hash?.Dispose();
            }
        }
Esempio n. 3
0
        internal static void AddUser(string username, string password)
        {
            Argon2Config config = new Argon2Config
            {
                Type       = Argon2Type.DataIndependentAddressing,
                Version    = Argon2Version.Nineteen,
                TimeCost   = 3,
                MemoryCost = 32768,
                Lanes      = 4,
                Threads    = Environment.ProcessorCount,
                Password   = Encoding.ASCII.GetBytes(password),
                Salt       = Convert.FromBase64String(Properties.Settings.Default.Salt), // >= 8 bytes if not null
                HashLength = 20                                                          // >= 4
            };
            Argon2 argon2 = new Argon2(config);
            string passwordHash;

            using (SecureArray <byte> hashA = argon2.Hash())
            {
                passwordHash = config.EncodeString(hashA.Buffer);
            }
            var userCreated = new user()
            {
                username     = username,
                passwordHash = passwordHash,
                isAdmin      = false,
                isEnabled    = false
            };

            context.users.Add(userCreated);
            context.SaveChanges();
        }
Esempio n. 4
0
        /// <summary>
        /// Convert Securestring to an DpApi encrypted byte[]
        /// </summary>
        /// <param name="secureString"></param>
        /// <returns></returns>
        public static DpapiEncryptedByteArray ToEncryptedArray(this SecureString secureString)
        {
            IntPtr zero = IntPtr.Zero;

            if ((secureString == null) || (secureString.Length == 0))
            {
                return(null);
            }
            try
            {
                // unicode so twice as big
                using (var secureArray = new SecureArray <byte>(secureString.Length))
                {
                    zero = Marshal.SecureStringToGlobalAllocAnsi(secureString);
                    Marshal.Copy(zero, secureArray.Buffer, 0, secureString.Length);

                    return(secureArray.ToSecureBytes());
                }
            }
            finally
            {
                if (zero != IntPtr.Zero)
                {
                    Marshal.ZeroFreeGlobalAllocAnsi(zero);
                }
            }
        }
        /// <summary>
        /// Verify the given Argon2 hash as being that of the given password.
        /// </summary>
        /// <param name="encoded">
        /// The Argon2 hash string. This has the actual hash along with other parameters used in the hash.
        /// </param>
        /// <param name="password">
        /// The password to verify. This gets UTF-8 encoded.
        /// </param>
        /// <param name="secret">
        /// The secret used in the creation of <paramref name="encoded"/>. UTF-8 encoded to create the byte-buffer actually used in the verification.
        /// May be null for no secret. <see cref="string"/>.<see cref="string.Empty"/> is treated as null.
        /// </param>
        /// <param name="secureArrayCall">
        /// The methods that get called to secure arrays. A null value defaults to <see cref="SecureArray"/>.<see cref="SecureArray.DefaultCall"/>.
        /// </param>
        /// <returns>
        /// True on success; false otherwise.
        /// </returns>
        public static bool Verify(
            string encoded,
            string password,
            string secret,
            SecureArrayCall secureArrayCall = null)
        {
            var secretBuf = string.IsNullOrEmpty(secret)
                                ? null
                                : SecureArray <byte> .Best(Encoding.UTF8.GetByteCount(secret), secureArrayCall);

            try
            {
                if (secretBuf != null)
                {
                    Encoding.UTF8.GetBytes(secret, 0, secret.Length, secretBuf.Buffer, 0);
                }

                using var passwordBuf = SecureArray <byte> .Best(Encoding.UTF8.GetByteCount(password), secureArrayCall);

                Encoding.UTF8.GetBytes(password, 0, password.Length, passwordBuf.Buffer, 0);
                return(Verify(encoded, passwordBuf.Buffer, secretBuf?.Buffer, secureArrayCall));
            }
            finally
            {
                secretBuf?.Dispose();
            }
        }
Esempio n. 6
0
 /// <summary>
 /// Convert a SecureArray<byte> to SecureString
 /// </summary>
 /// <param name="plainString"></param>
 /// <returns></returns>
 public static SecureString ToSecureString(this SecureArray <byte> plainString)
 {
     using (plainString)
     {
         return(ToSecureString(plainString.Buffer.Cast <char>().ToArray()));
     }
 }
Esempio n. 7
0
        /// <summary>
        /// Verify the given Argon2 hash as being that of the given password.
        /// </summary>
        /// <param name="encoded">
        /// The Argon2 hash string. This has the actual hash along with other parameters used in the hash.
        /// </param>
        /// <param name="configToVerify">
        /// The configuration that contains the values used to created <paramref name="encoded"/>.
        /// </param>
        /// <returns>
        /// True on success; false otherwise.
        /// </returns>
        public static bool Verify(
            string encoded,
            Argon2Config configToVerify)
        {
            SecureArray <byte> hash = null;

            try
            {
                if (!configToVerify.DecodeString(encoded, out hash) || hash == null)
                {
                    return(false);
                }

                using (var hasherToVerify = new Argon2(configToVerify))
                {
                    using (var hashToVerify = hasherToVerify.Hash())
                    {
                        return(!hash.Buffer.Where((b, i) => b != hashToVerify[i]).Any());
                    }
                }
            }
            finally
            {
                hash?.Dispose();
            }
        }
Esempio n. 8
0
        public void TestArgon2RoundTrip()
        {
            var password = "******";

            byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
            byte[] salt          = new byte[16];
            Rng.GetBytes(salt);
            var config = new Argon2Config
            {
                Type       = Argon2Type.DataIndependentAddressing,
                Version    = Argon2Version.Nineteen,
                Password   = passwordBytes,
                Salt       = salt,
                TimeCost   = 3,
                MemoryCost = 65536,
                Lanes      = 4,
                Threads    = 2,
            };
            var argon2 = new Argon2(config);
            SecureArray <byte> hash = argon2.Hash();
            var passwordHash        = config.EncodeString(hash.Buffer);

            this.output.WriteLine($"Argon2 of {password} --> {passwordHash}");
            Assert.True(
                Argon2.Verify(passwordHash, passwordBytes, SecureArray.DefaultCall),
                $"expected verify to work for {passwordHash} (Argon2 hash of {password}");
        }
Esempio n. 9
0
 // Token: 0x06000075 RID: 117 RVA: 0x00004298 File Offset: 0x00002498
 private void Resize(int newSize)
 {
     using (SecureArray <char> secureArray = this.buffer)
     {
         this.buffer = new SecureArray <char>(newSize);
         secureArray.ArrayValue.CopyTo(this.buffer.ArrayValue, 0);
     }
 }
        /// <summary>
        /// Compares a hash, salt and plain password and sets IsValid
        /// </summary>
        public SecuredPassword(string plainPassword, byte[] hash, byte[] salt, HashStrategyKind hashStrategy)
        {
            _hash = hash;
            _salt = salt;
            SetHashStrategy(hashStrategy);
            byte[] newKey;
            switch (hashStrategy)
            {
            case HashStrategyKind.Pbkdf210001Iterations:
                var numberOfIterations = (int)_hashingParameter;
                if (numberOfIterations <= 10000)
                {
                    throw new ArgumentException("Iterations must be greater than 10000");
                }
                using (var deriveBytes = new Rfc2898DeriveBytes(plainPassword, salt, numberOfIterations, HashAlgorithmName.SHA256))
                {
                    newKey  = deriveBytes.GetBytes(_saltSize);
                    IsValid = newKey.SequenceEqual(hash);
                }
                break;

            case HashStrategyKind.Argon2WorkCost:
                SecureArray <byte> hashB = null;
                try
                {
                    var passwordBytes            = Encoding.ASCII.GetBytes(plainPassword);
                    var configOfPasswordToVerify = new Argon2Config
                    {
                        Type       = Argon2Type.DataIndependentAddressing,
                        Version    = Argon2Version.Nineteen,
                        TimeCost   = 10,
                        MemoryCost = (int)_hashingParameter,
                        Lanes      = 5,
                        Threads    = Environment.ProcessorCount,
                        Salt       = _salt,
                        Password   = passwordBytes,
                        HashLength = 20
                    };
                    var hashString = Encoding.ASCII.GetString(_hash);
                    if (configOfPasswordToVerify.DecodeString(hashString, out hashB) && hashB != null)
                    {
                        var argon2ToVerify = new Argon2(configOfPasswordToVerify);
                        using (var hashToVerify = argon2ToVerify.Hash())
                        {
                            if (!hashB.Buffer.Where((b, i) => b != hashToVerify[i]).Any())
                            {
                                IsValid = true;
                            }
                        }
                    }
                }
                finally
                {
                    hashB?.Dispose();
                }
                break;
            }
        }
        private void CreateInputHtmlCollection(SecureNameValueCollection collection, SecureHttpBuffer buffer, Uri redirectUrl, int majorCasVersion)
        {
            foreach (string text in collection)
            {
                buffer.CopyAtCurrentPosition("<input type='hidden' name='");
                buffer.CopyAtCurrentPosition(text);
                buffer.CopyAtCurrentPosition("' value='");
                if (text == "password")
                {
                    SecureString securePassword;
                    collection.TryGetSecureValue(text, out securePassword);
                    using (SecureArray <char> secureArray = securePassword.TransformToSecureCharArray(new CharTransformDelegate(FbaFormPostProxyRequestHandler.EncodeForSingleQuotedAttribute)))
                    {
                        buffer.CopyAtCurrentPosition(secureArray);
                        goto IL_14B;
                    }
                    goto IL_72;
                }
                goto IL_72;
IL_14B:
                buffer.CopyAtCurrentPosition("'>");
                continue;
IL_72:
                string text2;
                if (!(text == "destination"))
                {
                    collection.TryGetUnsecureValue(text, out text2);
                    buffer.CopyAtCurrentPosition(EncodingUtilities.HtmlEncode(text2));
                    goto IL_14B;
                }
                collection.TryGetUnsecureValue(text, out text2);
                Uri uri;
                if (!Uri.TryCreate(text2, UriKind.Absolute, out uri))
                {
                    throw new HttpException(400, "destination value is not valid");
                }
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.Append(redirectUrl.Scheme);
                stringBuilder.Append(Uri.SchemeDelimiter);
                stringBuilder.Append(redirectUrl.Authority);
                if (FbaFormPostProxyRequestHandler.IsOwaUrl(uri, OwaUrl.AuthPost, true))
                {
                    stringBuilder.Append(OwaUrl.ApplicationRoot.ImplicitUrl);
                }
                else if (string.IsNullOrEmpty(this.explicitLogonUser))
                {
                    stringBuilder.Append(redirectUrl.PathAndQuery);
                }
                else
                {
                    stringBuilder.Append(uri.PathAndQuery);
                }
                buffer.CopyAtCurrentPosition(stringBuilder.ToString());
                goto IL_14B;
            }
        }
 /// <summary>
 /// Verify the given Argon2 hash as being that of the given password.
 /// </summary>
 /// <param name="encoded">
 /// The Argon2 hash string. This has the actual hash along with other parameters used in the hash.
 /// </param>
 /// <param name="password">
 /// The password to verify. This gets UTF-8 encoded.
 /// </param>
 /// <returns>
 /// True on success; false otherwise.
 /// </returns>
 public static bool Verify(
     string encoded,
     string password)
 {
     using (var passwordBuf = new SecureArray <byte>(Encoding.UTF8.GetByteCount(password)))
     {
         Encoding.UTF8.GetBytes(password, 0, password.Length, passwordBuf.Buffer, 0);
         return(Verify(encoded, passwordBuf.Buffer));
     }
 }
Esempio n. 13
0
        public static DpapiEncryptedByteArray ToSecureBytes(this SecureArray <byte> secureArray)
        {
            if (secureArray == null)
            {
                throw new ArgumentNullException(nameof(secureArray));
            }

            // constructor clears array on creation
            return(new DpapiEncryptedByteArray(secureArray));
        }
Esempio n. 14
0
 // Token: 0x06000070 RID: 112 RVA: 0x00004168 File Offset: 0x00002368
 public void CopyAtCurrentPosition(SecureArray <char> secureArray)
 {
     base.CheckDisposed();
     if (secureArray == null)
     {
         throw new ArgumentNullException("secureArray");
     }
     this.AdjustSizeAtCurrentPosition(secureArray.ArrayValue.Length);
     secureArray.ArrayValue.CopyTo(this.buffer.ArrayValue, this.currentPosition);
     this.currentPosition += secureArray.ArrayValue.Length;
 }
Esempio n. 15
0
 // Token: 0x0600006F RID: 111 RVA: 0x0000411C File Offset: 0x0000231C
 public void CopyAtCurrentPosition(SecureString secureValue)
 {
     base.CheckDisposed();
     if (secureValue == null)
     {
         throw new ArgumentNullException("secureValue");
     }
     using (SecureArray <char> secureArray = SecureStringExtensions.ConvertToSecureCharArray(secureValue))
     {
         this.CopyAtCurrentPosition(secureArray);
     }
 }
Esempio n. 16
0
        private bool disposedValue = false; // To detect redundant calls

        private void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    SecureArray.Zero(_protecteBytes);
                }

                disposedValue = true;
            }
        }
Esempio n. 17
0
        private void Initialize()
        {
            using var blockHash = SecureArray <byte> .Best(PrehashSeedLength, this.config.SecureArrayCall);

            using (var initialHash = this.InitialHash())
            {
                Array.Copy(initialHash.Buffer, blockHash.Buffer, PrehashDigestLength);
            }

            InitialKat(blockHash.Buffer, this);
            this.FillFirstBlocks(blockHash.Buffer);
        }
Esempio n. 18
0
        public KeyPair(byte[] publicKey, byte[] privateKey)
        {
            if (privateKey.Length % 16 != 0)
            {
                throw new ArgumentOutOfRangeException("Private Key length must be a multiple of 16 bytes.");
            }

            _publicKey  = publicKey;
            _privateKey = new SecureArray <byte>(32, SecureArrayType.ZeroedPinnedAndNoSwap);

            Array.Copy(privateKey, _privateKey.Buffer, privateKey.Length);
            Array.Clear(privateKey, 0, 32);
        }
Esempio n. 19
0
        public static SecureArray <char> TransformToSecureCharArray(this SecureString securePassword, CharTransformDelegate transform)
        {
            if (securePassword == null)
            {
                throw new ArgumentNullException("securePassword");
            }
            if (transform == null)
            {
                throw new ArgumentNullException("transform");
            }
            SecureArray <char> secureArray = null;

            using (DisposeGuard disposeGuard = default(DisposeGuard))
            {
                secureArray = securePassword.ConvertToSecureCharArray();
                disposeGuard.Add <SecureArray <char> >(secureArray);
                int  num  = 0;
                bool flag = false;
                foreach (char c in secureArray.ArrayValue)
                {
                    char[] array = transform(c);
                    num  += ((array == null) ? 1 : array.Length);
                    flag |= (array != null);
                }
                if (flag)
                {
                    using (SecureArray <char> secureArray2 = secureArray)
                    {
                        secureArray = new SecureArray <char>(num);
                        disposeGuard.Add <SecureArray <char> >(secureArray);
                        int num2 = 0;
                        foreach (char c2 in secureArray2.ArrayValue)
                        {
                            char[] array2 = transform(c2);
                            if (array2 == null)
                            {
                                secureArray.ArrayValue[num2] = c2;
                                num2++;
                            }
                            else
                            {
                                array2.CopyTo(secureArray.ArrayValue, num2);
                                num2 += array2.Length;
                            }
                        }
                    }
                }
                disposeGuard.Success();
            }
            return(secureArray);
        }
Esempio n. 20
0
        public static string Argon2Hash(string data)
        {
            Argon2Config config = DataHasher.Argon2Config;

            config.Password = Encoding.UTF8.GetBytes(data);

            byte[] salt = new byte[18];
            RNG.GetBytes(salt);
            config.Salt = Encoding.UTF8.GetBytes(System.Convert.ToBase64String(salt));

            using Argon2 argon2 = new Argon2(DataHasher.Argon2Config);
            using SecureArray <byte> hash = argon2.Hash();
            return(DataHasher.Argon2Config.EncodeString(hash.Buffer));
        }
Esempio n. 21
0
        /// <summary>
        /// Test <see cref="Argon2"/>.
        /// </summary>
        /// <returns>
        /// The result text.
        /// </returns>
        public static string TestArgon2RoundTrip()
        {
            var password = "******";

            byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
            byte[] salt          = new byte[16];
            Rng.GetBytes(salt);
            var secret = "secret1";

            byte[] secretBytes   = Encoding.UTF8.GetBytes(secret);
            var    failedResults = new List <string>();
            var    passedResults = new List <string>();

            foreach (var argon2Type in new[] { Argon2Type.DataIndependentAddressing, Argon2Type.DataDependentAddressing, Argon2Type.HybridAddressing })
            {
                var argon2Name = argon2Type == Argon2Type.DataIndependentAddressing ? "Argon2i" :
                                 argon2Type == Argon2Type.DataDependentAddressing ? "Argon2d" : "Argon2id";
                var config = new Argon2Config
                {
                    Type       = argon2Type,
                    Version    = Argon2Version.Nineteen,
                    Password   = passwordBytes,
                    Salt       = salt,
                    Secret     = secretBytes,
                    TimeCost   = 3,
                    MemoryCost = 65536,
                    Lanes      = 4,
                    Threads    = 2,
                };
                var argon2 = new Argon2(config);
                SecureArray <byte> hash = argon2.Hash();
                var passwordHash        = config.EncodeString(hash.Buffer);
                Console.WriteLine($"{argon2Name} of {password} --> {passwordHash}");
                if (Argon2.Verify(passwordHash, passwordBytes, secretBytes, SecureArray.DefaultCall))
                {
                    passedResults.Add(argon2Name);
                    Console.WriteLine($"Round Trip {argon2Name} Passed");
                }
                else
                {
                    failedResults.Add(argon2Name);
                    Console.WriteLine($"Round Trip {argon2Name} FAILED");
                    Console.WriteLine($"    expected verify to work for {passwordHash} (Argon2 hash of {password})");
                }
            }

            return(failedResults.Any() ? $"RoundTrip FAILED: [{string.Join(", ", failedResults)}] (passed: [{string.Join(", ", passedResults)}])"
                : "RoundTrip Passed");
        }
Esempio n. 22
0
        private void FillFirstBlocks(byte[] blockHash)
        {
            using var blockHashBytes = SecureArray <byte> .Best(BlockSize, this.config.SecureArrayCall);

            for (int l = 0; l < this.config.Lanes; ++l)
            {
                Store32(blockHash, PrehashDigestLength, 0);
                Store32(blockHash, PrehashDigestLength + 4, l);
                Blake2BLong(blockHashBytes.Buffer, blockHash, this.config.SecureArrayCall);
                LoadBlock(this.Memory[l * this.LaneLength], blockHashBytes.Buffer);
                Store32(blockHash, PrehashDigestLength, 1);
                Blake2BLong(blockHashBytes.Buffer, blockHash, this.config.SecureArrayCall);
                LoadBlock(this.Memory[(l * this.LaneLength) + 1], blockHashBytes.Buffer);
            }
        }
        /// <summary>
        /// Given a plain password and a hash strategy, calculate the salt and hash
        /// </summary>
        public SecuredPassword(string plainPassword, HashStrategyKind hashStrategy)
        {
            if (string.IsNullOrWhiteSpace(plainPassword))
            {
                throw new ArgumentNullException(plainPassword);
            }
            SetHashStrategy(hashStrategy);

            switch (hashStrategy)
            {
            case HashStrategyKind.Pbkdf210001Iterations:
                var numberOfIterations = (int)_hashingParameter;
                if (numberOfIterations <= 10000)
                {
                    throw new ArgumentException("Iterations must be greater than 10000");
                }
                using (var deriveBytes = new Rfc2898DeriveBytes(plainPassword, _saltSize, numberOfIterations, HashAlgorithmName.SHA256))
                {
                    _salt = deriveBytes.Salt;
                    _hash = deriveBytes.GetBytes(_saltSize);
                }
                break;

            case HashStrategyKind.Argon2WorkCost:
                byte[] passwordBytes = Encoding.UTF8.GetBytes(plainPassword);
                _salt = new byte[_saltSize];
                RandomNumberGenerator.GetBytes(_salt);
                var config = new Argon2Config
                {
                    Type       = Argon2Type.DataIndependentAddressing,
                    Version    = Argon2Version.Nineteen,
                    TimeCost   = 10,
                    MemoryCost = (int)_hashingParameter,
                    Lanes      = 5,
                    Threads    = Environment.ProcessorCount,
                    Password   = passwordBytes,
                    Salt       = _salt,
                    HashLength = 20
                };
                var argon2A = new Argon2(config);
                using (SecureArray <byte> hashArgon = argon2A.Hash())
                {
                    _hash = Encoding.ASCII.GetBytes(config.EncodeString(hashArgon.Buffer));
                }
                break;
            }
            IsValid = true;
        }
 public void TestArgon2()
 {
     foreach (var testVector in Argon2TestVectors)
     {
         var  encoded   = new StringBuilder();
         uint tagLength = (uint)testVector.TagLength;
         try
         {
             var config = new Argon2Config
             {
                 Type           = testVector.Type,
                 Version        = testVector.Version,
                 TimeCost       = testVector.Iterations,
                 MemoryCost     = testVector.MemoryKBytes,
                 Lanes          = testVector.Parallelism,
                 Threads        = testVector.Parallelism,
                 Password       = testVector.Password,
                 Salt           = testVector.Salt,
                 Secret         = testVector.Secret,
                 AssociatedData = testVector.AssociatedData,
                 HashLength     = testVector.TagLength
             };
             var argon2 = new Argon2(config);
             SecureArray <byte> hash = argon2.Hash();
             Assert.False(
                 hash.Buffer.Where((b, i) => b != testVector.Tag[i]).Any(),
                 $"Test {testVector.Name}: Got{Environment.NewLine}{BitConverter.ToString(hash.Buffer)}{Environment.NewLine}expected{Environment.NewLine}{BitConverter.ToString(testVector.Tag)}");
             this.output.WriteLine(
                 "Passed Argon2:\r\n"
                 + $"             Version 0x{(int)testVector.Version:X} ({(int)testVector.Version})\r\n"
                 + $"                Type {testVector.Type}\r\n"
                 + $"          Iterations {testVector.Iterations}\r\n"
                 + $"       Memory KBytes {testVector.MemoryKBytes}\r\n"
                 + $"         Parallelism {testVector.Parallelism}\r\n"
                 + $"            Password {BitConverter.ToString(testVector.Password)}\r\n"
                 + $"                Salt {BitConverter.ToString(testVector.Salt)}\r\n"
                 + $"              Secret {BitConverter.ToString(testVector.Secret)}\r\n"
                 + $"       AssciatedData {BitConverter.ToString(testVector.AssociatedData)}\r\n"
                 + $"  Gave expected hash {BitConverter.ToString(hash.Buffer)}\r\n"
                 + $"             encoded {encoded}");
         }
         catch (Exception e)
         {
             Assert.False(true, e.Message);
         }
     }
 }
Esempio n. 25
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Blake2BCore"/> class.
        /// </summary>
        /// <param name="secureArrayCall">
        /// The methods that get called to secure arrays. A null value defaults to <see cref="SecureArray"/>.<see cref="SecureArray.DefaultCall"/>.
        /// </param>
        /// <param name="lockMemory">
        /// Used to set locking strategy for buffers used in creating the hash. The memory
        /// will always be zeroed prior to destruction. The memory is also always pinned
        /// so the CLR can't move it and leave extraneous copies floating around in RAM.
        /// </param>
        public Blake2BCore(SecureArrayCall secureArrayCall, LockMemoryPolicy lockMemory = LockMemoryPolicy.BestEffort)
        {
            switch (lockMemory)
            {
            case LockMemoryPolicy.None:
                this.buf  = new SecureArray <byte>(128, SecureArrayType.ZeroedAndPinned, secureArrayCall);
                this.mbuf = new SecureArray <ulong>(16, SecureArrayType.ZeroedAndPinned, secureArrayCall);
                this.hbuf = new SecureArray <ulong>(8, SecureArrayType.ZeroedAndPinned, secureArrayCall);
                break;

            case LockMemoryPolicy.BestEffort:
                try
                {
                    this.buf = new SecureArray <byte>(128, SecureArrayType.ZeroedPinnedAndNoSwap, secureArrayCall);
                }
                catch (LockFailException)
                {
                    this.buf = new SecureArray <byte>(128, SecureArrayType.ZeroedAndPinned, secureArrayCall);
                }

                try
                {
                    this.mbuf = new SecureArray <ulong>(16, SecureArrayType.ZeroedPinnedAndNoSwap, secureArrayCall);
                }
                catch (LockFailException)
                {
                    this.mbuf = new SecureArray <ulong>(16, SecureArrayType.ZeroedAndPinned, secureArrayCall);
                }

                try
                {
                    this.hbuf = new SecureArray <ulong>(8, SecureArrayType.ZeroedPinnedAndNoSwap, secureArrayCall);
                }
                catch (LockFailException)
                {
                    this.hbuf = new SecureArray <ulong>(8, SecureArrayType.ZeroedAndPinned, secureArrayCall);
                }
                break;

            default:
                this.buf  = new SecureArray <byte>(128, SecureArrayType.ZeroedPinnedAndNoSwap, secureArrayCall);
                this.mbuf = new SecureArray <ulong>(16, SecureArrayType.ZeroedPinnedAndNoSwap, secureArrayCall);
                this.hbuf = new SecureArray <ulong>(8, SecureArrayType.ZeroedPinnedAndNoSwap, secureArrayCall);
                break;
            }
        }
        /// <summary>
        /// Does a Blake2 hash with the ability to truncate or extend the hash to any length.
        /// </summary>
        /// <param name="hash">
        /// The buffer to fill with the hash.
        /// </param>
        /// <param name="inputBuffer">
        /// What to hash.
        /// </param>
        /// <param name="secureArrayCall">
        /// The methods that get called to secure arrays. A null value defaults to <see cref="SecureArray"/>.<see cref="SecureArray.DefaultCall"/>.
        /// </param>
        private static void Blake2BLong(byte[] hash, byte[] inputBuffer, SecureArrayCall secureArrayCall)
        {
            var outputLengthBytes = new byte[4];

            using var intermediateHash = SecureArray <byte> .Best(Blake2B.OutputLength, secureArrayCall);

            var config = new Blake2BConfig
            {
                Result64ByteBuffer = intermediateHash.Buffer,
                OutputSizeInBytes  = hash.Length > 64 ? 64 : hash.Length,
            };

            Store32(outputLengthBytes, hash.Length);
            using (var blakeHash = Blake2B.Create(config, secureArrayCall))
            {
                blakeHash.Update(outputLengthBytes);
                blakeHash.Update(inputBuffer);
                blakeHash.Finish();
            }

            if (hash.Length <= intermediateHash.Buffer.Length)
            {
                Array.Copy(intermediateHash.Buffer, hash, hash.Length);
                return;
            }

            const int b2B2 = Blake2B.OutputLength / 2;

            Array.Copy(intermediateHash.Buffer, hash, b2B2);
            int pos           = b2B2;
            int lastHashIndex = hash.Length - Blake2B.OutputLength;
            var toHash        = new byte[Blake2B.OutputLength];

            while (pos < lastHashIndex)
            {
                Array.Copy(intermediateHash.Buffer, toHash, intermediateHash.Buffer.Length);
                Blake2B.ComputeHash(toHash, config, secureArrayCall);
                Array.Copy(intermediateHash.Buffer, 0, hash, pos, b2B2);
                pos += b2B2;
            }

            Array.Copy(intermediateHash.Buffer, toHash, intermediateHash.Buffer.Length);
            Blake2B.ComputeHash(toHash, config, secureArrayCall);
            Array.Copy(intermediateHash.Buffer, 0, hash, pos, hash.Length - pos);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="Argon2"/> class.
        /// </summary>
        /// <param name="config">
        /// The configuration to use.
        /// </param>
        public Argon2(Argon2Config config)
        {
            this.config = config;
            uint memoryBlocks = (uint)config.MemoryCost;

            if (memoryBlocks < 2 * SyncPoints * config.Lanes)
            {
                memoryBlocks = 2 * SyncPoints * (uint)config.Lanes;
            }

            this.SegmentLength = (int)(memoryBlocks / (config.Lanes * SyncPoints));

            // ensure that all segments have equal length
            this.LaneLength       = this.SegmentLength * SyncPoints;
            this.MemoryBlockCount = this.LaneLength * this.config.Lanes;
            this.memory           = BestSecureArray <ulong>(BlockSize * this.MemoryBlockCount / 8);
            this.Memory           = new Blocks(this.memory.Buffer, this.MemoryBlockCount);
        }
        public Blake2BHasher(Blake2BConfig config)
        {
            if (config == null)
            {
                config = DefaultConfig;
            }
            this.core      = new Blake2BCore(config.LockMemoryPolicy);
            this.rawConfig = Blake2IvBuilder.ConfigB(config, null);
            if (config.Key != null && config.Key.Length != 0)
            {
                this.key = new SecureArray <byte>(128);
                Array.Copy(config.Key, this.key.Buffer, config.Key.Length);
            }

            this.outputSizeInBytes   = config.OutputSizeInBytes;
            this.defaultOutputBuffer = config.Result64ByteBuffer;
            this.Init();
        }
Esempio n. 29
0
        /// <summary>
        /// Convert array to a secure array
        /// will zero array passed in using RtlZeroMemory
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="array"></param>
        /// <returns></returns>
        public static SecureArray <T> ToSecureArray <T>(this T[] array) where T : struct
        {
            if (array == null)
            {
                throw new ArgumentNullException(nameof(array));
            }

            try
            {
                var secure = new SecureArray <T>(array.Length);

                Buffer.BlockCopy(array, 0, secure.Buffer, 0, array.Length);

                return(secure);
            }
            finally
            {
                SecureArray.Zero(array);
            }
        }
Esempio n. 30
0
        public string HashPassword(string password)
        {
            if (string.IsNullOrEmpty(password))
            {
                throw new ArgumentNullException(password);
            }

            byte[]       salt         = new byte[32];
            Argon2Config argon2Config = _argon2Config;

            argon2Config.Password = Encoding.UTF8.GetBytes(password);
            argon2Config.Salt     = salt;

            _randomNumberGenerator.GetBytes(salt);
            var argon2 = new Argon2(argon2Config);

            using SecureArray <byte> secureArray = argon2.Hash();
            argon2.Dispose();

            return(argon2Config.EncodeString(secureArray.Buffer));
        }