public static byte[] SignECDsa(byte[] message, byte[] prikey, byte[] pubkey, ECDsaCurve curve)
        {
            NetCrypto.ECCurve usedCurve = NetCrypto.ECCurve.NamedCurves.nistP256;
            switch (curve)
            {
            case ECDsaCurve.Secp256r1:
                // default
                break;

            case ECDsaCurve.Secp256k1:
                var oid = NetCrypto.Oid.FromFriendlyName("secP256k1", NetCrypto.OidGroup.PublicKeyAlgorithm);
                usedCurve = NetCrypto.ECCurve.CreateFromOid(oid);
                break;
            }
            ;

            using (var ecdsa = NetCrypto.ECDsa.Create(new NetCrypto.ECParameters
            {
                Curve = usedCurve,
                D = prikey,
                Q = ECPointDecode(pubkey, curve)
            }))
            {
                return(ecdsa.SignData(message, NetCrypto.HashAlgorithmName.SHA256));
            }
        }
        public static bool VerifySignatureECDsa(byte[] message, byte[] signature, byte[] pubkey, ECDsaCurve curve)
        {
            NetCrypto.ECCurve usedCurve = NetCrypto.ECCurve.NamedCurves.nistP256;
            switch (curve)
            {
            case ECDsaCurve.Secp256r1:
                // default
                break;

            case ECDsaCurve.Secp256k1:
                var oid = NetCrypto.Oid.FromFriendlyName("secP256k1", NetCrypto.OidGroup.PublicKeyAlgorithm);
                usedCurve = NetCrypto.ECCurve.CreateFromOid(oid);
                break;
            }
            ;
#if NET461
            const int ECDSA_PUBLIC_P256_MAGIC = 0x31534345;
            pubkey = BitConverter.GetBytes(ECDSA_PUBLIC_P256_MAGIC).Concat(BitConverter.GetBytes(32)).Concat(pubkey).ToArray();
            using (CngKey key = CngKey.Import(pubkey, CngKeyBlobFormat.EccPublicBlob))
                using (ECDsaCng ecdsa = new ECDsaCng(key))
                {
                    return(ecdsa.VerifyData(message, signature, HashAlgorithmName.SHA256));
                }
#else
            using (var ecdsa = NetCrypto.ECDsa.Create(new NetCrypto.ECParameters
            {
                Curve = usedCurve,
                Q = ECPointDecode(pubkey, curve)
            }))
            {
                return(ecdsa.VerifyData(message, signature, NetCrypto.HashAlgorithmName.SHA256));
            }
#endif
        }
Example #3
0
            /// <summary>
            /// Create an ECDsaCng algorithm with a named curve.
            /// </summary>
            /// <param name="curve">The <see cref="ECCurve"/> representing the curve.</param>
            /// <exception cref="ArgumentNullException">if <paramref name="curve" /> is null.</exception>
            /// <exception cref="PlatformNotSupportedException">if <paramref name="curve" /> does not contain an Oid with a FriendlyName.</exception>
            public ECDsaCng(ECCurve curve)
            {
                // FriendlyName is required; an attempt was already made to default it in ECCurve
                if (string.IsNullOrEmpty(curve.Oid.FriendlyName))
                    throw new PlatformNotSupportedException(string.Format(SR.Cryptography_InvalidCurveOid, curve.Oid.Value.ToString()));

                // Named curves generate the key immediately
                GenerateKey(curve);
            }
Example #4
0
 /// <summary>
 ///     Return a CngProperty representing a named curve.
 /// </summary>
 internal static CngProperty GetPropertyFromNamedCurve(ECCurve curve)
 {
     string curveName = curve.Oid.FriendlyName;
     unsafe
     {
         byte[] curveNameBytes = new byte[(curveName.Length + 1) * sizeof(char)]; // +1 to add trailing null
         System.Text.Encoding.Unicode.GetBytes(curveName, 0, curveName.Length, curveNameBytes, 0);
         return new CngProperty(KeyPropertyName.ECCCurveName, curveNameBytes, CngPropertyOptions.None);
     }
 }
Example #5
0
        public CngKey GetOrGenerateKey(ECCurve? curve)
        {
            if (_lazyKey != null)
            {
                return _lazyKey;
            }

            // We don't have a key yet so generate
            Debug.Assert(curve.HasValue);

            CngKeyCreationParameters creationParameters = new CngKeyCreationParameters()
            {
                ExportPolicy = CngExportPolicies.AllowPlaintextExport,
            };

            if (curve.Value.IsNamed)
            {
                creationParameters.Parameters.Add(CngKey.GetPropertyFromNamedCurve(curve.Value));
            }
            else if (curve.Value.IsPrime)
            {
                ECCurve eccurve = curve.Value;
                byte[] parametersBlob = ECCng.GetPrimeCurveParameterBlob(ref eccurve);
                CngProperty prop = new CngProperty(
                    Interop.BCrypt.BCryptPropertyStrings.BCRYPT_ECC_PARAMETERS,
                    parametersBlob,
                    CngPropertyOptions.None);
                creationParameters.Parameters.Add(prop);
            }
            else
            {
                throw new PlatformNotSupportedException(string.Format(SR.Cryptography_CurveNotSupported, curve.Value.CurveType.ToString()));
            }

            try
            {
                _lazyKey = CngKey.Create(CngAlgorithm.ECDsa, null, creationParameters);
            }
            catch (CryptographicException e)
            {
                // Map to PlatformNotSupportedException if appropriate
                ErrorCode errorCode = (ErrorCode)e.HResult;

                if (curve.Value.IsNamed &&
                    errorCode == ErrorCode.NTE_INVALID_PARAMETER || errorCode == ErrorCode.NTE_NOT_SUPPORTED)
                {
                    throw new PlatformNotSupportedException(string.Format(SR.Cryptography_CurveNotSupported, curve.Value.Oid.FriendlyName), e);
                }
                throw;
            }

            return _lazyKey;
        }
 internal static extern SafeEcKeyHandle EcKeyCreateByExplicitParameters(
     ECCurve.ECCurveType curveType,
     byte[] qx, int qxLength,
     byte[] qy, int qyLength,
     byte[] d, int dLength,
     byte[] p, int pLength,
     byte[] a, int aLength,
     byte[] b, int bLength,
     byte[] gx, int gxLength,
     byte[] gy, int gyLength,
     byte[] order, int nLength,
     byte[] cofactor, int cofactorLength,
     byte[] seed, int seedLength);
