Example #1
0
        public static void Properties()
        {
            var a = new HkdfSha256();

            Assert.True(a.PseudorandomKeySize > 0);
            Assert.True(a.MaxOutputSize > 0);
        }
Example #2
0
        public void TestHkdfVector2()
        {
            // Expected Values
            byte[] prkFromSpec = CognitoAuthHelper.StringToByteArray("06a6b88c5853361a06104c9ceb35b45cef760014904671" +
                                                                     "014a193f40c15fc244");
            byte[] okmFromSpec = CognitoAuthHelper.StringToByteArray("b11e398dc80327a1c8e7f78c596a49344f012eda2d4efa" +
                                                                     "d8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71c" +
                                                                     "c30c58179ec3e87c14c01d5c1f3434f1d87");

            byte[] ikmBytes = CognitoAuthHelper.StringToByteArray("000102030405060708090a0b0c0d0e0f101112131" +
                                                                  "415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d" +
                                                                  "3e3f404142434445464748494a4b4c4d4e4f");
            byte[] saltBytes = CognitoAuthHelper.StringToByteArray("606162636465666768696a6b6c6d6e6f70717273" +
                                                                   "7475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9" +
                                                                   "d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf");
            byte[] infoBytes = CognitoAuthHelper.StringToByteArray("b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3" +
                                                                   "c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebece" +
                                                                   "deeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
            int length = 82;

            HkdfSha256 hkdfSha256 = new HkdfSha256(saltBytes, ikmBytes);

            byte[] hkdfResult = hkdfSha256.Expand(infoBytes, length);

            Assert.Equal(prkFromSpec, hkdfSha256.Prk);
            Assert.Equal(okmFromSpec, hkdfResult);
        }
Example #3
0
        /// <summary>
        /// Creates the Password Authentication Key based on the SRP protocol
        /// </summary>
        /// <param name="userID"> Username of CognitoUser</param>
        /// <param name="userPassword">Password of CognitoUser</param>
        /// <param name="poolName">PoolName of CognitoUserPool (part of poolID after "_")</param>
        /// <param name="Aa">Returned from TupleAa</param>
        /// <param name="B">BigInteger SRPB from AWS ChallengeParameters</param>
        /// <param name="salt">BigInteger salt from AWS ChallengeParameters</param>
        /// <returns>Returns the password authentication key for the SRP protocol</returns>
        public static byte[] GetPasswordAuthenticationKey(string userID,
                                                          string userPassword,
                                                          string poolName,
                                                          Tuple <BigInteger, BigInteger> Aa,
                                                          BigInteger B,
                                                          BigInteger salt)
        {
            // Authenticate the password
            // u = H(A, B)
            byte[] contentBytes = CognitoAuthHelper.CombineBytes(new [] { Aa.Item1.ToBigEndianByteArray(), B.ToBigEndianByteArray() });
            byte[] digest       = CognitoAuthHelper.Sha256.ComputeHash(contentBytes);

            BigInteger u = BigIntegerExtensions.FromUnsignedBigEndian(digest);

            if (u.Equals(BigInteger.Zero))
            {
                throw new ArgumentException("Hash of A and B cannot be zero.");
            }

            // x = H(salt | H(poolName | userId | ":" | password))
            byte[] userIdContent = CognitoAuthHelper.CombineBytes(new byte[][] { Encoding.UTF8.GetBytes(poolName), Encoding.UTF8.GetBytes(userID),
                                                                                 Encoding.UTF8.GetBytes(":"), Encoding.UTF8.GetBytes(userPassword) });
            byte[] userIdHash = CognitoAuthHelper.Sha256.ComputeHash(userIdContent);
            byte[] xBytes     = CognitoAuthHelper.CombineBytes(new byte[][] { salt.ToBigEndianByteArray(), userIdHash });

            byte[]     xDigest = CognitoAuthHelper.Sha256.ComputeHash(xBytes);
            BigInteger x       = BigIntegerExtensions.FromUnsignedBigEndian(xDigest);

            // Use HKDF to get final password authentication key
            var        first      = (B - k * BigInteger.ModPow(g, x, N)).TrueMod(N);
            var        second     = BigInteger.ModPow(first, Aa.Item2 + u * x, N);
            HkdfSha256 hkdfSha256 = new HkdfSha256(u.ToBigEndianByteArray(), second.ToBigEndianByteArray());

            return(hkdfSha256.Expand(Encoding.UTF8.GetBytes(DerivedKeyInfo), DerivedKeySizeBytes));
        }
Example #4
0
        public static void ExpandWithKeyOverlapping()
        {
            var a = new HkdfSha256();
            var b = new byte[200];

            Assert.Throws <ArgumentException>("bytes", () => a.Expand(b.AsSpan().Slice(10, a.PseudorandomKeySize), ReadOnlySpan <byte> .Empty, b.AsSpan().Slice(30, 100)));
            Assert.Throws <ArgumentException>("bytes", () => a.Expand(b.AsSpan().Slice(30, a.PseudorandomKeySize), ReadOnlySpan <byte> .Empty, b.AsSpan().Slice(10, 100)));
        }
Example #5
0
        public static void Properties()
        {
            var a = new HkdfSha256();

            Assert.Equal(8160, a.MaxOutputSize);
            Assert.Equal(32, a.PseudorandomKeySize);
            Assert.True(a.SupportsSalt);
        }
Example #6
0
        public static void ExpandWithCountWithLongPrk()
        {
            var a = new HkdfSha256();

            var b = a.Expand((s_prkForEmpty + s_prkForEmpty).DecodeHex(), ReadOnlySpan <byte> .Empty, 256);

            Assert.NotNull(b);
            Assert.Equal(256, b.Length);
        }
Example #7
0
        public static void ExtractWithSpanTooLong()
        {
            var a = new HkdfSha256();

            using (var s = SharedSecret.Import(ReadOnlySpan <byte> .Empty))
            {
                Assert.Throws <ArgumentException>("pseudorandomKey", () => a.Extract(s, ReadOnlySpan <byte> .Empty, new byte[a.PseudorandomKeySize + 1]));
            }
        }
Example #8
0
        public static void TestOneStep(string ikm, string salt, string info, string expectedPrk, string expectedOkm)
        {
            var a = new HkdfSha256();

            using (var s = SharedSecret.Import(ikm.DecodeHex()))
            {
                var actualOkm = a.DeriveBytes(s, salt.DecodeHex(), info.DecodeHex(), expectedOkm.DecodeHex().Length);
                Assert.Equal(expectedOkm.DecodeHex(), actualOkm);
            }
        }
Example #9
0
        public static void ExpandWithCountSuccess(int count)
        {
            var a = new HkdfSha256();

            var expected = s_outputForEmpty.DecodeHex().Substring(0, count);
            var actual   = a.Expand(s_prkForEmpty.DecodeHex(), ReadOnlySpan <byte> .Empty, count);

            Assert.NotNull(actual);
            Assert.Equal(expected, actual);
            Assert.Equal(count, actual.Length);
        }
Example #10
0
        public static void ExpandWithMaxCount()
        {
            var a = new HkdfSha256();

            var expected = s_outputForEmpty.DecodeHex();
            var actual   = a.Expand(s_prkForEmpty.DecodeHex(), ReadOnlySpan <byte> .Empty, a.MaxOutputSize);

            Assert.NotNull(actual);
            Assert.Equal(expected, actual);
            Assert.Equal(a.MaxOutputSize, actual.Length);
        }
Example #11
0
        public static void ExpandWithSpanSuccess(int count)
        {
            var a = new HkdfSha256();

            var expected = s_outputForEmpty.DecodeHex().Substring(0, count);
            var actual   = new byte[count];

            a.Expand(s_prkForEmpty.DecodeHex(), ReadOnlySpan <byte> .Empty, actual);

            Assert.Equal(expected, actual);
        }
Example #12
0
        public static void ExpandWithMaxSpan()
        {
            var a = new HkdfSha256();

            var expected = s_outputForEmpty.DecodeHex();
            var actual   = new byte[a.MaxOutputSize];

            a.Expand(s_prkForEmpty.DecodeHex(), ReadOnlySpan <byte> .Empty, actual);

            Assert.Equal(expected, actual);
        }
Example #13
0
        public Key CreateAes256GcmSymmetricKey(byte[] clientPublicKeyBytes, Key serverKey)
        {
            var keyDerivationAlgorithm = new HkdfSha256();
            //Import clientPublicKey from bytes
            PublicKey clientPublicKey = PublicKey.Import(keyAgreementAlgorithm, clientPublicKeyBytes, KeyBlobFormat.RawPublicKey);
            //Create SharedSecret
            SharedSecret sharedSecretServer = keyAgreementAlgorithm.Agree(serverKey, clientPublicKey);
            //Convert sharedSecret to bytes
            var sharedSecretBytes = keyDerivationAlgorithm.DeriveBytes(sharedSecretServer, null, null, sharedSecretServer.Size);

            //Create symmetric key from sharedSecret bytes
            return(Key.Import(aeadAlgorithm, sharedSecretBytes, KeyBlobFormat.RawSymmetricKey));
        }
Example #14
0
        public static void TestTwoStep(string ikm, string salt, string info, string expectedPrk, string expectedOkm)
        {
            var a = new HkdfSha256();

            using (var s = SharedSecret.Import(ikm.DecodeHex()))
            {
                var actualPrk = a.Extract(s, salt.DecodeHex());
                Assert.Equal(expectedPrk.DecodeHex(), actualPrk);

                var actualOkm = a.Expand(actualPrk, info.DecodeHex(), expectedOkm.DecodeHex().Length);
                Assert.Equal(expectedOkm.DecodeHex(), actualOkm);
            }
        }
Example #15
0
        public static void ExtractSuccess()
        {
            var a = new HkdfSha256();

            using (var s = SharedSecret.Import(ReadOnlySpan <byte> .Empty))
            {
                var expected = s_prkForEmpty.DecodeHex();
                var actual   = a.Extract(s, ReadOnlySpan <byte> .Empty);

                Assert.Equal(expected, actual);
                Assert.Equal(a.PseudorandomKeySize, actual.Length);
            }
        }
Example #16
0
        public static void ExtractWithSpanSuccess()
        {
            var a = new HkdfSha256();

            using (var s = SharedSecret.Import(ReadOnlySpan <byte> .Empty))
            {
                var expected = s_prkForEmpty.DecodeHex();
                var actual   = new byte[expected.Length];

                a.Extract(s, ReadOnlySpan <byte> .Empty, actual);

                Assert.Equal(expected, actual);
            }
        }
Example #17
0
        public static void ExtractWithEmptySalt()
        {
            const int HashLen = 256 / 8;

            var a = new HkdfSha256();

            using (var s = SharedSecret.Import(ReadOnlySpan <byte> .Empty))
            {
                var expected = a.Extract(s, new byte[HashLen]);
                var actual   = a.Extract(s, ReadOnlySpan <byte> .Empty);

                Assert.Equal(expected, actual);
            }
        }
Example #18
0
        public static void Test(string privateKey, string publicKey, string sharedSecret)
        {
            var a   = new X25519();
            var kdf = new HkdfSha256();

            using (var k = Key.Import(a, privateKey.DecodeHex(), KeyBlobFormat.RawPrivateKey))
                using (var sharedSecretExpected = SharedSecret.Import(sharedSecret.DecodeHex()))
                    using (var sharedSecretActual = a.Agree(k, PublicKey.Import(a, publicKey.DecodeHex(), KeyBlobFormat.RawPublicKey)))
                    {
                        var expected = kdf.Extract(sharedSecretExpected, ReadOnlySpan <byte> .Empty);
                        var actual   = kdf.Extract(sharedSecretActual, ReadOnlySpan <byte> .Empty);

                        Assert.Equal(expected, actual);
                    }
        }
Example #19
0
        public static void ExtractWithSpanWithSaltOverlapping()
        {
            var a = new HkdfSha256();

            using (var s = SharedSecret.Import(ReadOnlySpan <byte> .Empty))
            {
                var expected = new byte[a.PseudorandomKeySize];
                var actual   = Utilities.RandomBytes.Slice(0, a.PseudorandomKeySize).ToArray();

                a.Extract(s, actual, expected);
                a.Extract(s, actual, actual);

                Assert.Equal(expected, actual);
            }
        }
Example #20
0
        public static void ExpandWithInfoOverlapping()
        {
            var a = new HkdfSha256();
            var x = new X25519();

            using (var k = new Key(x))
                using (var s = x.Agree(k, k.PublicKey))
                {
                    var b = new byte[200];

                    var prk = a.Extract(s, ReadOnlySpan <byte> .Empty);

                    Assert.Throws <ArgumentException>("bytes", () => a.Expand(prk, b.AsSpan().Slice(10, 100), b.AsSpan().Slice(60, 100)));
                    Assert.Throws <ArgumentException>("bytes", () => a.Expand(prk, b.AsSpan().Slice(60, 100), b.AsSpan().Slice(10, 100)));
                }
        }
Example #21
0
        public static void ExtractWithSpanWithEmptySalt()
        {
            const int HashLen = 256 / 8;

            var a = new HkdfSha256();

            using (var s = SharedSecret.Import(ReadOnlySpan <byte> .Empty))
            {
                var expected = new byte[a.PseudorandomKeySize];
                var actual   = new byte[expected.Length];

                a.Extract(s, new byte[HashLen], expected);
                a.Extract(s, ReadOnlySpan <byte> .Empty, actual);

                Assert.Equal(expected, actual);
            }
        }
        public void TestHkdfVector1()
        {
            // Expected Values
            var prkFromSepc = CognitoAuthHelper.StringToByteArray("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3" +
                                                                  "122ec844ad7c2b3e5");
            var okmFromSpec = CognitoAuthHelper.StringToByteArray("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4" +
                                                                  "c5db02d56ecc4c5bf34007208d5b887185865");

            var ikmBytes  = CognitoAuthHelper.StringToByteArray("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
            var saltBytes = CognitoAuthHelper.StringToByteArray("000102030405060708090a0b0c");
            var infoBytes = CognitoAuthHelper.StringToByteArray("f0f1f2f3f4f5f6f7f8f9");
            var length    = 42;

            var hkdfSha256 = new HkdfSha256(saltBytes, ikmBytes);
            var hkdfResult = hkdfSha256.Expand(infoBytes, length);

            Assert.Equal(prkFromSepc, hkdfSha256.Prk);
            Assert.Equal(okmFromSpec, hkdfResult);
        }
        public void TestHkdfVector3()
        {
            // Expected Values
            var prkFromSpec = CognitoAuthHelper.StringToByteArray("19ef24a32c717b167f33a91d6f648bdf96596776afdb6" +
                                                                  "377ac434c1c293ccb04");
            var okmFromSpec = CognitoAuthHelper.StringToByteArray("8da4e775a563c18f715f802a063c5a31b8a11f5c5ee18" +
                                                                  "79ec3454e5f3c738d2d9d201395faa4b61a96c8");

            var ikmBytes  = CognitoAuthHelper.StringToByteArray("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
            var saltBytes = CognitoAuthHelper.StringToByteArray("");
            var infoBytes = CognitoAuthHelper.StringToByteArray("");
            var length    = 42;

            var hkdfSha256 = new HkdfSha256(saltBytes, ikmBytes);
            var hkdfResult = hkdfSha256.Expand(infoBytes, length);

            Assert.Equal(prkFromSpec, hkdfSha256.Prk);
            Assert.Equal(okmFromSpec, hkdfResult);
        }
        /// <summary>
        /// Creates the Device Password Authentication Key based on the SRP protocol
        /// </summary>
        /// <param name="username"> Username of Cognito User</param>
        /// <param name="devicePass">Password of CognitoDevice</param>
        /// <param name="deviceGroup">GroupKey of CognitoDevice</param>
        /// <param name="Aa">Returned from TupleAa</param>
        /// <param name="B">BigInteger SRPB from AWS ChallengeParameters</param>
        /// <param name="salt">BigInteger salt from AWS ChallengeParameters</param>
        /// <returns>Returns the password authentication key for the SRP protocol</returns>
        public static byte[] GetDeviceAuthenticationKey(
            string username,
            string devicePass,
            string deviceGroup,
            Tuple <BigInteger, BigInteger> Aa,
            BigInteger B,
            BigInteger salt)
        {
            // Authenticate the password
            // u = H(A, B)
            byte[] contentBytes = CognitoAuthHelper.CombineBytes(Aa.Item1.ToBigEndianByteArray(), B.ToBigEndianByteArray());
            byte[] digest       = CognitoAuthHelper.Sha256.ComputeHash(contentBytes);

            BigInteger u = BigIntegerExtensions.FromUnsignedBigEndian(digest);

            if (u.Equals(BigInteger.Zero))
            {
                throw new ArgumentException("Hash of A and B cannot be zero.");
            }

            // x = H(salt | H(deviceGroupKey | deviceKey | ":" | devicePassword))
            byte[] deviceContent = CognitoAuthHelper.CombineBytes(Encoding.UTF8.GetBytes(deviceGroup), Encoding.UTF8.GetBytes(username),
                                                                  Encoding.UTF8.GetBytes(":"), Encoding.UTF8.GetBytes(devicePass));
            byte[] deviceHash = CognitoAuthHelper.Sha256.ComputeHash(deviceContent);
            byte[] xBytes     = CognitoAuthHelper.CombineBytes(salt.ToBigEndianByteArray(), deviceHash);

            byte[]     xDigest = CognitoAuthHelper.Sha256.ComputeHash(xBytes);
            BigInteger x       = BigIntegerExtensions.FromUnsignedBigEndian(xDigest);

            var gX = BigInteger.ModPow(g, x, N);
            // Use HKDF to get final password authentication key
            var intValue2 = (B - k * gX).TrueMod(N);
            var s_value   = BigInteger.ModPow(intValue2, Aa.Item2 + u * x, N);

            HkdfSha256 hkdfSha256 = new HkdfSha256(u.ToBigEndianByteArray(), s_value.ToBigEndianByteArray());

            return(hkdfSha256.Expand(Encoding.UTF8.GetBytes(DerivedKeyInfo), DerivedKeySizeBytes));
        }
Example #25
0
        public static void BitMaskedAgree(string privateKey, string publicKey, string sharedSecret)
        {
            var a   = new X25519();
            var kdf = new HkdfSha256();

            var pk1 = publicKey.DecodeHex();
            var pk2 = publicKey.DecodeHex();

            pk1[pk1.Length - 1] &= 0x7F;
            pk2[pk2.Length - 1] |= 0x80;

            using (var k = Key.Import(a, privateKey.DecodeHex(), KeyBlobFormat.RawPrivateKey))
                using (var sharedSecretExpected = SharedSecret.Import(sharedSecret.DecodeHex()))
                    using (var sharedSecretActual1 = a.Agree(k, PublicKey.Import(a, pk1, KeyBlobFormat.RawPublicKey)))
                        using (var sharedSecretActual2 = a.Agree(k, PublicKey.Import(a, pk2, KeyBlobFormat.RawPublicKey)))
                        {
                            var expected = kdf.Extract(sharedSecretExpected, ReadOnlySpan <byte> .Empty);
                            var actual1  = kdf.Extract(sharedSecretActual1, ReadOnlySpan <byte> .Empty);
                            var actual2  = kdf.Extract(sharedSecretActual2, ReadOnlySpan <byte> .Empty);

                            Assert.Equal(expected, actual1);
                            Assert.Equal(expected, actual2);
                        }
        }
Example #26
0
        public static void ExpandWithSpanTooLarge()
        {
            var a = new HkdfSha256();

            Assert.Throws <ArgumentException>("bytes", () => a.Expand(s_prkForEmpty.DecodeHex(), ReadOnlySpan <byte> .Empty, new byte[a.MaxOutputSize + 1]));
        }
Example #27
0
        public static void ExpandWithSpanWithPrkTooShort()
        {
            var a = new HkdfSha256();

            Assert.Throws <ArgumentException>("pseudorandomKey", () => a.Expand(new byte[a.PseudorandomKeySize - 1], ReadOnlySpan <byte> .Empty, new byte[0]));
        }
Example #28
0
        public static void ExpandWithCountTooLarge()
        {
            var a = new HkdfSha256();

            Assert.Throws <ArgumentOutOfRangeException>("count", () => a.Expand(s_prkForEmpty.DecodeHex(), ReadOnlySpan <byte> .Empty, a.MaxOutputSize + 1));
        }
Example #29
0
        public static void ExpandWithNegativeCount()
        {
            var a = new HkdfSha256();

            Assert.Throws <ArgumentOutOfRangeException>("count", () => a.Expand(s_prkForEmpty.DecodeHex(), ReadOnlySpan <byte> .Empty, -1));
        }
Example #30
0
        public static void ExtractWithSpanWithNullSecret()
        {
            var a = new HkdfSha256();

            Assert.Throws <ArgumentNullException>("sharedSecret", () => a.Extract(null, ReadOnlySpan <byte> .Empty, Span <byte> .Empty));
        }