/// <summary>
        /// Creates an encrypted message
        /// </summary>
        /// <param name="recipientsEcPublicKey">The public portion of the message recpient's EC key.</param>
        /// <param name="plaintextMessageAsByteArray">The message to encrypt.</param>
        public EcEncryptedMessageAesCbcHmacSha256(ECDiffieHellmanPublicKey recipientsEcPublicKey, byte[] plaintextMessageAsByteArray)
        {
            ECDiffieHellmanCng oneTimeEcKey = new ECDiffieHellmanCng(CngKey.Create(CngAlgorithm.ECDiffieHellmanP256, null, new CngKeyCreationParameters()));
            PublicOneTimeEcKey = oneTimeEcKey.PublicKey.ToByteArray();

            byte[] sessionKey = oneTimeEcKey.DeriveKeyMaterial(recipientsEcPublicKey);
            EncryptedMessage = Encryption.EncryptAesCbc(plaintextMessageAsByteArray, sessionKey, addHmac: true);
        }
示例#2
0
 /// <summary>
 /// Derive key material using the formula HASH(secretPrepend || x || secretAppend) where x is the computed
 /// result of the EC Diffie-Hellman algorithm.
 /// </summary>
 /// <param name="otherPartyPublicKey">The public key of the party with which to derive a mutual secret.</param>
 /// <param name="hashAlgorithm">The identifier for the hash algorithm to use.</param>
 /// <param name="secretPrepend">A value to prepend to the derived secret before hashing. A <c>null</c> value is treated as an empty array.</param>
 /// <param name="secretAppend">A value to append to the derived secret before hashing. A <c>null</c> value is treated as an empty array.</param>
 /// <returns>A hashed output suitable for key material</returns>
 /// <exception cref="ArgumentException"><paramref name="otherPartyPublicKey"/> is over a different curve than this key</exception>
 public virtual byte[] DeriveKeyFromHash(
     ECDiffieHellmanPublicKey otherPartyPublicKey,
     HashAlgorithmName hashAlgorithm,
     byte[] secretPrepend,
     byte[] secretAppend)
 {
     throw DerivedClassMustOverride();
 }
 public static void ExportKey(string Path, ECDiffieHellmanPublicKey Key)
 {
     using (BinaryWriter Writer = new BinaryWriter(File.Create(Path)))
     {
         Writer.Write((byte)Key.ToByteArray().Length);
         Writer.Write(Key.ToByteArray());
     }
 }
 /// <summary>
 /// Decrypts the provided data.
 /// </summary>
 /// <param name="privateKey">The private key used for decryption.</param>
 /// <param name="publicKey">The public key used for decryption.</param>
 /// <param name="nonce">The nonce used for decryption.</param>
 /// <param name="encryptedData">The data to decrypt.</param>
 /// <returns>The decrypted data.</returns>
 public static byte[] Decrypt(ECDiffieHellmanCng privateKey, ECDiffieHellmanPublicKey publicKey, byte[] nonce, byte[] encryptedData)
 {
     try
     {
         Aes aes = DeriveKeyAndIv(privateKey, publicKey, nonce);
         return aes.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length);
     }
     catch (Exception E)
     {
         throw new DecryptionException(E.ToString());
     }
 }
 /// <summary>
 /// Creates an encrypted message
 /// </summary>
 /// <param name="recipientsEcPublicKey">The public portion of the message recpient's EC key.</param>
 /// <param name="plaintextMessageAsByteArray">The message to encrypt.</param>
 public EcEncryptedMessageAesCbcHmacSha256(ECDiffieHellmanPublicKey recipientsEcPublicKey,
     byte[] plaintextMessageAsByteArray)
 {
     byte[] sessionKey;
     using (CngKey oneTimeEcCngKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256))
     {
         using (ECDiffieHellmanCng oneTimeEcKey = new ECDiffieHellmanCng(oneTimeEcCngKey))
         {
             PublicOneTimeEcKey = oneTimeEcKey.PublicKey.ToByteArray();
             sessionKey = oneTimeEcKey.DeriveKeyMaterial(recipientsEcPublicKey);
         }
     }
     EncryptedMessage = Encryption.EncryptAesCbc(plaintextMessageAsByteArray, sessionKey, addHmac: true);
 }
示例#6
0
        public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
        {
            ArgumentNullException.ThrowIfNull(otherPartyPublicKey);
            ArgumentNullException.ThrowIfNull(prfLabel);
            ArgumentNullException.ThrowIfNull(prfSeed);

            using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
            {
                return(Interop.NCrypt.DeriveKeyMaterialTls(
                           secretAgreement,
                           prfLabel,
                           prfSeed,
                           Interop.NCrypt.SecretAgreementFlags.None));
            }
        }
示例#7
0
        public SafeNCryptSecretHandle DeriveSecretAgreementHandle(ECDiffieHellmanPublicKey otherPartyPublicKey)
        {
            if (otherPartyPublicKey == null)
            {
                throw new ArgumentNullException("otherPartyPublicKey");
            }
            ECDiffieHellmanCngPublicKey key = otherPartyPublicKey as ECDiffieHellmanCngPublicKey;

            if (otherPartyPublicKey == null)
            {
                throw new ArgumentException(System.SR.GetString("Cryptography_ArgExpectedECDiffieHellmanCngPublicKey"));
            }
            using (CngKey key2 = key.Import())
            {
                return(this.DeriveSecretAgreementHandle(key2));
            }
        }