Example #7
0
        public override void GenerateKey(ECCurve curve)
        {
            curve.Validate();
            _core.DisposeKey();

            if (curve.IsNamed)
            {
                // Map curve name to algorithm to support pre-Win10 curves
                CngAlgorithm alg = CngKey.EcdsaCurveNameToAlgorithm(curve.Oid.FriendlyName);
                if (CngKey.IsECNamedCurve(alg.Algorithm))
                {
                    CngKey key = _core.GetOrGenerateKey(curve);
                    ForceSetKeySize(key.KeySize);
                }
                else {
                    int keySize = 0;
                    // Get the proper KeySize from algorithm name
                    if (alg == CngAlgorithm.ECDsaP256)
                        keySize = 256;
                    else if (alg == CngAlgorithm.ECDsaP384)
                        keySize = 384;
                    else if (alg == CngAlgorithm.ECDsaP521)
                        keySize = 521;
                    else
                    {
                        Debug.Fail(string.Format("Unknown algorithm {0}", alg.ToString()));
                        throw new ArgumentException(SR.Cryptography_InvalidKeySize);
                    }
                    CngKey key = _core.GetOrGenerateKey(keySize, alg);
                    ForceSetKeySize(keySize);
                }
            }
            else if (curve.IsExplicit)
            {
                CngKey key = _core.GetOrGenerateKey(curve);
                ForceSetKeySize(key.KeySize);
            }
            else
            {
                throw new PlatformNotSupportedException(string.Format(SR.Cryptography_CurveNotSupported, curve.CurveType.ToString()));
            }
        }
        internal static SafeEcKeyHandle EcKeyCreateByExplicitCurve(ECCurve curve)
        {
            byte[] p;
            if (curve.IsPrime)
            {
                p = curve.Prime;
            }
            else if (curve.IsCharacteristic2)
            {
                p = curve.Polynomial;
            }
            else
            {
                throw new PlatformNotSupportedException(string.Format(SR.Cryptography_CurveNotSupported, curve.CurveType.ToString()));
            }

            SafeEcKeyHandle key = Interop.Crypto.EcKeyCreateByExplicitParameters(
                curve.CurveType,
                null, 0,
                null, 0,
                null, 0,
                p, p.Length,
                curve.A, curve.A.Length,
                curve.B, curve.B.Length,
                curve.G.X, curve.G.X.Length,
                curve.G.Y, curve.G.Y.Length,
                curve.Order, curve.Order.Length,
                curve.Cofactor, curve.Cofactor.Length,
                curve.Seed, curve.Seed == null ? 0 : curve.Seed.Length);

            if (key == null || key.IsInvalid)
            {
                if (key != null)
                    key.Dispose();
                throw Interop.Crypto.CreateOpenSslCryptographicException();
            }

            return key;
        }
Example #9
0
 /// <summary>
 /// Creates an instance of the platform specific implementation of the cref="ECDsa" algorithm.
 /// </summary>
 /// <param name="curve">
 /// The <see cref="ECCurve"/> representing the elliptic curve.
 /// </param>
 public static ECDsa Create(ECCurve curve)
 {
     return new ECDsaImplementation.ECDsaCng(curve);
 }
Example #10
0
 public override void GenerateKey(ECCurve curve)
 {
     _key.GenerateKey(curve);
     ForceSetKeySize(_key.KeySize);
 }
Example #11
0
 /// <summary>
 /// Create a curve without having to make a copy of the Oid
 /// </summary>
 private static ECCurve Create(Oid oid)
 {
     ECCurve curve = new ECCurve();
     curve.CurveType = ECCurveType.Named;
     curve.Oid = oid;
     return curve;
 }
Example #12
0
 /// <summary>
 /// Create an ECDsaOpenSsl algorithm with a named curve.
 /// </summary>
 /// <param name="curve">The <see cref="ECCurve"/> representing the curve.</param>
 /// <exception cref="ArgumentNullException">if <paramref name="curve" /> is null.</exception>
 public ECDsaOpenSsl(ECCurve curve)
 {
     GenerateKey(curve);
 }
Example #13
0
 public ECDiffieHellmanCng(ECCurve curve)
 {
     // GenerateKey will already do all of the validation we need.
     GenerateKey(curve);
 }
Example #14
0
 /// <summary>
 /// Creates an instance of the platform specific implementation of the cref="ECDsa" algorithm.
 /// </summary>
 /// <param name="curve">
 /// The <see cref="ECCurve"/> representing the elliptic curve.
 /// </param>
 public static ECDsa Create(ECCurve curve)
 {
     return(new ECDsaImplementation.ECDsaCng(curve));
 }
Example #15
0
        internal static SafeNCryptKeyHandle GenerateNewExportableKey(string algorithm, ref ECCurve explicitCurve)
        {
            // Despite the function being create "persisted" key, since we pass a null name it's
            // actually ephemeral.
            SafeNCryptKeyHandle keyHandle;
            ErrorCode           errorCode = Interop.NCrypt.NCryptCreatePersistedKey(
                s_microsoftSoftwareProviderHandle,
                out keyHandle,
                algorithm,
                null,
                0,
                CngKeyCreationOptions.None);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            Debug.Assert(!keyHandle.IsInvalid);

            SetExportable(keyHandle);
            byte[] parametersBlob = ECCng.GetPrimeCurveParameterBlob(ref explicitCurve);
            SetProperty(keyHandle, KeyPropertyName.ECCParameters, parametersBlob);

            errorCode = Interop.NCrypt.NCryptFinalizeKey(keyHandle, 0);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            return(keyHandle);
        }
