public byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey) { ECPublicKeyParameters publicKey = GetPublicKeyParameters(otherPartyPublicKey); // Calculate the shared secret from public key Org.BouncyCastle.Crypto.Agreement.ECDHBasicAgreement agreement = new Org.BouncyCastle.Crypto.Agreement.ECDHBasicAgreement(); agreement.Init(_privateKeyParameters); byte[] secret = agreement.CalculateAgreement(publicKey).ToByteArray(); // Make sure the secret is always correct length byte[] tmpSecret = new byte[(_keySize+7)/8]; Buffer.BlockCopy(secret, System.Math.Max(0, secret.Length-tmpSecret.Length), tmpSecret, System.Math.Max(0, tmpSecret.Length-secret.Length), System.Math.Min(tmpSecret.Length, secret.Length)); secret = tmpSecret; if (_kdf == ECDiffieHellmanKeyDerivationFunction.Hash || _kdf == ECDiffieHellmanKeyDerivationFunction.Hmac) { HashAlgorithm hashAlgorithm; if (_kdf == ECDiffieHellmanKeyDerivationFunction.Hash) { if (_hashAlgorithm.Equals(CngAlgorithm.MD5)) { hashAlgorithm = new MD5CryptoServiceProvider(); } else if (_hashAlgorithm.Equals(CngAlgorithm.Sha1)) { hashAlgorithm = new SHA1CryptoServiceProvider(); } else if (_hashAlgorithm.Equals(CngAlgorithm.Sha256)) { hashAlgorithm = new SHA256Managed(); } else if (_hashAlgorithm.Equals(CngAlgorithm.Sha384)) { hashAlgorithm = new SHA384Managed(); } else if (_hashAlgorithm.Equals(CngAlgorithm.Sha512)) { hashAlgorithm = new SHA512Managed(); } else { throw new Exception("Unsupported hash algorithm type: " + _hashAlgorithm); } } else { byte[] hmacKey = _hmacKey; if (UseSecretAgreementAsHmacKey) { hmacKey = secret; } if (_hashAlgorithm.Equals(CngAlgorithm.MD5)) { hashAlgorithm = new HMACMD5(hmacKey); } else if (_hashAlgorithm.Equals(CngAlgorithm.Sha1)) { hashAlgorithm = new HMACSHA1(hmacKey); } else if (_hashAlgorithm.Equals(CngAlgorithm.Sha256)) { hashAlgorithm = new HMACSHA256(hmacKey); } else if (_hashAlgorithm.Equals(CngAlgorithm.Sha384)) { hashAlgorithm = new HMACSHA384(hmacKey); } else if (_hashAlgorithm.Equals(CngAlgorithm.Sha512)) { hashAlgorithm = new HMACSHA512(hmacKey); } else { throw new Exception("Unsupported hash algorithm type: " + _hashAlgorithm); } } hashAlgorithm.Initialize(); if (_secretPrepend != null) { hashAlgorithm.TransformBlock(_secretPrepend, 0, _secretPrepend.Length, _secretPrepend, 0); } hashAlgorithm.TransformBlock(secret, 0, secret.Length, secret, 0); if (_secretAppend != null) { hashAlgorithm.TransformBlock(_secretAppend, 0, _secretAppend.Length, _secretAppend, 0); } hashAlgorithm.TransformFinalBlock(new byte[0], 0, 0); return hashAlgorithm.Hash; } throw new Exception("KeyDerivationFunction not implemented yet"); }
public byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey) { ECPublicKeyParameters publicKey = GetPublicKeyParameters(otherPartyPublicKey); // Calculate the shared secret from public key Org.BouncyCastle.Crypto.Agreement.ECDHBasicAgreement agreement = new Org.BouncyCastle.Crypto.Agreement.ECDHBasicAgreement(); agreement.Init(_privateKeyParameters); byte[] secret = agreement.CalculateAgreement(publicKey).ToByteArray(); // Make sure the secret is always correct length byte[] tmpSecret = new byte[(_keySize + 7) / 8]; Buffer.BlockCopy(secret, System.Math.Max(0, secret.Length - tmpSecret.Length), tmpSecret, System.Math.Max(0, tmpSecret.Length - secret.Length), System.Math.Min(tmpSecret.Length, secret.Length)); secret = tmpSecret; if (_kdf == ECDiffieHellmanKeyDerivationFunction.Hash || _kdf == ECDiffieHellmanKeyDerivationFunction.Hmac) { HashAlgorithm hashAlgorithm; if (_kdf == ECDiffieHellmanKeyDerivationFunction.Hash) { if (_hashAlgorithm.Equals(CngAlgorithm.MD5)) { hashAlgorithm = new MD5CryptoServiceProvider(); } else if (_hashAlgorithm.Equals(CngAlgorithm.Sha1)) { hashAlgorithm = new SHA1CryptoServiceProvider(); } else if (_hashAlgorithm.Equals(CngAlgorithm.Sha256)) { hashAlgorithm = new SHA256Managed(); } else if (_hashAlgorithm.Equals(CngAlgorithm.Sha384)) { hashAlgorithm = new SHA384Managed(); } else if (_hashAlgorithm.Equals(CngAlgorithm.Sha512)) { hashAlgorithm = new SHA512Managed(); } else { throw new Exception("Unsupported hash algorithm type: " + _hashAlgorithm); } } else { byte[] hmacKey = _hmacKey; if (UseSecretAgreementAsHmacKey) { hmacKey = secret; } if (_hashAlgorithm.Equals(CngAlgorithm.MD5)) { hashAlgorithm = new HMACMD5(hmacKey); } else if (_hashAlgorithm.Equals(CngAlgorithm.Sha1)) { hashAlgorithm = new HMACSHA1(hmacKey); } else if (_hashAlgorithm.Equals(CngAlgorithm.Sha256)) { hashAlgorithm = new HMACSHA256(hmacKey); } else if (_hashAlgorithm.Equals(CngAlgorithm.Sha384)) { hashAlgorithm = new HMACSHA384(hmacKey); } else if (_hashAlgorithm.Equals(CngAlgorithm.Sha512)) { hashAlgorithm = new HMACSHA512(hmacKey); } else { throw new Exception("Unsupported hash algorithm type: " + _hashAlgorithm); } } hashAlgorithm.Initialize(); if (_secretPrepend != null) { hashAlgorithm.TransformBlock(_secretPrepend, 0, _secretPrepend.Length, _secretPrepend, 0); } hashAlgorithm.TransformBlock(secret, 0, secret.Length, secret, 0); if (_secretAppend != null) { hashAlgorithm.TransformBlock(_secretAppend, 0, _secretAppend.Length, _secretAppend, 0); } hashAlgorithm.TransformFinalBlock(new byte[0], 0, 0); return(hashAlgorithm.Hash); } throw new Exception("KeyDerivationFunction not implemented yet"); }
/// <summary> /// Connects to the specified device and completes encryption handshake/key generation. /// </summary> /// <param name="deviceName">Name of the device to connect to.</param> public async Task <bool> ConnectToDevice(string deviceName) //, Func<bool> DisconnectedHanlder { //adapter.DeviceConnectionLost += (s, a) => //{ // DisconnectedHanlder(); //}; try { IDevice device = null; foreach (IDevice i in deviceList) { if (i.Name == deviceName) { device = i; break; } } await adapter.ConnectToDeviceAsync(device); OnPropertyChanged("BluetoothState"); PairedDevice = device; var service = await device.GetServiceAsync(Guid.Parse("913CF3FD-7173-43A5-82F4-DFD6F61BAF5F")); characteristic = await service.GetCharacteristicAsync(Guid.Parse("44B1DF4E-15C8-4F97-9F34-123D33B0C29D")); X9ECParameters x9 = ECNamedCurveTable.GetByName("secp256r1"); ECCurve curve = x9.Curve; ECDomainParameters ecDomain = new ECDomainParameters(x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed()); ECKeyPairGenerator generator = (ECKeyPairGenerator)GeneratorUtilities.GetKeyPairGenerator("ECDH"); generator.Init(new ECKeyGenerationParameters(ecDomain, new SecureRandom())); AsymmetricCipherKeyPair appKeyPair = generator.GenerateKeyPair(); ECPublicKeyParameters appPublicKey = (ECPublicKeyParameters)appKeyPair.Public; ECPrivateKeyParameters appPrivateKey = (ECPrivateKeyParameters)appKeyPair.Private; // Wait for Arduino Public Key characteristic.ValueUpdated += GetPubKeyPortion; await characteristic.StartUpdatesAsync(); Task.Run(CheckIfKeyObtainComplete).Wait(); // Once full Key has been obtained, stop reading characteristic and unregister handler await characteristic.StopUpdatesAsync(); characteristic.ValueUpdated -= GetPubKeyPortion; // Cut off 'starting' padding from beginning of arduino's public key & convert to byte array ArdPubKeyStr = ArdPubKeyStr.Substring(8); // Now send the app's public key to arduino via same characteristic string appPublicKeyStr = appPublicKey.Q.ToString(); string appPubKey_x = appPublicKey.Q.XCoord.ToString(); string appPubKey_y = appPublicKey.Q.YCoord.ToString(); for (int i = 0; i < 64 - appPubKey_x.Length; i++) { appPubKey_x = "0" + appPubKey_x; } for (int i = 0; i < 64 - appPubKey_y.Length; i++) { appPubKey_y = "0" + appPubKey_y; } appPublicKeyStr = appPubKey_x + appPubKey_y; char[] pubkey_chars = appPublicKeyStr.ToCharArray(); byte[] pubkey_bytes = new byte[128]; for (int i = 0; i < 128; i++) { pubkey_bytes[i] = Convert.ToByte(pubkey_chars[i]); } byte[][] chunks = pubkey_bytes .Select((c, i) => new { Value = c, Index = i }) .GroupBy(x => x.Index / 16) .Select(grp => grp.Select(x => x.Value).ToArray()) .ToArray(); foreach (byte[] b in chunks) { await characteristic.WriteAsync(b); } BigInteger Q_x = new BigInteger(1, StringToByteArray(ArdPubKeyStr.Substring(0, 64))); BigInteger Q_y = new BigInteger(1, StringToByteArray(ArdPubKeyStr.Substring(64, 64))); ECPoint Q = curve.CreatePoint(Q_x, Q_y); ECPublicKeyParameters ArdPubKey = new ECPublicKeyParameters(Q, ecDomain); // Extract the shared secret for decryption IBasicAgreement agreement = new Org.BouncyCastle.Crypto.Agreement.ECDHBasicAgreement(); agreement.Init(appPrivateKey); sharedKey = agreement.CalculateAgreement(ArdPubKey); Debug.WriteLine("Shared KEY: " + ByteArrayToString(sharedKey.ToByteArrayUnsigned())); characteristic.ValueUpdated += GetEncryptedMessagePortion; await characteristic.StartUpdatesAsync(); return(true); } catch (DeviceConnectionException) { Debug.WriteLine("Could not connect to device"); return(false); } catch (Exception e) { Debug.WriteLine(e.Message); return(false); } }