示例#8
0
        public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey)
        {
            if (otherPartyPublicKey == null)
            {
                throw new ArgumentNullException("otherPartyPublicKey");
            }
            ECDiffieHellmanCngPublicKey key = otherPartyPublicKey as ECDiffieHellmanCngPublicKey;

            if (otherPartyPublicKey == null)
            {
                throw new ArgumentException(System.SR.GetString("Cryptography_ArgExpectedECDiffieHellmanCngPublicKey"));
            }
            using (CngKey key2 = key.Import())
            {
                return(this.DeriveKeyMaterial(key2));
            }
        }
示例#9
0
            // For the public ECDiffieHellmanCng this is exposed as the HashAlgorithm property
            // which is a CngAlgorithm type. We're not doing that, but we do need the default value
            // for DeriveKeyMaterial.
            public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey)
            {
                if (otherPartyPublicKey == null)
                {
                    throw new ArgumentNullException(nameof(otherPartyPublicKey));
                }

                // ECDiffieHellmanCng on .NET Framework will throw an ArgumentException in this method
                // if otherPartyPublicKey is not an ECDiffieHellmanCngPublicKey.  All of the other methods
                // will use Import/Export to coerce the correct type for interop.

                // None of the other Core types will match that behavior, so the ECDiffieHellman.Create() on
                // Windows on .NET Core won't, either.

                // The default behavior for ECDiffieHellmanCng / ECDiffieHellman.Create() on .NET Framework was
                // to derive from hash, no prepend, no append, SHA-2-256.
                return(DeriveKeyFromHash(otherPartyPublicKey, HashAlgorithmName.SHA256));
            }
示例#10
0
            public override byte[] DeriveKeyFromHash(
                ECDiffieHellmanPublicKey otherPartyPublicKey,
                HashAlgorithmName hashAlgorithm,
                byte[] secretPrepend,
                byte[] secretAppend)
            {
                if (otherPartyPublicKey == null)
                    throw new ArgumentNullException(nameof(otherPartyPublicKey));
                if (string.IsNullOrEmpty(hashAlgorithm.Name))
                    throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm));

                return ECDiffieHellmanDerivation.DeriveKeyFromHash(
                    otherPartyPublicKey,
                    hashAlgorithm,
                    secretPrepend,
                    secretAppend,
                    (pubKey, hasher) => DeriveSecretAgreement(pubKey, hasher));
            }
示例#11
0
        public override byte[] DeriveKeyFromHash(
            ECDiffieHellmanPublicKey otherPartyPublicKey,
            HashAlgorithmName hashAlgorithm,
            byte[]?secretPrepend,
            byte[]?secretAppend)
        {
            ArgumentNullException.ThrowIfNull(otherPartyPublicKey);
            ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));

            ThrowIfDisposed();

            return(ECDiffieHellmanDerivation.DeriveKeyFromHash(
                       otherPartyPublicKey,
                       hashAlgorithm,
                       secretPrepend,
                       secretAppend,
                       DeriveSecretAgreement));
        }
        private static Aes DeriveKeyAndIv(ECDiffieHellmanCng privateKey, ECDiffieHellmanPublicKey publicKey, byte[] nonce)
        {
            privateKey.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
            privateKey.HashAlgorithm = CngAlgorithm.Sha256;
            privateKey.SecretAppend = nonce;
            byte[] keyAndIv = privateKey.DeriveKeyMaterial(publicKey);
            byte[] key = new byte[16];
            Array.Copy(keyAndIv, 0, key, 0, 16);
            byte[] iv = new byte[16];
            Array.Copy(keyAndIv, 16, iv, 0, 16);

            Aes aes = new AesManaged();
            aes.Key = key;
            aes.IV = iv;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;

            return aes;
        }
示例#13
0
        /// <summary>
        ///     Get a handle to the secret agreement generated between two parties
        /// </summary>
        public SafeNCryptSecretHandle DeriveSecretAgreementHandle(ECDiffieHellmanPublicKey otherPartyPublicKey)
        {
            if (otherPartyPublicKey == null)
            {
                throw new ArgumentNullException("otherPartyPublicKey");
            }

            // We can only work with ECDiffieHellmanCngPublicKeys
            ECDiffieHellmanCngPublicKey otherKey = otherPartyPublicKey as ECDiffieHellmanCngPublicKey;

            if (otherPartyPublicKey == null)
            {
                throw new ArgumentException(SR.GetString(SR.Cryptography_ArgExpectedECDiffieHellmanCngPublicKey));
            }

            using (CngKey importedKey = otherKey.Import()) {
                return(DeriveSecretAgreementHandle(importedKey));
            }
        }
示例#14
0
        public override byte[] DeriveKeyFromHash(
            ECDiffieHellmanPublicKey otherPartyPublicKey,
            HashAlgorithmName hashAlgorithm,
            byte[]?secretPrepend,
            byte[]?secretAppend)
        {
            ArgumentNullException.ThrowIfNull(otherPartyPublicKey);
            ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));

            using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
            {
                return(Interop.NCrypt.DeriveKeyMaterialHash(
                           secretAgreement,
                           hashAlgorithm.Name,
                           secretPrepend,
                           secretAppend,
                           Interop.NCrypt.SecretAgreementFlags.None));
            }
        }