Example #16
0
 public ECDsaCng(ECCurve curve)
 {
     throw new NotImplementedException();
 }
Example #17
0
 public static ECDsa Create(ECCurve curve)
 {
     throw new NotImplementedException();
 }
Example #18
0
        internal static byte[] GetPrimeCurveParameterBlob(ref ECCurve curve)
        {
            byte[] blob;
            int    offset;
            int    blobSize;

            unsafe
            {
                // We need to build a key blob structured as follows:
                //     BCRYPT_ECC_PARAMETER_HEADER  header
                //     byte[cbFieldLength]          P
                //     byte[cbFieldLength]          A
                //     byte[cbFieldLength]          B
                //     byte[cbFieldLength]          G.X
                //     byte[cbFieldLength]          G.Y
                //     byte[cbSubgroupOrder]        Order (n)
                //     byte[cbCofactor]             Cofactor (h)
                //     byte[cbSeed]                 Seed

                blobSize = sizeof(BCRYPT_ECC_PARAMETER_HEADER) +
                           curve.Prime.Length +
                           curve.A.Length +
                           curve.B.Length +
                           curve.G.X.Length +
                           curve.G.Y.Length +
                           curve.Order.Length +
                           curve.Cofactor.Length +
                           (curve.Seed == null ? 0 : curve.Seed.Length);

                blob = new byte[blobSize];
                fixed(byte *pBlob = blob)
                {
                    // Build the header
                    BCRYPT_ECC_PARAMETER_HEADER *pBcryptBlob = (BCRYPT_ECC_PARAMETER_HEADER *)pBlob;

                    pBcryptBlob->Version              = Interop.BCrypt.BCRYPT_ECC_PARAMETER_HEADER_V1;
                    pBcryptBlob->cbCofactor           = curve.Cofactor.Length;
                    pBcryptBlob->cbFieldLength        = curve.A.Length; // P, A, B, X, Y have the same length
                    pBcryptBlob->cbSeed               = curve.Seed == null ? 0 : curve.Seed.Length;
                    pBcryptBlob->cbSubgroupOrder      = curve.Order.Length;
                    pBcryptBlob->CurveGenerationAlgId = ECCng.GetHashAlgorithmId(curve.Hash);
                    pBcryptBlob->CurveType            = ECCng.ConvertToCurveTypeEnum(curve.CurveType);
                }

                offset = sizeof(BCRYPT_ECC_PARAMETER_HEADER);
            }

            // Emit the blob
            Interop.BCrypt.Emit(blob, ref offset, curve.Prime);
            Interop.BCrypt.Emit(blob, ref offset, curve.A);
            Interop.BCrypt.Emit(blob, ref offset, curve.B);
            Interop.BCrypt.Emit(blob, ref offset, curve.G.X);
            Interop.BCrypt.Emit(blob, ref offset, curve.G.Y);
            Interop.BCrypt.Emit(blob, ref offset, curve.Order);
            Interop.BCrypt.Emit(blob, ref offset, curve.Cofactor);

            if (curve.Seed != null)
            {
                Interop.BCrypt.Emit(blob, ref offset, curve.Seed);
            }

            // We better have computed the right allocation size above!
            Debug.Assert(offset == blobSize, "offset == blobSize");

            return(blob);
        }
Example #19
0
        private static byte[] GetPrimeCurveBlob(
            ref ECParameters parameters,
            Func <bool, KeyBlobMagicNumber> magicResolver)
        {
            Debug.Assert(parameters.Curve.IsPrime);

            bool    includePrivateParameters = (parameters.D != null);
            ECCurve curve = parameters.Curve;

            byte[] blob;
            int    offset;
            int    blobSize;

            // We need to build a key blob structured as follows:
            //     BCRYPT_ECCFULLKEY_BLOB       header
            //     byte[cbFieldLength]          P
            //     byte[cbFieldLength]          A
            //     byte[cbFieldLength]          B
            //     byte[cbFieldLength]          G.X
            //     byte[cbFieldLength]          G.Y
            //     byte[cbSubgroupOrder]        Order (n)
            //     byte[cbCofactor]             Cofactor (h)
            //     byte[cbSeed]                 Seed
            //     byte[cbFieldLength]          Q.X
            //     byte[cbFieldLength]          Q.Y
            //     -- Only if "includePrivateParameters" is true --
            //     byte[cbSubgroupOrder]        D

            unsafe
            {
                blobSize = sizeof(BCRYPT_ECCFULLKEY_BLOB) +
                           curve.Prime.Length +
                           curve.A.Length +
                           curve.B.Length +
                           curve.G.X.Length +
                           curve.G.Y.Length +
                           curve.Order.Length +
                           curve.Cofactor.Length +
                           (curve.Seed == null ? 0 : curve.Seed.Length) +
                           parameters.Q.X.Length +
                           parameters.Q.Y.Length;

                if (includePrivateParameters)
                {
                    blobSize += parameters.D.Length;
                }

                blob = new byte[blobSize];

                fixed(byte *pBlob = blob)
                {
                    // Build the header
                    BCRYPT_ECCFULLKEY_BLOB *pBcryptBlob = (BCRYPT_ECCFULLKEY_BLOB *)pBlob;

                    pBcryptBlob->Version              = 1; // No constant for this found in bcrypt.h
                    pBcryptBlob->Magic                = magicResolver(includePrivateParameters);
                    pBcryptBlob->cbCofactor           = curve.Cofactor.Length;
                    pBcryptBlob->cbFieldLength        = parameters.Q.X.Length;
                    pBcryptBlob->cbSeed               = curve.Seed == null ? 0 : curve.Seed.Length;
                    pBcryptBlob->cbSubgroupOrder      = curve.Order.Length;
                    pBcryptBlob->CurveGenerationAlgId = GetHashAlgorithmId(curve.Hash);
                    pBcryptBlob->CurveType            = ConvertToCurveTypeEnum(curve.CurveType);
                }

                offset = sizeof(BCRYPT_ECCFULLKEY_BLOB);
            }

            // Emit the blob
            Interop.BCrypt.Emit(blob, ref offset, curve.Prime);
            Interop.BCrypt.Emit(blob, ref offset, curve.A);
            Interop.BCrypt.Emit(blob, ref offset, curve.B);
            Interop.BCrypt.Emit(blob, ref offset, curve.G.X);
            Interop.BCrypt.Emit(blob, ref offset, curve.G.Y);
            Interop.BCrypt.Emit(blob, ref offset, curve.Order);
            Interop.BCrypt.Emit(blob, ref offset, curve.Cofactor);
            if (curve.Seed != null)
            {
                Interop.BCrypt.Emit(blob, ref offset, curve.Seed);
            }
            Interop.BCrypt.Emit(blob, ref offset, parameters.Q.X);
            Interop.BCrypt.Emit(blob, ref offset, parameters.Q.Y);
            if (includePrivateParameters)
            {
                Interop.BCrypt.Emit(blob, ref offset, parameters.D);
            }

            // We better have computed the right allocation size above!
            Debug.Assert(offset == blobSize, "offset == blobSize");

            return(blob);
        }
