public static void DeriveKeyWithDisposedSecret(KeyDerivationAlgorithm a) { var s = SharedSecret.Import(Utilities.RandomBytes.Slice(0, 32)); s.Dispose(); Assert.Throws <ObjectDisposedException>(() => a.DeriveKey(s, ReadOnlySpan <byte> .Empty, ReadOnlySpan <byte> .Empty, AeadAlgorithm.ChaCha20Poly1305)); }
public static void DeriveBytesWithDisposedSecretAndSpan(KeyDerivationAlgorithm a) { var s = SharedSecret.Import(Utilities.RandomBytes.Slice(0, 32)); s.Dispose(); Assert.Throws <ObjectDisposedException>(() => a.DeriveBytes(s, ReadOnlySpan <byte> .Empty, ReadOnlySpan <byte> .Empty, Span <byte> .Empty)); }
public void TestHkdkf() { var hkdkf = new HkdfSha512(); var result = hkdkf.DeriveBytes(SharedSecret.Import(HkdfIkm), HkdfSalt, HkdfInfo, 42); Assert.Equal(HkdfOkm, result); }
public static void ExtractWithSpanTooLong() { var a = KeyDerivationAlgorithm.HkdfSha256; using var s = SharedSecret.Import(ReadOnlySpan <byte> .Empty); Assert.Throws <ArgumentException>("pseudorandomKey", () => a.Extract(s, ReadOnlySpan <byte> .Empty, new byte[a.PseudorandomKeySize + 1])); }
public static void ImportEmpty() { using (var s = SharedSecret.Import(ReadOnlySpan <byte> .Empty)) { Assert.NotNull(s); Assert.Equal(0, s.Size); } }
public static void ImportZeros() { var b = new byte[64]; using var s = SharedSecret.Import(b); Assert.NotNull(s); Assert.Equal(b.Length, s.Size); }
public static void ImportNonEmpty() { var b = Utilities.RandomBytes.Slice(0, 57); using var s = SharedSecret.Import(b); Assert.NotNull(s); Assert.Equal(b.Length, s.Size); }
public static void PropertiesAfterDispose() { var b = new byte[64]; var s = SharedSecret.Import(b); s.Dispose(); Assert.NotNull(s); Assert.Equal(b.Length, s.Size); }
public static void ExtractWithSpanTooLong() { var a = new HkdfSha512(); using (var s = SharedSecret.Import(ReadOnlySpan <byte> .Empty)) { Assert.Throws <ArgumentException>("pseudorandomKey", () => a.Extract(s, ReadOnlySpan <byte> .Empty, new byte[a.PseudorandomKeySize + 1])); } }
public static void DeriveBytesWithDisposedSecret(Type algorithmType) { var a = (KeyDerivationAlgorithm)Activator.CreateInstance(algorithmType); var s = SharedSecret.Import(Utilities.RandomBytes.Slice(0, 32)); s.Dispose(); Assert.Throws <ObjectDisposedException>(() => a.DeriveBytes(s, ReadOnlySpan <byte> .Empty, ReadOnlySpan <byte> .Empty, 0)); }
public static void DisposeMoreThanOnce() { var b = new byte[64]; var s = SharedSecret.Import(b); Assert.NotNull(s); s.Dispose(); s.Dispose(); s.Dispose(); }
public static void ImportNonEmpty() { var b = "00010203040506070809".DecodeHex(); using (var s = SharedSecret.Import(b)) { Assert.NotNull(s); Assert.Equal(b.Length, s.Size); } }
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); } }
public static void ExtractSuccess() { var a = KeyDerivationAlgorithm.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); }
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 static void ExtractWithSpanSuccess() { var a = KeyDerivationAlgorithm.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); }
public static void ExtractWithEmptySalt() { const int HashLen = 256 / 8; var a = KeyDerivationAlgorithm.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); }
public static void ExtractWithEmptySalt() { const int HashLen = 512 / 8; var a = new HkdfSha512(); 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); } }
public static void Test(string privateKey, string publicKey, string sharedSecret) { var a = KeyAgreementAlgorithm.X25519; var kdf = KeyDerivationAlgorithm.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)) ?? throw new Xunit.Sdk.NotNullException(); var expected = kdf.Extract(sharedSecretExpected, ReadOnlySpan <byte> .Empty); var actual = kdf.Extract(sharedSecretActual, ReadOnlySpan <byte> .Empty); Assert.Equal(expected, actual); }
public static void ExtractWithSpanWithSaltOverlapping() { var a = KeyDerivationAlgorithm.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); }
public static void ExtractWithSpanSuccess() { var a = new HkdfSha512(); 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); } }
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); } }
public static void ExtractWithSpanWithEmptySalt() { const int HashLen = 256 / 8; var a = KeyDerivationAlgorithm.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 static void ExtractWithSpanWithEmptySalt() { const int HashLen = 512 / 8; var a = new HkdfSha512(); 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 static void BitMaskedAgree(string privateKey, string publicKey, string sharedSecret) { var a = KeyAgreementAlgorithm.X25519; var kdf = KeyDerivationAlgorithm.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)) ?? throw new Xunit.Sdk.NotNullException(); using var sharedSecretActual2 = a.Agree(k, PublicKey.Import(a, pk2, KeyBlobFormat.RawPublicKey)) ?? throw new Xunit.Sdk.NotNullException(); 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); }
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); } }
internal Tlv HandlePairSetupM5Raw(ConnectionSession session, out KeyPair keyPair) { var hdkf = new HkdfSha512(); var accessory = hdkf.DeriveBytes( SharedSecret.Import(SrpInteger.FromHex(session.ServerSession.Key).ToByteArray()), Encoding.UTF8.GetBytes("Pair-Setup-Accessory-Sign-Salt"), Encoding.UTF8.GetBytes("Pair-Setup-Accessory-Sign-Info"), 32); keyPair = KeyGenerator.GenerateNewPair(); var serverUsername = Encoding.UTF8.GetBytes(HapControllerServer.HapControllerId); var material = accessory.Concat(serverUsername).Concat(keyPair.PublicKey).ToArray(); var signature = Chaos.NaCl.Ed25519.Sign(material, keyPair.PrivateKey); var encoder = new Tlv(); encoder.AddType(Constants.Identifier, serverUsername); encoder.AddType(Constants.PublicKey, keyPair.PublicKey); encoder.AddType(Constants.Signature, signature); return(encoder); }
public byte[] decrypt(byte[] data) { SharedSecret secret = SharedSecret.Import(motherKey); byte[] seconds = new byte[4]; Array.Copy(data, 0, seconds, 0, 4); Console.WriteLine("Seconds size: " + seconds.Length); Console.WriteLine("Seconds: " + BitConverter.ToInt32(seconds)); byte[] IV = new byte[12]; Array.Copy(data, 4, IV, 0, 12); Console.WriteLine("IV size: " + IV.Length); Console.WriteLine("IV: " + BitConverter.ToString(IV)); byte[] ciphertext = new byte[data.Length - 16]; Array.Copy(data, 16, ciphertext, 0, ciphertext.Length); Console.WriteLine("Ciphertext size: " + ciphertext.Length); Console.WriteLine("Ciphertext: " + BitConverter.ToString(ciphertext)); Key keyCipher = KeyDerivationAlgorithm.HkdfSha256.DeriveKey(secret, seconds, null, ChaCha20Poly1305.ChaCha20Poly1305); byte[] plaintext = new byte[ciphertext.Length - ChaCha20Poly1305.ChaCha20Poly1305.TagSize]; bool decrypt = ChaCha20Poly1305.ChaCha20Poly1305.Decrypt(keyCipher, new Nonce(IV, 0), null, ciphertext, plaintext); if (decrypt) { Console.WriteLine("Decryption successful, plaintext: " + BitConverter.ToString(plaintext)); return(plaintext); } else { Console.WriteLine("Decryption unsuccessful"); return(null); } }
public PairSetupReturn Post(Tlv parts) { var customParams = SrpParameters.Create3072 <SHA512>(); var state = parts.GetTypeAsInt(Constants.State); if (state == 1) //srp sign up { var rnd = new Random(); _salt = new byte[16]; rnd.NextBytes(_salt); _saltInt = SrpInteger.FromByteArray(_salt); var srp = new SrpClient(customParams); _privateKey = srp.DerivePrivateKey(_saltInt.ToHex(), Username, _code); _verifier = srp.DeriveVerifier(_privateKey); _server = new SrpServer(customParams); _serverEphemeral = _server.GenerateEphemeral(_verifier); var responseTlv = new Tlv(); responseTlv.AddType(Constants.State, 2); responseTlv.AddType(Constants.PublicKey, StringToByteArray(_serverEphemeral.Public)); responseTlv.AddType(Constants.Salt, _salt); return(new PairSetupReturn { State = 1, TlvData = responseTlv, Ok = true }); } if (state == 3) //srp authenticate { _logger.LogDebug("Pair Setup Step 3/6"); _logger.LogDebug("SRP Verify Request"); var pubKey = parts.GetType(Constants.PublicKey); var proof = parts.GetType(Constants.Proof); var iOsPublicKey = SrpInteger.FromByteArray(pubKey); var iOsProof = SrpInteger.FromByteArray(proof); var responseTlv = new Tlv(); responseTlv.AddType(Constants.State, 4); var ok = true; try { _serverSession = _server.DeriveSession(_serverEphemeral.Secret, iOsPublicKey.ToHex(), _saltInt.ToHex(), Username, _verifier, iOsProof.ToHex()); _logger.LogInformation("Verification was successful. Generating Server Proof (M2)"); responseTlv.AddType(Constants.Proof, StringToByteArray(_serverSession.Proof)); } catch (Exception) { ok = false; _logger.LogError("Verification failed as iOS provided code was incorrect"); responseTlv.AddType(Constants.Error, ErrorCodes.Authentication); } return(new PairSetupReturn { State = 3, Ok = ok, TlvData = responseTlv }); } if (state == 5) { _logger.LogDebug("Pair Setup Step 5/6"); _logger.LogDebug("Exchange Response"); try { var iOsEncryptedData = parts.GetType(Constants.EncryptedData).AsSpan(); // A var zeros = new byte[] { 0, 0, 0, 0 }; var nonce = new Nonce(zeros, Encoding.UTF8.GetBytes("PS-Msg05")); var hdkf = new HkdfSha512(); var hkdfEncKey = hdkf.DeriveBytes( SharedSecret.Import(SrpInteger.FromHex(_serverSession.Key).ToByteArray()), Encoding.UTF8.GetBytes("Pair-Setup-Encrypt-Salt"), Encoding.UTF8.GetBytes("Pair-Setup-Encrypt-Info"), 32); var decrypt = AeadAlgorithm.ChaCha20Poly1305.Decrypt( Key.Import(AeadAlgorithm.ChaCha20Poly1305, hkdfEncKey, KeyBlobFormat.RawSymmetricKey), nonce, new byte[0], iOsEncryptedData, out var output); var responseTlv = new Tlv(); responseTlv.AddType(Constants.State, 6); if (!decrypt) { responseTlv.AddType(Constants.Error, ErrorCodes.Authentication); return(new PairSetupReturn { State = 5, TlvData = responseTlv, Ok = false }); } var subData = TlvParser.Parse(output); byte[] username = subData.GetType(Constants.Identifier); byte[] ltpk = subData.GetType(Constants.PublicKey); byte[] proof = subData.GetType(Constants.Signature); var okm = hdkf.DeriveBytes( SharedSecret.Import(SrpInteger.FromHex(_serverSession.Key).ToByteArray()), Encoding.UTF8.GetBytes("Pair-Setup-Controller-Sign-Salt"), Encoding.UTF8.GetBytes("Pair-Setup-Controller-Sign-Info"), 32); var completeData = okm.Concat(username).Concat(ltpk).ToArray(); if (!SignatureAlgorithm.Ed25519.Verify( PublicKey.Import(SignatureAlgorithm.Ed25519, ltpk, KeyBlobFormat.RawPublicKey), completeData, proof)) { var errorTlv = new Tlv(); errorTlv.AddType(Constants.Error, ErrorCodes.Authentication); return(new PairSetupReturn { State = 5, TlvData = errorTlv, Ok = false }); } var accessory = hdkf.DeriveBytes( SharedSecret.Import(SrpInteger.FromHex(_serverSession.Key).ToByteArray()), Encoding.UTF8.GetBytes("Pair-Setup-Accessory-Sign-Salt"), Encoding.UTF8.GetBytes("Pair-Setup-Accessory-Sign-Info"), 32); var seed = new byte[32]; RandomNumberGenerator.Create().GetBytes(seed); Chaos.NaCl.Ed25519.KeyPairFromSeed(out var accessoryLtpk, out var accessoryLtsk, seed); var serverUsername = Encoding.UTF8.GetBytes(HapControllerServer.HapControllerId); var material = accessory.Concat(serverUsername).Concat(accessoryLtpk).ToArray(); var signature = Chaos.NaCl.Ed25519.Sign(material, accessoryLtsk); var encoder = new Tlv(); encoder.AddType(Constants.Identifier, serverUsername); encoder.AddType(Constants.PublicKey, accessoryLtpk); encoder.AddType(Constants.Signature, signature); var plaintext = TlvParser.Serialise(encoder); var nonce6 = new Nonce(zeros, Encoding.UTF8.GetBytes("PS-Msg06")); var encryptedOutput = AeadAlgorithm.ChaCha20Poly1305.Encrypt( Key.Import(AeadAlgorithm.ChaCha20Poly1305, hkdfEncKey, KeyBlobFormat.RawSymmetricKey), nonce6, new byte[0], plaintext); responseTlv.AddType(Constants.EncryptedData, encryptedOutput); return(new PairSetupReturn { State = 5, TlvData = responseTlv, Ok = true, Ltsk = ByteArrayToString(accessoryLtsk), Ltpk = ByteArrayToString(ltpk) }); } catch (Exception e) { _logger.LogError(e, "Could not exchange request"); throw; } } return(null); }
public static void ImportTooLong() { var b = new byte[129]; Assert.Throws <ArgumentException>("sharedSecret", () => SharedSecret.Import(b)); }