示例#15
0
        public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
        {
            if (otherPartyPublicKey == null)
            {
                throw new ArgumentNullException(nameof(otherPartyPublicKey));
            }
            if (prfLabel == null)
            {
                throw new ArgumentNullException(nameof(prfLabel));
            }
            if (prfSeed == null)
            {
                throw new ArgumentNullException(nameof(prfSeed));
            }

            return(ECDiffieHellmanDerivation.DeriveKeyTls(
                       otherPartyPublicKey,
                       prfLabel,
                       prfSeed,
                       (pubKey, hasher) => DeriveSecretAgreement(pubKey, hasher)));
        }
        internal static byte[] DeriveKeyFromHash(
            ECDiffieHellmanPublicKey otherPartyPublicKey,
            HashAlgorithmName hashAlgorithm,
            ReadOnlySpan <byte> secretPrepend,
            ReadOnlySpan <byte> secretAppend,
            DeriveSecretAgreement deriveSecretAgreement)
        {
            Debug.Assert(otherPartyPublicKey != null);
            Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name));

            using (IncrementalHash hash = IncrementalHash.CreateHash(hashAlgorithm))
            {
                hash.AppendData(secretPrepend);

                byte[]? secretAgreement = deriveSecretAgreement(otherPartyPublicKey, hash);
                // We want the side effect, and it should not have returned the answer.
                Debug.Assert(secretAgreement == null);

                hash.AppendData(secretAppend);

                return(hash.GetHashAndReset());
            }
        }
示例#17
0
        /// <summary>
        ///     Given a second party's public key, derive shared key material
        /// </summary>
        public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey)
        {
            Contract.Ensures(Contract.Result <byte[]>() != null);
            Contract.Assert(m_kdf >= ECDiffieHellmanKeyDerivationFunction.Hash &&
                            m_kdf <= ECDiffieHellmanKeyDerivationFunction.Tls);

            if (otherPartyPublicKey == null)
            {
                throw new ArgumentNullException("otherPartyPublicKey");
            }

            // We can only work with ECDiffieHellmanCngPublicKeys
            ECDiffieHellmanCngPublicKey otherKey = otherPartyPublicKey as ECDiffieHellmanCngPublicKey;

            if (otherKey == null)
            {
                throw new ArgumentException(SR.GetString(SR.Cryptography_ArgExpectedECDiffieHellmanCngPublicKey));
            }

            using (CngKey import = otherKey.Import()) {
                return(DeriveKeyMaterial(import));
            }
        }
示例#18
0
        /// <summary>
        ///     Get a handle to the secret agreement generated between two parties
        /// </summary>
        public SafeNCryptSecretHandle DeriveSecretAgreementHandle(ECDiffieHellmanPublicKey otherPartyPublicKey)
        {
            if (otherPartyPublicKey == null)
            {
                throw new ArgumentNullException(nameof(otherPartyPublicKey));
            }

            if (otherPartyPublicKey is ECDiffieHellmanCngPublicKey otherKey)
            {
                using (CngKey importedKey = otherKey.Import())
                {
                    return(DeriveSecretAgreementHandle(importedKey));
                }
            }

            ECParameters otherPartyParameters = otherPartyPublicKey.ExportParameters();

            using (ECDiffieHellmanCng otherPartyCng = (ECDiffieHellmanCng)Create(otherPartyParameters))
                using (otherKey = (ECDiffieHellmanCngPublicKey)otherPartyCng.PublicKey)
                    using (CngKey importedKey = otherKey.Import())
                    {
                        return(DeriveSecretAgreementHandle(importedKey));
                    }
        }
        public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
        {
            if (otherPartyPublicKey == null)
            {
                throw new ArgumentNullException(nameof(otherPartyPublicKey));
            }
            if (prfLabel == null)
            {
                throw new ArgumentNullException(nameof(prfLabel));
            }
            if (prfSeed == null)
            {
                throw new ArgumentNullException(nameof(prfSeed));
            }

            using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
            {
                return(Interop.NCrypt.DeriveKeyMaterialTls(
                           secretAgreement,
                           prfLabel,
                           prfSeed,
                           Interop.NCrypt.SecretAgreementFlags.None));
            }
        }