Example #20
0
        internal static void ExportPrimeCurveParameters(
            ref ECParameters ecParams,
            byte[] ecBlob,
            bool includePrivateParameters)
        {
            // We now have a buffer laid out as follows:
            //     BCRYPT_ECCFULLKEY_BLOB       header
            //     byte[cbFieldLength]          P
            //     byte[cbFieldLength]          A
            //     byte[cbFieldLength]          B
            //     byte[cbFieldLength]          G.X
            //     byte[cbFieldLength]          G.Y
            //     byte[cbSubgroupOrder]        Order (n)
            //     byte[cbCofactor]             Cofactor (h)
            //     byte[cbSeed]                 Seed
            //     byte[cbFieldLength]          Q.X
            //     byte[cbFieldLength]          Q.Y
            //     -- Private only --
            //     byte[cbSubgroupOrder]        D

            KeyBlobMagicNumber magic = (KeyBlobMagicNumber)BitConverter.ToInt32(ecBlob, 0);

            // Check the magic value in the key blob header. If the blob does not have the required magic,
            // then throw a CryptographicException.
            CheckMagicValueOfKey(magic, includePrivateParameters);

            unsafe
            {
                // Fail-fast if a rogue provider gave us a blob that isn't even the size of the blob header.
                if (ecBlob.Length < sizeof(BCRYPT_ECCFULLKEY_BLOB))
                    throw ErrorCode.E_FAIL.ToCryptographicException();

                fixed(byte *pEcBlob = ecBlob)
                {
                    BCRYPT_ECCFULLKEY_BLOB *pBcryptBlob = (BCRYPT_ECCFULLKEY_BLOB *)pEcBlob;

                    var primeCurve = new ECCurve();

                    primeCurve.CurveType = ConvertToCurveTypeEnum(pBcryptBlob->CurveType);
                    primeCurve.Hash      = GetHashAlgorithmName(pBcryptBlob->CurveGenerationAlgId);

                    int offset = sizeof(BCRYPT_ECCFULLKEY_BLOB);

                    primeCurve.Prime = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength);
                    primeCurve.A     = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength);
                    primeCurve.B     = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength);
                    primeCurve.G     = new ECPoint()
                    {
                        X = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength),
                        Y = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength),
                    };
                    primeCurve.Order    = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbSubgroupOrder);
                    primeCurve.Cofactor = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbCofactor);

                    // Optional parameters
                    primeCurve.Seed = pBcryptBlob->cbSeed == 0 ?
                                      null :
                                      Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbSeed);

                    ecParams.Q = new ECPoint
                    {
                        X = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength),
                        Y = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength)
                    };

                    if (includePrivateParameters)
                    {
                        ecParams.D = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbSubgroupOrder);
                    }

                    ecParams.Curve = primeCurve;
                }
            }
        }
Example #21
0
 /// <summary>
 /// Create an ECDsaOpenSsl algorithm with a named curve.
 /// </summary>
 /// <param name="curve">The <see cref="ECCurve"/> representing the curve.</param>
 /// <exception cref="ArgumentNullException">if <paramref name="curve" /> is null.</exception>
 public ECDsaOpenSsl(ECCurve curve)
 {
     _key = new ECOpenSsl(curve);
     ForceSetKeySize(_key.KeySize);
 }
