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 }
/// <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); }
/// <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); } }
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);
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; }
/// <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); }
public override void GenerateKey(ECCurve curve) { _key.GenerateKey(curve); ForceSetKeySize(_key.KeySize); }
/// <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; }
/// <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); }
public ECDiffieHellmanCng(ECCurve curve) { // GenerateKey will already do all of the validation we need. GenerateKey(curve); }
/// <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)); }
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); }
public ECDsaCng(ECCurve curve) { throw new NotImplementedException(); }
public static ECDsa Create(ECCurve curve) { throw new NotImplementedException(); }
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); }
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); }
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; } } }
/// <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); }
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; } }
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. }
public virtual void GenerateKey(ECCurve curve) { throw new NotImplementedException(); }
public override void GenerateKey(ECCurve curve) { throw new NotImplementedException(); }
public ECDsaCng(ECCurve curve) { throw new NotImplementedException (); }
private static ECCurve CreateFromValueAndName(string oidValue, string oidFriendlyName) { return(ECCurve.Create(new Oid(oidValue, oidFriendlyName))); }
public static ECDsa Create (ECCurve curve) { throw new NotImplementedException (); }
public static partial ECDsa Create(ECCurve curve);
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())); } }
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); }
/// <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);
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; } }
private Lazy <SafeEcKeyHandle> _key = null !; // Always initialized public ECAndroid(ECCurve curve) { GenerateKey(curve); }
public override void GenerateKey(ECCurve curve) { KeySizeValue = _ecc.GenerateKey(curve); }
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); }
/// <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)); }
public virtual void GenerateKey (ECCurve curve) { throw new NotImplementedException (); }
/// <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); }
public static ECDsa Create(ECCurve curve) { throw new NotImplementedException("todo: add factory methods for portable scenarios"); }
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; } } }
/// <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); }
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; }