示例#20
0
            /// <summary>
            /// Get the secret agreement generated between two parties
            /// </summary>
            private byte[]? DeriveSecretAgreement(ECDiffieHellmanPublicKey otherPartyPublicKey, IncrementalHash?hasher)
            {
                Debug.Assert(otherPartyPublicKey != null);

                // Ensure that this ECDH object contains a private key by attempting a parameter export
                // which will throw an OpenSslCryptoException if no private key is available
                ECParameters thisKeyExplicit             = ExportExplicitParameters(true);
                bool         thisIsNamed                 = Interop.AndroidCrypto.EcKeyHasCurveName(_key.Value);
                ECDiffieHellmanAndroidPublicKey?otherKey = otherPartyPublicKey as ECDiffieHellmanAndroidPublicKey;
                bool disposeOtherKey = false;

                if (otherKey == null)
                {
                    disposeOtherKey = true;

                    ECParameters otherParameters =
                        thisIsNamed
                            ? otherPartyPublicKey.ExportParameters()
                            : otherPartyPublicKey.ExportExplicitParameters();

                    otherKey = new ECDiffieHellmanAndroidPublicKey(otherParameters);
                }

                bool otherIsNamed = otherKey.HasCurveName;

                SafeEcKeyHandle?ourKey   = null;
                SafeEcKeyHandle?theirKey = null;

                byte[]? rented = null;
                // Calculate secretLength in bytes.
                int secretLength = AsymmetricAlgorithmHelpers.BitsToBytes(KeySize);

                try
                {
                    if (otherKey.KeySize != KeySize)
                    {
                        throw new ArgumentException(SR.Cryptography_ArgECDHKeySizeMismatch, nameof(otherPartyPublicKey));
                    }

                    if (otherIsNamed == thisIsNamed)
                    {
                        ourKey   = _key.UpRefKeyHandle();
                        theirKey = otherKey.DuplicateKeyHandle();
                    }
                    else if (otherIsNamed)
                    {
                        ourKey = _key.UpRefKeyHandle();

                        using (ECAndroid tmp = new ECAndroid(otherKey.ExportExplicitParameters()))
                        {
                            theirKey = tmp.UpRefKeyHandle();
                        }
                    }
                    else
                    {
                        using (ECAndroid tmp = new ECAndroid(thisKeyExplicit))
                        {
                            ourKey = tmp.UpRefKeyHandle();
                        }

                        theirKey = otherKey.DuplicateKeyHandle();
                    }

                    // Indicate that secret can hold stackallocs from nested scopes
                    Span <byte> secret = stackalloc byte[0];

                    // Arbitrary limit. But it covers secp521r1, which is the biggest common case.
                    const int StackAllocMax = 66;

                    if (secretLength > StackAllocMax)
                    {
                        rented = CryptoPool.Rent(secretLength);
                        secret = new Span <byte>(rented, 0, secretLength);
                    }
                    else
                    {
                        secret = stackalloc byte[secretLength];
                    }

                    if (!Interop.AndroidCrypto.EcdhDeriveKey(ourKey, theirKey, secret, out int usedBufferLength))
                    {
                        throw new CryptographicException();
                    }

                    Debug.Assert(secretLength == usedBufferLength, $"Expected secret length {secretLength} does not match actual secret length {usedBufferLength}.");

                    if (hasher == null)
                    {
                        return(secret.ToArray());
                    }
                    else
                    {
                        hasher.AppendData(secret);
                        return(null);
                    }
                }
                finally
                {
                    theirKey?.Dispose();
                    ourKey?.Dispose();

                    if (disposeOtherKey)
                    {
                        otherKey.Dispose();
                    }

                    if (rented != null)
                    {
                        CryptoPool.Return(rented, secretLength);
                    }
                }
            }
示例#21
0
 // This method must be implemented by derived classes. In order to conform to the contract, it cannot be abstract.
 public virtual byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey)
 {
     throw DerivedClassMustOverride();
 }
 public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey !!)
 {
     if (otherPartyPublicKey is ECDiffieHellmanCngPublicKey otherKey)
        /// <summary>
        ///     Get a handle to the secret agreement generated between two parties
        /// </summary>
        public SafeNCryptSecretHandle DeriveSecretAgreementHandle(ECDiffieHellmanPublicKey otherPartyPublicKey) {
            if (otherPartyPublicKey == null) {
                throw new ArgumentNullException("otherPartyPublicKey");
            }
            
            // We can only work with ECDiffieHellmanCngPublicKeys
            ECDiffieHellmanCngPublicKey otherKey = otherPartyPublicKey as ECDiffieHellmanCngPublicKey;
            if (otherPartyPublicKey == null) {
                throw new ArgumentException(SR.GetString(SR.Cryptography_ArgExpectedECDiffieHellmanCngPublicKey));
            }

            using (CngKey importedKey = otherKey.Import()) {
                return DeriveSecretAgreementHandle(importedKey);
            }
        }
示例#24
0
 public override byte[] DeriveKeyFromHash(
     ECDiffieHellmanPublicKey otherPartyPublicKey !!,
            private byte[]? DeriveSecretAgreement(ECDiffieHellmanPublicKey otherPartyPublicKey, IncrementalHash?hasher)
            {
                if (!(otherPartyPublicKey is ECDiffieHellmanSecurityTransformsPublicKey secTransPubKey))
                {
                    secTransPubKey =
                        new ECDiffieHellmanSecurityTransformsPublicKey(otherPartyPublicKey.ExportParameters());
                }

                try
                {
                    SafeSecKeyRefHandle otherPublic = secTransPubKey.KeyHandle;

                    if (Interop.AppleCrypto.EccGetKeySizeInBits(otherPublic) != KeySize)
                    {
                        throw new ArgumentException(
                                  SR.Cryptography_ArgECDHKeySizeMismatch,
                                  nameof(otherPartyPublicKey));
                    }

                    SafeSecKeyRefHandle?thisPrivate = GetKeys().PrivateKey;

                    if (thisPrivate == null)
                    {
                        throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey);
                    }

                    // Since Apple only supports secp256r1, secp384r1, and secp521r1; and 521 fits in
                    // 66 bytes ((521 + 7) / 8), the Span path will always succeed.
                    Span <byte> secretSpan = stackalloc byte[66];

                    byte[]? secret = Interop.AppleCrypto.EcdhKeyAgree(
                        thisPrivate,
                        otherPublic,
                        secretSpan,
                        out int bytesWritten);

                    // Either we wrote to the span or we returned an array, but not both, and not neither.
                    // ("neither" would have thrown)
                    Debug.Assert(
                        (bytesWritten == 0) != (secret == null),
                        $"bytesWritten={bytesWritten}, (secret==null)={secret == null}");

                    if (hasher == null)
                    {
                        return(secret ?? secretSpan.Slice(0, bytesWritten).ToArray());
                    }

                    if (secret == null)
                    {
                        hasher.AppendData(secretSpan.Slice(0, bytesWritten));
                    }
                    else
                    {
                        hasher.AppendData(secret);
                        Array.Clear(secret, 0, secret.Length);
                    }

                    return(null);
                }
                finally
                {
                    if (!ReferenceEquals(otherPartyPublicKey, secTransPubKey))
                    {
                        secTransPubKey.Dispose();
                    }
                }
            }
 public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey)
 {
     if (otherPartyPublicKey == null)
     {
         throw new ArgumentNullException("otherPartyPublicKey");
     }
     ECDiffieHellmanCngPublicKey key = otherPartyPublicKey as ECDiffieHellmanCngPublicKey;
     if (otherPartyPublicKey == null)
     {
         throw new ArgumentException(System.SR.GetString("Cryptography_ArgExpectedECDiffieHellmanCngPublicKey"));
     }
     using (CngKey key2 = key.Import())
     {
         return this.DeriveKeyMaterial(key2);
     }
 }
    public Microsoft.Win32.SafeHandles.SafeNCryptSecretHandle DeriveSecretAgreementHandle(ECDiffieHellmanPublicKey otherPartyPublicKey)
    {
      Contract.Ensures(this.Key.Handle != null);

      return default(Microsoft.Win32.SafeHandles.SafeNCryptSecretHandle);
    }
        public override byte[] ProcessServerKeys(ProtocolVersion version, byte[] data)
        {
            // Only ECCurveType.named_curve is supported
            if (data[0] != 3) {
                throw new Exception("ECCurveType " + data[0] + " is not supported");
            }

            // Create our ECDiffieHellmanCng provider with correct curve
            UInt16 namedCurve = (UInt16) ((data[1] << 8) + data[2]);
            _ecdhCng = new ECDiffieHellmanCng(NamedCurveToKeySize(namedCurve));

            // Extract the ECPoint data
            int keyLength = data[3];
            byte[] ecPoint = new byte[keyLength];
            Buffer.BlockCopy(data, 4, ecPoint, 0, keyLength);

            // Extract the signature
            byte[] signature = new byte[data.Length-4-keyLength];
            Buffer.BlockCopy(data, 4+keyLength, signature, 0, data.Length-4-keyLength);

            // Create the public key from the ecPoint
            byte[] keyBlob = Point2Blob(ecPoint);
            _publicKey = ECDiffieHellmanCngPublicKey.FromByteArray(keyBlob, CngKeyBlobFormat.EccPublicBlob);

            return signature;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ECDiffieHellmanPublicKey"/> class.
        /// </summary>
        /// <param name="publicKey">The underlying platform public key.</param>
        internal ECDiffieHellmanPublicKey(Platform.ECDiffieHellmanPublicKey publicKey)
        {
            Requires.NotNull(publicKey, nameof(publicKey));

            this.publicKey = publicKey;
        }
示例#30
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ECDiffieHellmanPublicKey"/> class.
        /// </summary>
        /// <param name="publicKey">The underlying platform public key.</param>
        internal ECDiffieHellmanPublicKey(Platform.ECDiffieHellmanPublicKey publicKey)
        {
            Requires.NotNull(publicKey, nameof(publicKey));

            this.publicKey = publicKey;
        }
示例#31
0
 public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey) =>
 _wrapped.DeriveKeyMaterial(Unwrap(otherPartyPublicKey));