Example #22
0
        internal static CngKey Create(ECCurve curve, Func <string?, CngAlgorithm> algorithmResolver)
        {
            System.Diagnostics.Debug.Assert(algorithmResolver != null);

            curve.Validate();

            CngKeyCreationParameters creationParameters = new CngKeyCreationParameters
            {
                ExportPolicy = CngExportPolicies.AllowPlaintextExport,
            };

            CngAlgorithm alg;

            if (curve.IsNamed)
            {
                if (string.IsNullOrEmpty(curve.Oid.FriendlyName))
                {
                    throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_InvalidCurveOid, curve.Oid.Value));
                }

                // Map curve name to algorithm to support pre-Win10 curves
                alg = algorithmResolver(curve.Oid.FriendlyName);

                if (CngKey.IsECNamedCurve(alg.Algorithm))
                {
                    creationParameters.Parameters.Add(GetPropertyFromNamedCurve(curve));
                }
                else
                {
                    if (alg == CngAlgorithm.ECDsaP256 || alg == CngAlgorithm.ECDiffieHellmanP256 ||
                        alg == CngAlgorithm.ECDsaP384 || alg == CngAlgorithm.ECDiffieHellmanP384 ||
                        alg == CngAlgorithm.ECDsaP521 || alg == CngAlgorithm.ECDiffieHellmanP521)
                    {
                        // No parameters required, the algorithm ID has everything built-in.
                    }
                    else
                    {
                        Debug.Fail($"Unknown algorithm {alg}");
                        throw new ArgumentException(SR.Cryptography_InvalidKeySize);
                    }
                }
            }
            else if (curve.IsPrime)
            {
                byte[] parametersBlob = ECCng.GetPrimeCurveParameterBlob(ref curve);

                CngProperty prop = new CngProperty(
                    KeyPropertyName.ECCParameters,
                    parametersBlob,
                    CngPropertyOptions.None);

                creationParameters.Parameters.Add(prop);
                alg = algorithmResolver(null);
            }
            else
            {
                throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_CurveNotSupported, curve.CurveType.ToString()));
            }

            try
            {
                return(Create(alg, null, creationParameters));
            }
            catch (CryptographicException e)
            {
                Interop.NCrypt.ErrorCode errorCode = (Interop.NCrypt.ErrorCode)e.HResult;

                if (errorCode == Interop.NCrypt.ErrorCode.NTE_INVALID_PARAMETER ||
                    errorCode == Interop.NCrypt.ErrorCode.NTE_NOT_SUPPORTED)
                {
                    string?target = curve.IsNamed ? curve.Oid.FriendlyName : curve.CurveType.ToString();
                    throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_CurveNotSupported, target), e);
                }

                throw;
            }
        }
Example #23
0
        internal static void ReadPkcs8Blob(this DerSequenceReader reader, ref ECParameters parameters)
        {
            // OneAsymmetricKey ::= SEQUENCE {
            //   version                   Version,
            //   privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
            //   privateKey                PrivateKey,
            //   attributes            [0] Attributes OPTIONAL,
            //   ...,
            //   [[2: publicKey        [1] PublicKey OPTIONAL ]],
            //   ...
            // }
            //
            // PrivateKeyInfo ::= OneAsymmetricKey
            //
            // PrivateKey ::= OCTET STRING

            int version = reader.ReadInteger();

            // We understand both version 0 and 1 formats,
            // which are now known as v1 and v2, respectively.
            if (version > 1)
            {
                throw new CryptographicException();
            }

            {
                // Ensure we're reading EC Public Key (well, Private, but the OID says Public)
                DerSequenceReader algorithm = reader.ReadSequence();

                string algorithmOid = algorithm.ReadOidAsString();

                if (algorithmOid != s_idEcPublicKey.Value)
                {
                    throw new CryptographicException();
                }
            }

            byte[] privateKeyBlob = reader.ReadOctetString();

            // ECPrivateKey{CURVES:IOSet} ::= SEQUENCE {
            //   version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
            //   privateKey OCTET STRING,
            //   parameters [0] Parameters{{IOSet}} OPTIONAL,
            //   publicKey  [1] BIT STRING OPTIONAL
            // }
            DerSequenceReader keyReader = new DerSequenceReader(privateKeyBlob);

            version = keyReader.ReadInteger();

            // We understand the version 1 format
            if (version > 1)
            {
                throw new CryptographicException();
            }

            parameters.D = keyReader.ReadOctetString();

            // Check for context specific 0
            const byte ConstructedContextSpecific =
                DerSequenceReader.ContextSpecificTagFlag | DerSequenceReader.ConstructedFlag;

            const byte ConstructedContextSpecific0 = (ConstructedContextSpecific | 0);
            const byte ConstructedContextSpecific1 = (ConstructedContextSpecific | 1);

            if (keyReader.PeekTag() != ConstructedContextSpecific0)
            {
                throw new CryptographicException();
            }

            // Parameters ::= CHOICE {
            //   ecParameters ECParameters,
            //   namedCurve CURVES.&id({ CurveNames}),
            //   implicitlyCA  NULL
            // }
            DerSequenceReader parametersReader = keyReader.ReadSequence();

            if (parametersReader.PeekTag() != (int)DerSequenceReader.DerTag.ObjectIdentifier)
            {
                throw new PlatformNotSupportedException(SR.Cryptography_ECC_NamedCurvesOnly);
            }

            parameters.Curve = ECCurve.CreateFromValue(parametersReader.ReadOidAsString());

            // Check for context specific 1
            if (keyReader.PeekTag() != ConstructedContextSpecific1)
            {
                throw new CryptographicException();
            }

            keyReader = keyReader.ReadSequence();
            byte[] encodedPoint = keyReader.ReadBitString();
            ReadEncodedPoint(encodedPoint, ref parameters);

            // We don't care about the rest of the blob here, but it's expected to not exist.
        }
Example #24
0
 public virtual void GenerateKey(ECCurve curve)
 {
     throw new NotImplementedException();
 }
Example #25
0
 public override void GenerateKey(ECCurve curve)
 {
     throw new NotImplementedException();
 }
Example #26
0
 public ECDsaCng(ECCurve curve) {
     throw new NotImplementedException ();
 }
Example #27
0
 private static ECCurve CreateFromValueAndName(string oidValue, string oidFriendlyName)
 {
     return(ECCurve.Create(new Oid(oidValue, oidFriendlyName)));
 }
Example #28
0
 public static ECDsa Create (ECCurve curve)
 {
     throw new NotImplementedException ();
 }
Example #29
0
 public static partial ECDsa Create(ECCurve curve);
