示例#1
0
        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");
        }
示例#2
0
        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);
            }
        }