示例#32
0
        private ECPublicKeyParameters GetPublicKeyParameters(ECDiffieHellmanPublicKey publicKey)
        {
            byte[] ecdhBlob = publicKey.ToByteArray();

            int keySize;
            string magic = Encoding.ASCII.GetString(ecdhBlob, 0, 4);
            if (magic.Equals("ECK1")) {
                keySize = 256;
            } else if (magic.Equals("ECK3")) {
                keySize = 384;
            } else if (magic.Equals("ECK5")) {
                keySize = 521;
            } else {
                throw new Exception("Unknown public key type");
            }
            if (keySize != _keySize) {
                throw new Exception("Public key size doesn't match our key size");
            }

            byte[] encoded = new byte[1 + ecdhBlob.Length - 8];
            encoded[0] = 0x04;
            Buffer.BlockCopy(ecdhBlob, 8, encoded, 1, ecdhBlob.Length - 8);
            Org.BouncyCastle.Math.EC.ECPoint ecPoint = _domainParameters.Curve.DecodePoint(encoded);
            return new ECPublicKeyParameters(ecPoint, _domainParameters);
        }
示例#33
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");
        }
 public SafeNCryptSecretHandle DeriveSecretAgreementHandle(ECDiffieHellmanPublicKey otherPartyPublicKey)
 {
     if (otherPartyPublicKey == null)
     {
         throw new ArgumentNullException("otherPartyPublicKey");
     }
     ECDiffieHellmanCngPublicKey key = otherPartyPublicKey as ECDiffieHellmanCngPublicKey;
     if (otherPartyPublicKey == null)
     {
         throw new ArgumentException(System.SR.GetString("Cryptography_ArgExpectedECDiffieHellmanCngPublicKey"));
     }
     using (CngKey key2 = key.Import())
     {
         return this.DeriveSecretAgreementHandle(key2);
     }
 }
 public abstract byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey);