Example #30
0
            public override void GenerateKey(ECCurve curve)
            {
                curve.Validate();
                FreeKey();

                if (curve.IsNamed)
                {
                    string oid = null;
                    // Use oid Value first if present, otherwise FriendlyName because Oid maintains a hard-coded
                    // cache that may have different casing for FriendlyNames than OpenSsl
                    oid = !string.IsNullOrEmpty(curve.Oid.Value) ? curve.Oid.Value : curve.Oid.FriendlyName;

                    SafeEcKeyHandle key = Interop.Crypto.EcKeyCreateByOid(oid);

                    if (key == null || key.IsInvalid)
                        throw new PlatformNotSupportedException(string.Format(SR.Cryptography_CurveNotSupported, oid));

                    if (!Interop.Crypto.EcKeyGenerateKey(key))
                        throw Interop.Crypto.CreateOpenSslCryptographicException();

                    SetKey(key);
                }
                else if (curve.IsExplicit)
                {
                    SafeEcKeyHandle key = Interop.Crypto.EcKeyCreateByExplicitCurve(curve);

                    if (!Interop.Crypto.EcKeyGenerateKey(key))
                        throw Interop.Crypto.CreateOpenSslCryptographicException();

                    SetKey(key);
                }
                else
                {
                    throw new PlatformNotSupportedException(string.Format(SR.Cryptography_CurveNotSupported, curve.CurveType.ToString()));
                }
            }
Example #31
0
            public override void GenerateKey(ECCurve curve)
            {
                curve.Validate();

                if (_keyHandle != null)
                {
                    DisposeKey();
                }

                string algorithm = null;
                int    keySize   = 0;

                if (curve.IsNamed)
                {
                    // Map curve name to algorithm to support pre-Win10 curves
                    algorithm = ECCng.EcdsaCurveNameToAlgorithm(curve.Oid.FriendlyName);
                    if (IsECNamedCurve(algorithm))
                    {
                        try
                        {
                            _keyHandle = CngKeyLite.GenerateNewExportableKey(algorithm, curve.Oid.FriendlyName);
                            keySize    = CngKeyLite.GetKeyLength(_keyHandle);
                        }
                        catch (CryptographicException e)
                        {
                            // Map to PlatformNotSupportedException if appropriate
                            ErrorCode errorCode = (ErrorCode)e.HResult;

                            if (curve.IsNamed &&
                                errorCode == ErrorCode.NTE_INVALID_PARAMETER || errorCode == ErrorCode.NTE_NOT_SUPPORTED)
                            {
                                throw new PlatformNotSupportedException(string.Format(SR.Cryptography_CurveNotSupported, curve.Oid.FriendlyName), e);
                            }
                            throw;
                        }
                    }
                    else
                    {
                        // Get the proper KeySize from algorithm name
                        if (algorithm == AlgorithmName.ECDsaP256)
                        {
                            keySize = 256;
                        }
                        else if (algorithm == AlgorithmName.ECDsaP384)
                        {
                            keySize = 384;
                        }
                        else if (algorithm == AlgorithmName.ECDsaP521)
                        {
                            keySize = 521;
                        }
                        else
                        {
                            Debug.Fail(string.Format("Unknown algorithm {0}", algorithm.ToString()));
                            throw new ArgumentException(SR.Cryptography_InvalidKeySize);
                        }
                        _keyHandle = CngKeyLite.GenerateNewExportableKey(algorithm, keySize);
                    }
                }
                else if (curve.IsExplicit)
                {
                    algorithm  = AlgorithmName.ECDsa;
                    _keyHandle = CngKeyLite.GenerateNewExportableKey(algorithm, ref curve);
                    keySize    = CngKeyLite.GetKeyLength(_keyHandle);
                }
                else
                {
                    throw new PlatformNotSupportedException(string.Format(SR.Cryptography_CurveNotSupported, curve.CurveType.ToString()));
                }

                _lastAlgorithm = algorithm;
                _lastKeySize   = keySize;
                ForceSetKeySize(keySize);
            }
Example #32
0
 /// <summary>
 /// When overridden in a derived class, generates a new public/private keypair for the specified curve.
 /// </summary>
 /// <param name="curve">The curve to use.</param>
 public virtual void GenerateKey(ECCurve curve)
 {
     throw new NotSupportedException(SR.NotSupported_SubclassOverride);
 }
 private static extern bool CryptoNative_GetECCurveParameters(
     SafeEcKeyHandle key,
     bool includePrivate,
     out ECCurve.ECCurveType curveType,
     out SafeBignumHandle qx, out int x_cb,
     out SafeBignumHandle qy, out int y_cb,
     out IntPtr d_bn_not_owned, out int d_cb,
     out SafeBignumHandle p, out int P_cb,
     out SafeBignumHandle a, out int A_cb,
     out SafeBignumHandle b, out int B_cb,
     out SafeBignumHandle gx, out int Gx_cb,
     out SafeBignumHandle gy, out int Gy_cb,
     out SafeBignumHandle order, out int order_cb,
     out SafeBignumHandle cofactor, out int cofactor_cb,
     out SafeBignumHandle seed, out int seed_cb);
