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))); }
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); }
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))); } }
/// <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)); }
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); }
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); }
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); }
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); }
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); }
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); } }
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)); }
public static void ExpandWithNegativeCount() { var a = new HkdfSha256(); Assert.Throws <ArgumentOutOfRangeException>("count", () => a.Expand(s_prkForEmpty.DecodeHex(), ReadOnlySpan <byte> .Empty, -1)); }
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])); }
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])); }
public static void ExpandWithCountTooLarge() { var a = new HkdfSha256(); Assert.Throws <ArgumentOutOfRangeException>("count", () => a.Expand(s_prkForEmpty.DecodeHex(), ReadOnlySpan <byte> .Empty, a.MaxOutputSize + 1)); }