示例#36
0
 /// <summary>
 /// Derive key material using the formula HMAC(hmacKey, x) where x is the computed
 /// result of the EC Diffie-Hellman algorithm.
 /// </summary>
 /// <param name="otherPartyPublicKey">The public key of the party with which to derive a mutual secret.</param>
 /// <param name="hashAlgorithm">The identifier for the hash algorithm to use.</param>
 /// <param name="hmacKey">The key to use in the HMAC. A <c>null</c> value indicates that the result of the EC Diffie-Hellman algorithm should be used as the HMAC key.</param>
 /// <returns>A hashed output suitable for key material</returns>
 /// <exception cref="ArgumentException"><paramref name="otherPartyPublicKey"/> is over a different curve than this key</exception>
 public byte[] DeriveKeyFromHmac(
     ECDiffieHellmanPublicKey otherPartyPublicKey,
     HashAlgorithmName hashAlgorithm,
     byte[] hmacKey)
 {
     return DeriveKeyFromHmac(otherPartyPublicKey, hashAlgorithm, hmacKey, null, null);
 }
示例#37
0
 /// <summary>
 /// Encrypt a plaintext incorrect password with the account's EC Diffie Helman public key so that it can
 /// be safely stored until the correct password is provided in the future.  Store it in the
 /// EncryptedIncorrectPassword field.  (This doesn't expose information about the correct password because
 /// the corresponding EC secret key needed to decrypt this incorrect password is itself encrypted with the
 /// phase1 hash of the correct password.)
 /// 
 /// The encryption format is a JSON-encoded EcEncryptedMessageAesCbcHmacSha256.
 /// </summary>
 /// <param name="incorrectPassword">The incorrect password to be stored into the EncryptedIncorrectPassword
 /// field.</param>
 /// <param name="ecPublicLogKey">The public key used to encrypt the incorrect password.</param>
 public void EncryptAndWriteIncorrectPassword(string incorrectPassword, ECDiffieHellmanPublicKey ecPublicLogKey)
 {
     EncryptedIncorrectPassword = JsonConvert.SerializeObject(
         new EcEncryptedMessageAesCbcHmacSha256(ecPublicLogKey, Encoding.UTF8.GetBytes(incorrectPassword)));
 }
        internal static unsafe byte[] DeriveKeyTls(
            ECDiffieHellmanPublicKey otherPartyPublicKey,
            ReadOnlySpan <byte> prfLabel,
            ReadOnlySpan <byte> prfSeed,
            DeriveSecretAgreement deriveSecretAgreement)
        {
            Debug.Assert(otherPartyPublicKey != null);

            if (prfSeed.Length != 64)
            {
                throw new CryptographicException(SR.Cryptography_TlsRequires64ByteSeed);
            }

            // Windows produces a 48-byte output, so that's what we do, too.
            byte[] ret = new byte[48];

            const int Sha1Size = 20;
            const int Md5Size  = 16;

            byte[]? secretAgreement = deriveSecretAgreement(otherPartyPublicKey, null);
            Debug.Assert(secretAgreement != null);

            // Reduce the likelihood of the value getting copied during heap compaction.
            fixed(byte *pinnedSecretAgreement = secretAgreement)
            {
                try
                {
                    // https://tools.ietf.org/html/rfc4346#section-5
                    //
                    //    S1 and S2 are the two halves of the secret, and each is the same
                    //    length.  S1 is taken from the first half of the secret, S2 from the
                    //    second half.  Their length is created by rounding up the length of
                    //    the overall secret, divided by two; thus, if the original secret is
                    //    an odd number of bytes long, the last byte of S1 will be the same as
                    //    the first byte of S2.
                    //
                    int half = secretAgreement.Length / 2;
                    int odd  = secretAgreement.Length & 1;

                    // PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
                    //                            P_SHA-1(S2, label + seed);

                    PHash(
                        HashAlgorithmName.MD5,
                        new ReadOnlySpan <byte>(secretAgreement, 0, half + odd),
                        prfLabel,
                        prfSeed,
                        Md5Size,
                        ret);

                    Span <byte> part2 = stackalloc byte[ret.Length];

                    PHash(
                        HashAlgorithmName.SHA1,
                        new ReadOnlySpan <byte>(secretAgreement, half, half + odd),
                        prfLabel,
                        prfSeed,
                        Sha1Size,
                        part2);

                    for (int i = 0; i < ret.Length; i++)
                    {
                        ret[i] ^= part2[i];
                    }

                    return(ret);
                }
                finally
                {
                    Array.Clear(secretAgreement, 0, secretAgreement.Length);
                }
            }
        }
示例#39
0
        public override byte[] DeriveKeyFromHmac(
            ECDiffieHellmanPublicKey otherPartyPublicKey,
            HashAlgorithmName hashAlgorithm,
            byte[] hmacKey,
            byte[] secretPrepend,
            byte[] secretAppend)
        {
            Contract.Ensures(Contract.Result<byte[]>() != null);

            if (otherPartyPublicKey == null)
                throw new ArgumentNullException("otherPartyPublicKey");
            if (string.IsNullOrEmpty(hashAlgorithm.Name))
                throw new ArgumentException(SR.GetString(SR.Cryptography_HashAlgorithmNameNullOrEmpty), "hashAlgorithm");

            using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
            {
                NCryptNative.SecretAgreementFlags flags = hmacKey == null ?
                    NCryptNative.SecretAgreementFlags.UseSecretAsHmacKey :
                    NCryptNative.SecretAgreementFlags.None;

                return NCryptNative.DeriveKeyMaterialHmac(
                    secretAgreement,
                    hashAlgorithm.Name,
                    hmacKey,
                    secretPrepend,
                    secretAppend,
                    flags);
            }
        }
        /// <summary>
        ///     Given a second party's public key, derive shared key material
        /// </summary>
        public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey) {
            Contract.Ensures(Contract.Result<byte[]>() != null);
            Contract.Assert(m_kdf >= ECDiffieHellmanKeyDerivationFunction.Hash &&
                            m_kdf <= ECDiffieHellmanKeyDerivationFunction.Tls);

            if (otherPartyPublicKey == null) {
                throw new ArgumentNullException("otherPartyPublicKey");
            }

            // We can only work with ECDiffieHellmanCngPublicKeys
            ECDiffieHellmanCngPublicKey otherKey = otherPartyPublicKey as ECDiffieHellmanCngPublicKey;
            if (otherPartyPublicKey == null) {
                throw new ArgumentException(SR.GetString(SR.Cryptography_ArgExpectedECDiffieHellmanCngPublicKey));
            }

            using (CngKey import = otherKey.Import()) {
                return DeriveKeyMaterial(import);
            }
        }