Example #34
0
        internal static byte[] GetPrimeCurveParameterBlob(ref ECCurve curve)
        {
            unsafe
            {
                // We need to build a key blob structured as follows:
                //     BCRYPT_ECC_PARAMETER_HEADER  header
                //     byte[cbFieldLength]          P
                //     byte[cbFieldLength]          A
                //     byte[cbFieldLength]          B
                //     byte[cbFieldLength]          G.X
                //     byte[cbFieldLength]          G.Y
                //     byte[cbSubgroupOrder]        Order (n)
                //     byte[cbCofactor]             Cofactor (h)
                //     byte[cbSeed]                 Seed

                int blobSize = sizeof(BCRYPT_ECC_PARAMETER_HEADER) +
                    curve.Prime.Length +
                    curve.A.Length +
                    curve.B.Length +
                    curve.G.X.Length +
                    curve.G.Y.Length +
                    curve.Order.Length +
                    curve.Cofactor.Length +
                    (curve.Seed == null ? 0 : curve.Seed.Length);

                byte[] blob = new byte[blobSize];
                fixed (byte* pBlob = blob)
                {
                    // Build the header
                    BCRYPT_ECC_PARAMETER_HEADER* pBcryptBlob = (BCRYPT_ECC_PARAMETER_HEADER*)pBlob;
                    pBcryptBlob->Version = Interop.BCrypt.BCRYPT_ECC_PARAMETER_HEADER_V1;
                    pBcryptBlob->cbCofactor = curve.Cofactor.Length;
                    pBcryptBlob->cbFieldLength = curve.A.Length; // P, A, B, X, Y have the same length
                    pBcryptBlob->cbSeed = curve.Seed == null ? 0 : curve.Seed.Length;
                    pBcryptBlob->cbSubgroupOrder = curve.Order.Length;
                    pBcryptBlob->CurveGenerationAlgId = ECCng.GetHashAlgorithmId(curve.Hash);
                    pBcryptBlob->CurveType = ECCng.ConvertToCurveTypeEnum(curve.CurveType);

                    // Emit the blob
                    int offset = sizeof(BCRYPT_ECC_PARAMETER_HEADER);
                    Interop.BCrypt.Emit(blob, ref offset, curve.Prime);
                    Interop.BCrypt.Emit(blob, ref offset, curve.A);
                    Interop.BCrypt.Emit(blob, ref offset, curve.B);
                    Interop.BCrypt.Emit(blob, ref offset, curve.G.X);
                    Interop.BCrypt.Emit(blob, ref offset, curve.G.Y);
                    Interop.BCrypt.Emit(blob, ref offset, curve.Order);
                    Interop.BCrypt.Emit(blob, ref offset, curve.Cofactor);
                    if (curve.Seed != null)
                    {
                        Interop.BCrypt.Emit(blob, ref offset, curve.Seed);
                    }

                    // We better have computed the right allocation size above!
                    Debug.Assert(offset == blobSize, "offset == blobSize");
                }

                return blob;
            }
        }
Example #35
0
        private Lazy <SafeEcKeyHandle> _key = null !; // Always initialized

        public ECAndroid(ECCurve curve)
        {
            GenerateKey(curve);
        }
Example #36
0
 public override void GenerateKey(ECCurve curve)
 {
     KeySizeValue = _ecc.GenerateKey(curve);
 }
Example #37
0
            public override void GenerateKey(ECCurve curve)
            {
                curve.Validate();

                if (_keyHandle != null)
                {
                    DisposeKey();
                }

                string algorithm = null;
                int keySize = 0;

                if (curve.IsNamed)
                {
                    // Map curve name to algorithm to support pre-Win10 curves
                    algorithm = ECCng.EcdsaCurveNameToAlgorithm(curve.Oid.FriendlyName);
                    if (IsECNamedCurve(algorithm))
                    {
                        try
                        {
                            _keyHandle = CngKeyLite.GenerateNewExportableKey(algorithm, curve.Oid.FriendlyName);
                            keySize = CngKeyLite.GetKeyLength(_keyHandle);
                        }
                        catch (CryptographicException e)
                        {
                            // Map to PlatformNotSupportedException if appropriate
                            ErrorCode errorCode = (ErrorCode)e.HResult;

                            if (curve.IsNamed &&
                                errorCode == ErrorCode.NTE_INVALID_PARAMETER || errorCode == ErrorCode.NTE_NOT_SUPPORTED)
                            {
                                throw new PlatformNotSupportedException(string.Format(SR.Cryptography_CurveNotSupported, curve.Oid.FriendlyName), e);
                            }
                            throw;
                        }
                    }
                    else
                    {
                        // Get the proper KeySize from algorithm name
                        if (algorithm == AlgorithmName.ECDsaP256)
                            keySize = 256;
                        else if (algorithm == AlgorithmName.ECDsaP384)
                            keySize = 384;
                        else if (algorithm == AlgorithmName.ECDsaP521)
                            keySize = 521;
                        else
                        {
                            Debug.Fail(string.Format("Unknown algorithm {0}", algorithm.ToString()));
                            throw new ArgumentException(SR.Cryptography_InvalidKeySize);
                        }
                        _keyHandle = CngKeyLite.GenerateNewExportableKey(algorithm, keySize);
                    }
                }
                else if (curve.IsExplicit)
                {
                    algorithm = AlgorithmName.ECDsa;
                    _keyHandle = CngKeyLite.GenerateNewExportableKey(algorithm, ref curve);
                    keySize = CngKeyLite.GetKeyLength(_keyHandle);
                }
                else
                {
                    throw new PlatformNotSupportedException(string.Format(SR.Cryptography_CurveNotSupported, curve.CurveType.ToString()));
                }

                _lastAlgorithm = algorithm;
                _lastKeySize = keySize;
                ForceSetKeySize(keySize);
            }
Example #38
0
 /// <summary>
 /// Creates an instance of the platform specific implementation of the cref="ECDsa" algorithm.
 /// </summary>
 /// <param name="curve">
 /// The <see cref="ECCurve"/> representing the elliptic curve.
 /// </param>
 public static partial ECDsa Create(ECCurve curve)
 {
     return(new ECDsaImplementation.ECDsaAndroid(curve));
 }
Example #39
0
 public virtual void GenerateKey (ECCurve curve)
 {
     throw new NotImplementedException ();
 }
Example #40
0
 /// <summary>
 /// Create an ECDsaAndroid algorithm with a named curve.
 /// </summary>
 /// <param name="curve">The <see cref="ECCurve"/> representing the curve.</param>
 /// <exception cref="ArgumentNullException">if <paramref name="curve" /> is null.</exception>
 public ECDsaAndroid(ECCurve curve)
 {
     _key = new ECAndroid(curve);
     ForceSetKeySize(_key.KeySize);
 }