示例#41
0
        public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
        {
            Contract.Ensures(Contract.Result<byte[]>() != null);

            if (otherPartyPublicKey == null)
                throw new ArgumentNullException("otherPartyPublicKey");
            if (prfLabel == null)
                throw new ArgumentNullException("prfLabel");
            if (prfSeed == null)
                throw new ArgumentNullException("prfSeed");

            using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
            {
                return NCryptNative.DeriveKeyMaterialTls(
                    secretAgreement,
                    prfLabel,
                    prfSeed,
                    NCryptNative.SecretAgreementFlags.None);
            }
        }
 public abstract byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey);
 public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey)
 {
   return default(byte[]);
 }
示例#44
0
 /// <summary>
 /// Derive key material using the TLS pseudo-random function (PRF) derivation algorithm.
 /// </summary>
 /// <param name="otherPartyPublicKey">The public key of the party with which to derive a mutual secret.</param>
 /// <param name="prfLabel">The ASCII encoded PRF label.</param>
 /// <param name="prfSeed">The 64-byte PRF seed.</param>
 /// <returns>A 48-byte output of the TLS pseudo-random function.</returns>
 /// <exception cref="ArgumentException"><paramref name="otherPartyPublicKey"/> is over a different curve than this key</exception>
 /// <exception cref="ArgumentNullException"><paramref name="prfLabel"/> is null</exception>
 /// <exception cref="ArgumentNullException"><paramref name="prfSeed"/> is null</exception>
 /// <exception cref="CryptographicException"><paramref name="prfSeed"/> is not exactly 64 bytes in length</exception>
 public virtual byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
 {
     throw DerivedClassMustOverride();
 }
示例#45
0
 /// <summary>
 /// Derive key material using the TLS pseudo-random function (PRF) derivation algorithm.
 /// </summary>
 /// <param name="otherPartyPublicKey">The public key of the party with which to derive a mutual secret.</param>
 /// <param name="prfLabel">The ASCII encoded PRF label.</param>
 /// <param name="prfSeed">The 64-byte PRF seed.</param>
 /// <returns>A 48-byte output of the TLS pseudo-random function.</returns>
 /// <exception cref="ArgumentException"><paramref name="otherPartyPublicKey"/> is over a different curve than this key</exception>
 /// <exception cref="ArgumentNullException"><paramref name="prfLabel"/> is null</exception>
 /// <exception cref="ArgumentNullException"><paramref name="prfSeed"/> is null</exception>
 /// <exception cref="CryptographicException"><paramref name="prfSeed"/> is not exactly 64 bytes in length</exception>
 public virtual byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
 {
     throw DerivedClassMustOverride();
 }
示例#46
0
 /// <summary>
 /// Derive key material using the formula HASH(x) where x is the computed result of the EC Diffie-Hellman algorithm.
 /// </summary>
 /// <param name="otherPartyPublicKey">The public key of the party with which to derive a mutual secret.</param>
 /// <param name="hashAlgorithm">The identifier for the hash algorithm to use.</param>
 /// <returns>A hashed output suitable for key material</returns>
 /// <exception cref="ArgumentException"><paramref name="otherPartyPublicKey"/> is over a different curve than this key</exception>
 public byte[] DeriveKeyFromHash(ECDiffieHellmanPublicKey otherPartyPublicKey, HashAlgorithmName hashAlgorithm)
 {
     return(DeriveKeyFromHash(otherPartyPublicKey, hashAlgorithm, null, null));
 }
示例#47
0
 // This method must be implemented by derived classes. In order to conform to the contract, it cannot be abstract.
 public virtual byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey)
 {
     throw DerivedClassMustOverride();
 }
示例#48
0
 public override byte[] DeriveKeyFromHash(
     ECDiffieHellmanPublicKey otherPartyPublicKey,
     HashAlgorithmName hashAlgorithm,
     byte[]?secretPrepend,
     byte[]?secretAppend) =>
 _wrapped.DeriveKeyFromHash(Unwrap(otherPartyPublicKey), hashAlgorithm, secretPrepend, secretAppend);
 /// <summary>
 /// Encrypts the provided data.
 /// </summary>
 /// <param name="privateKey">The private key used for encryption.</param>
 /// <param name="publicKey">The public key used for encryption.</param>
 /// <param name="nonce">The nonce used for encryption.</param>
 /// <param name="data">The data to encrypt.</param>
 /// <returns>The encrypted data.</returns>
 public static byte[] Encrypt(ECDiffieHellmanCng privateKey, ECDiffieHellmanPublicKey publicKey, byte[] nonce, byte[] data)
 {
     Aes aes = DeriveKeyAndIv(privateKey, publicKey, nonce);
     return aes.CreateEncryptor().TransformFinalBlock(data, 0, data.Length);
 }