Example #41
0
 /// <summary>
 /// Create an ECDsaOpenSsl algorithm with a named curve.
 /// </summary>
 /// <param name="curve">The <see cref="ECCurve"/> representing the curve.</param>
 /// <exception cref="ArgumentNullException">if <paramref name="curve" /> is null.</exception>
 public ECDsaOpenSsl(ECCurve curve)
 {
     GenerateKey(curve);
 }
Example #42
0
 public static ECDsa Create(ECCurve curve)
 {
     throw new NotImplementedException("todo: add factory methods for portable scenarios");
 }
Example #43
0
        internal static void ExportPrimeCurveParameters(ref ECParameters ecParams, byte[] ecBlob, bool includePrivateParameters)
        {
            // We now have a buffer laid out as follows:
            //     BCRYPT_ECCFULLKEY_BLOB       header
            //     byte[cbFieldLength]          P
            //     byte[cbFieldLength]          A
            //     byte[cbFieldLength]          B
            //     byte[cbFieldLength]          G.X
            //     byte[cbFieldLength]          G.Y
            //     byte[cbSubgroupOrder]        Order (n)
            //     byte[cbCofactor]             Cofactor (h)
            //     byte[cbSeed]                 Seed
            //     byte[cbFieldLength]          Q.X
            //     byte[cbFieldLength]          Q.Y
            //     -- Private only --
            //     byte[cbSubgroupOrder]        D

            KeyBlobMagicNumber magic = (KeyBlobMagicNumber)BitConverter.ToInt32(ecBlob, 0);

            // Check the magic value in the key blob header. If the blob does not have the required magic,
            // then throw a CryptographicException.
            CheckMagicValueOfKey(magic, includePrivateParameters);

            unsafe
            {
                // Fail-fast if a rogue provider gave us a blob that isn't even the size of the blob header.
                if (ecBlob.Length < sizeof(BCRYPT_ECCFULLKEY_BLOB))
                    throw ErrorCode.E_FAIL.ToCryptographicException();

                fixed (byte* pEcBlob = ecBlob)
                {
                    BCRYPT_ECCFULLKEY_BLOB* pBcryptBlob = (BCRYPT_ECCFULLKEY_BLOB*)pEcBlob;

                    var primeCurve = new ECCurve();
                    primeCurve.CurveType = ConvertToCurveTypeEnum(pBcryptBlob->CurveType);
                    primeCurve.Hash = GetHashAlgorithmName(pBcryptBlob->CurveGenerationAlgId);

                    int offset = sizeof(BCRYPT_ECCFULLKEY_BLOB);

                    primeCurve.Prime = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength);
                    primeCurve.A = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength);
                    primeCurve.B = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength);
                    primeCurve.G = new ECPoint()
                    {
                        X = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength),
                        Y = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength),
                    };
                    primeCurve.Order = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbSubgroupOrder);
                    primeCurve.Cofactor = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbCofactor);

                    // Optional parameters
                    primeCurve.Seed = pBcryptBlob->cbSeed == 0 ? null : Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbSeed);

                    ecParams.Q = new ECPoint
                    {
                        X = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength),
                        Y = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength)
                    };

                    if (includePrivateParameters)
                    {
                        ecParams.D = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbSubgroupOrder);
                    }

                    ecParams.Curve = primeCurve;
                }
            }
        }
Example #44
0
 /// <summary>
 /// When overridden in a derived class, generates a new public/private keypair for the specified curve.
 /// </summary>
 /// <param name="curve">The curve to use.</param>
 public virtual void GenerateKey(ECCurve curve)
 {
     throw new NotSupportedException(SR.NotSupported_SubclassOverride);
 }
Example #45
0
 /// <summary>
 /// Helper method to map between BCrypt.ECC_CURVE_TYPE_ENUM and ECCurve.ECCurveType
 /// </summary>
 private static Interop.BCrypt.ECC_CURVE_TYPE_ENUM ConvertToCurveTypeEnum(ECCurve.ECCurveType value)
 {
     // Currently values 1-3 are interchangeable
     Debug.Assert(value == ECCurve.ECCurveType.Characteristic2 ||
         value == ECCurve.ECCurveType.PrimeShortWeierstrass ||
         value == ECCurve.ECCurveType.PrimeTwistedEdwards);
     return (Interop.BCrypt.ECC_CURVE_TYPE_ENUM)value;
 }
 public ECDiffieHellmanOpenSsl(ECCurve curve)
 {
     _key         = new ECOpenSsl(curve);
     KeySizeValue = _key.KeySize;
 }
 public override void GenerateKey(ECCurve curve)
 {
     ThrowIfDisposed();
     KeySizeValue = _key.GenerateKey(curve);
 }
Example #48
0
        internal static SafeNCryptKeyHandle GenerateNewExportableKey(string algorithm, ref ECCurve explicitCurve)
        {
            // Despite the function being create "persisted" key, since we pass a null name it's
            // actually ephemeral.
            SafeNCryptKeyHandle keyHandle;
            ErrorCode errorCode = Interop.NCrypt.NCryptCreatePersistedKey(
                s_microsoftSoftwareProviderHandle,
                out keyHandle,
                algorithm,
                null,
                0,
                CngKeyCreationOptions.None);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            Debug.Assert(!keyHandle.IsInvalid);

            SetExportable(keyHandle);
            byte[] parametersBlob = ECCng.GetPrimeCurveParameterBlob(ref explicitCurve);
            SetProperty(keyHandle, KeyPropertyName.ECCParameters, parametersBlob);

            errorCode = Interop.NCrypt.NCryptFinalizeKey(keyHandle, 0);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            return keyHandle;
        }