示例#50
0
 public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed) =>
 _wrapped.DeriveKeyTls(Unwrap(otherPartyPublicKey), prfLabel, prfSeed);
示例#51
0
 public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey)
 {
     return(default(byte[]));
 }
示例#52
0
 /// <summary>
 /// Given a second party's public key, derive shared key material
 /// </summary>
 public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey) =>
 DeriveKeyFromHash(otherPartyPublicKey, HashAlgorithmName.SHA256, null, null);
示例#53
0
        public Microsoft.Win32.SafeHandles.SafeNCryptSecretHandle DeriveSecretAgreementHandle(ECDiffieHellmanPublicKey otherPartyPublicKey)
        {
            Contract.Ensures(this.Key.Handle != null);

            return(default(Microsoft.Win32.SafeHandles.SafeNCryptSecretHandle));
        }
示例#54
0
        /// <summary>
        /// Get the secret agreement generated between two parties
        /// </summary>
        private byte[]? DeriveSecretAgreement(ECDiffieHellmanPublicKey otherPartyPublicKey, IncrementalHash?hasher)
        {
            Debug.Assert(otherPartyPublicKey != null);

            // Ensure that this ECDH object contains a private key by attempting a parameter export
            // which will throw an OpenSslCryptoException if no private key is available
            ECParameters thisKeyExplicit             = ExportExplicitParameters(true);
            bool         thisIsNamed                 = Interop.Crypto.EcKeyHasCurveName(_key.Value);
            ECDiffieHellmanOpenSslPublicKey?otherKey = otherPartyPublicKey as ECDiffieHellmanOpenSslPublicKey;
            bool disposeOtherKey = false;

            if (otherKey == null)
            {
                disposeOtherKey = true;

                ECParameters otherParameters =
                    thisIsNamed
                        ? otherPartyPublicKey.ExportParameters()
                        : otherPartyPublicKey.ExportExplicitParameters();

                otherKey = new ECDiffieHellmanOpenSslPublicKey(otherParameters);
            }

            bool otherIsNamed = otherKey.HasCurveName;

            SafeEvpPKeyHandle?ourKey   = null;
            SafeEvpPKeyHandle?theirKey = null;

            byte[]? rented = null;
            int secretLength = 0;

            try
            {
                if (otherKey.KeySize != KeySize)
                {
                    throw new ArgumentException(SR.Cryptography_ArgECDHKeySizeMismatch, nameof(otherPartyPublicKey));
                }

                if (otherIsNamed == thisIsNamed)
                {
                    ourKey   = _key.UpRefKeyHandle();
                    theirKey = otherKey.DuplicateKeyHandle();
                }
                else if (otherIsNamed)
                {
                    ourKey = _key.UpRefKeyHandle();

                    using (ECOpenSsl tmp = new ECOpenSsl(otherKey.ExportExplicitParameters()))
                    {
                        theirKey = tmp.UpRefKeyHandle();
                    }
                }
                else
                {
                    using (ECOpenSsl tmp = new ECOpenSsl(thisKeyExplicit))
                    {
                        ourKey = tmp.UpRefKeyHandle();
                    }

                    theirKey = otherKey.DuplicateKeyHandle();
                }

                using (SafeEvpPKeyCtxHandle ctx = Interop.Crypto.EvpPKeyCtxCreate(ourKey, theirKey, out uint secretLengthU))
                {
                    if (ctx == null || ctx.IsInvalid || secretLengthU == 0 || secretLengthU > int.MaxValue)
                    {
                        throw Interop.Crypto.CreateOpenSslCryptographicException();
                    }

                    secretLength = (int)secretLengthU;

                    // Indicate that secret can hold stackallocs from nested scopes
                    Span <byte> secret = stackalloc byte[0];

                    // Arbitrary limit. But it covers secp521r1, which is the biggest common case.
                    const int StackAllocMax = 66;

                    if (secretLength > StackAllocMax)
                    {
                        rented = CryptoPool.Rent(secretLength);
                        secret = new Span <byte>(rented, 0, secretLength);
                    }
                    else
                    {
                        secret = stackalloc byte[secretLength];
                    }

                    Interop.Crypto.EvpPKeyDeriveSecretAgreement(ctx, secret);

                    if (hasher == null)
                    {
                        return(secret.ToArray());
                    }
                    else
                    {
                        hasher.AppendData(secret);
                        return(null);
                    }
                }
            }
            finally
            {
                theirKey?.Dispose();
                ourKey?.Dispose();

                if (disposeOtherKey)
                {
                    otherKey.Dispose();
                }

                if (rented != null)
                {
                    CryptoPool.Return(rented, secretLength);
                }
            }
        }
        public override void ProcessClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePrivateKey privateKey, byte[] data)
        {
            if (data[0] != data.Length-1) {
                throw new Exception("Incorrect ECPoint length");
            }

            // Exctract the ECPoint
            byte[] ecPoint = new byte[data.Length-1];
            Buffer.BlockCopy(data, 1, ecPoint, 0, ecPoint.Length);

            // Create key blob and public key
            byte[] keyBlob = Point2Blob(ecPoint);
            _publicKey = ECDiffieHellmanCngPublicKey.FromByteArray(keyBlob, CngKeyBlobFormat.EccPublicBlob);
        }