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); }
private byte[] ExportKeyBlob(bool includePrivateParameters) { #if uap return(null); #else return(ECCng.ExportKeyBlob(Key, includePrivateParameters)); #endif // uap }
internal static void ExportExplicitParameters( CngKey key, bool includePrivateParameters, ref ECParameters ecparams) { byte[] blob = ExportFullKeyBlob(key, includePrivateParameters); ECCng.ExportPrimeCurveParameters(ref ecparams, blob, includePrivateParameters); }
internal static ECDiffieHellmanCngPublicKey FromKey(CngKey key) { CngKeyBlobFormat format; string? curveName; byte[] blob = ECCng.ExportKeyBlob(key, false, out format, out curveName); return(new ECDiffieHellmanCngPublicKey(blob, curveName, format)); }
/// <summary> /// Exports the key and explicit curve parameters used by the ECC object into an <see cref="ECParameters"/> object. /// </summary> /// <exception cref="CryptographicException"> /// if there was an issue obtaining the curve values. /// </exception> /// <exception cref="PlatformNotSupportedException"> /// if explicit export is not supported by this platform. Windows 10 or higher is required. /// </exception> /// <returns>The key and explicit curve parameters used by the ECC object.</returns> public override ECParameters ExportExplicitParameters(bool includePrivateParameters) { byte[] blob = ExportFullKeyBlob(includePrivateParameters); ECParameters ecparams = new ECParameters(); ECCng.ExportPrimeCurveParameters(ref ecparams, blob, includePrivateParameters); return(ecparams); }
private byte[] ExportFullKeyBlob(bool includePrivateParameters) { #if NETNATIVE return(null); #else return(ECCng.ExportFullKeyBlob(Key, includePrivateParameters)); #endif //NETNATIVE }
internal static unsafe byte[] GetPrimeCurveParameterBlob(ref ECCurve curve) { // 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[0]) { // 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); }
internal SafeNCryptKeyHandle GetDuplicatedKeyHandle(int callerKeySizeProperty) { ThrowIfDisposed(); if (ECCng.IsECNamedCurve(_lastAlgorithm)) { // Curve was previously created, so use that return(new DuplicateSafeNCryptKeyHandle(_keyHandle !)); } else { if (_lastKeySize != callerKeySizeProperty) { // Map the current key size to a CNG algorithm name string algorithm; bool isEcdsa = _algorithmGroup == BCryptNative.AlgorithmName.ECDsa; switch (callerKeySizeProperty) { case 256: algorithm = isEcdsa ? BCryptNative.AlgorithmName.ECDsaP256 : BCryptNative.AlgorithmName.ECDHP256; break; case 384: algorithm = isEcdsa ? BCryptNative.AlgorithmName.ECDsaP384 : BCryptNative.AlgorithmName.ECDHP384; break; case 521: algorithm = isEcdsa ? BCryptNative.AlgorithmName.ECDsaP521 : BCryptNative.AlgorithmName.ECDHP521; break; default: Debug.Fail("Should not have invalid key size"); throw new ArgumentException(SR.Cryptography_InvalidKeySize); } if (_keyHandle != null) { DisposeKey(); } _keyHandle = CngKeyLite.GenerateNewExportableKey(algorithm, callerKeySizeProperty); _lastKeySize = callerKeySizeProperty; _lastAlgorithm = algorithm; KeySize = callerKeySizeProperty; } return(new DuplicateSafeNCryptKeyHandle(_keyHandle !)); } }
/// <summary> /// Exports the key and explicit curve parameters used by the ECC object into an <see cref="ECParameters"/> object. /// </summary> /// <exception cref="CryptographicException"> /// if there was an issue obtaining the curve values. /// </exception> /// <exception cref="PlatformNotSupportedException"> /// if explicit export is not supported by this platform. Windows 10 or higher is required. /// </exception> /// <returns>The key and explicit curve parameters used by the ECC object.</returns> public override ECParameters ExportExplicitParameters() { using (CngKey key = Import()) { ECParameters ecparams = default; byte[] blob = ECCng.ExportFullKeyBlob(key, includePrivateParameters: false); ECCng.ExportPrimeCurveParameters(ref ecparams, blob, includePrivateParameters: false); return(ecparams); } }
public CngKey GetOrGenerateKey(ECCurve?curve) { ThrowIfDisposed(); 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(SR.Format(SR.Cryptography_CurveNotSupported, curve.Value.CurveType.ToString())); } try { _lazyKey = CngKey.Create(DefaultKeyType ?? 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(SR.Format(SR.Cryptography_CurveNotSupported, curve.Value.Oid.FriendlyName), e); } throw; } return(_lazyKey); }
internal static CngKey Import(byte[] keyBlob, string curveName, CngKeyBlobFormat format, CngProvider provider) { Contract.Ensures(Contract.Result <CngKey>() != null); if (keyBlob == null) { throw new ArgumentNullException("keyBlob"); } if (format == null) { throw new ArgumentNullException("format"); } if (provider == null) { throw new ArgumentNullException("provider"); } // Make sure that NCrypt is supported on this platform if (!NCryptNative.NCryptSupported) { throw new PlatformNotSupportedException(SR.GetString(SR.Cryptography_PlatformNotSupported)); } // If we don't know for sure that the key will be ephemeral, then we need to demand Import // permission. Since we won't know the name of the key until it's too late, we demand a full Import // rather than one scoped to the key. bool safeKeyImport = format == CngKeyBlobFormat.EccPublicBlob || format == CngKeyBlobFormat.EccFullPublicBlob || format == CngKeyBlobFormat.GenericPublicBlob; if (!safeKeyImport) { new KeyContainerPermission(KeyContainerPermissionFlags.Import).Demand(); } // Import the key into the KSP SafeNCryptProviderHandle kspHandle = NCryptNative.OpenStorageProvider(provider.Provider); SafeNCryptKeyHandle keyHandle; if (curveName == null) { keyHandle = NCryptNative.ImportKey(kspHandle, keyBlob, format.Format); } else { keyHandle = ECCng.ImportKeyBlob(format.Format, keyBlob, curveName, kspHandle); } // Prepare the key for use CngKey key = new CngKey(kspHandle, keyHandle); // We can't tell directly if an OpaqueTransport blob imported as an ephemeral key or not key.IsEphemeral = format != CngKeyBlobFormat.OpaqueTransportBlob; return(key); }
internal static ECDiffieHellmanCngPublicKey FromKey(CngKey key) { Contract.Requires(key != null && key.AlgorithmGroup == CngAlgorithmGroup.ECDiffieHellman); Contract.Ensures(Contract.Result <ECDiffieHellmanCngPublicKey>() != null); CngKeyBlobFormat format; string curveName; byte[] blob = ECCng.ExportKeyBlob(key, false, out format, out curveName); return(new ECDiffieHellmanCngPublicKey(blob, curveName, format)); }
internal static CngKey Import( ReadOnlySpan <byte> keyBlob, string?curveName, CngKeyBlobFormat format, CngProvider provider) { ArgumentNullException.ThrowIfNull(format); ArgumentNullException.ThrowIfNull(provider); SafeNCryptProviderHandle providerHandle = provider.OpenStorageProvider(); SafeNCryptKeyHandle? keyHandle = null; try { ErrorCode errorCode; if (curveName == null) { errorCode = Interop.NCrypt.NCryptImportKey( providerHandle, IntPtr.Zero, format.Format, IntPtr.Zero, out keyHandle, ref MemoryMarshal.GetReference(keyBlob), keyBlob.Length, 0); if (errorCode != ErrorCode.ERROR_SUCCESS) { providerHandle.Dispose(); keyHandle.Dispose(); throw errorCode.ToCryptographicException(); } } else { keyHandle = ECCng.ImportKeyBlob(format.Format, keyBlob, curveName, providerHandle); } CngKey key = new CngKey(providerHandle, keyHandle); // We can't tell directly if an OpaqueTransport blob imported as an ephemeral key or not key.IsEphemeral = format != CngKeyBlobFormat.OpaqueTransportBlob; return(key); } catch { keyHandle?.Dispose(); providerHandle.Dispose(); throw; } }
internal static SafeNCryptKeyHandle ImportKeyBlob(string blobType, byte[] keyBlob, string curveName) { SafeNCryptKeyHandle keyHandle; keyHandle = ECCng.ImportKeyBlob(blobType, keyBlob, curveName, s_microsoftSoftwareProviderHandle); Debug.Assert(keyHandle != null); SetExportable(keyHandle); return(keyHandle); }
/// <summary> /// Exports the key and explicit curve parameters used by the ECC object into an <see cref="ECParameters"/> object. /// </summary> /// <exception cref="CryptographicException"> /// if there was an issue obtaining the curve values. /// </exception> /// <exception cref="PlatformNotSupportedException"> /// if explicit export is not supported by this platform. Windows 10 or higher is required. /// </exception> /// <returns>The key and explicit curve parameters used by the ECC object.</returns> public override ECParameters ExportExplicitParameters() { if (_keyBlob == null) { throw new ObjectDisposedException(nameof(ECDiffieHellmanPublicKey)); } ECParameters ecparams = new ECParameters(); ECCng.ExportPrimeCurveParameters(ref ecparams, _keyBlob, includePrivateParameters: false); return(ecparams); }
private void ImportKeyBlob(byte[] ecKeyBlob, string curveName, bool includePrivateParameters) { string blobType = includePrivateParameters ? Interop.BCrypt.KeyBlobType.BCRYPT_ECCPRIVATE_BLOB : Interop.BCrypt.KeyBlobType.BCRYPT_ECCPUBLIC_BLOB; SafeNCryptKeyHandle keyHandle = CngKeyLite.ImportKeyBlob(blobType, ecKeyBlob, curveName); Debug.Assert(!keyHandle.IsInvalid); _key.SetHandle(keyHandle, ECCng.EcdhCurveNameToAlgorithm(curveName)); ForceSetKeySize(_key.KeySize); }
/// <summary> /// Exports the key used by the ECC object into an <see cref="ECParameters"/> object. /// If the key was created as a named curve, the Curve property will contain named curve parameters /// otherwise it will contain explicit parameters. /// </summary> /// <exception cref="CryptographicException"> /// if there was an issue obtaining the curve values. /// </exception> /// <returns>The key and named curve parameters used by the ECC object.</returns> public override ECParameters ExportParameters() { if (string.IsNullOrEmpty(_curveName)) { return(ExportExplicitParameters()); } else { ECParameters ecparams = new ECParameters(); ECCng.ExportNamedCurveParameters(ref ecparams, _keyBlob, includePrivateParameters: false); ecparams.Curve = ECCurve.CreateFromFriendlyName(_curveName); return(ecparams); } }
private void ImportFullKeyBlob(byte[] ecfullKeyBlob, bool includePrivateParameters) { CngKey newKey = ECCng.ImportFullKeyBlob(ecfullKeyBlob, includePrivateParameters); try { Key = newKey; } catch { newKey.Dispose(); throw; } }
private void ImportKeyBlob(byte[] ecfullKeyBlob, string curveName, bool includePrivateParameters) { CngKey key = ECCng.ImportKeyBlob(ecfullKeyBlob, curveName, includePrivateParameters); try { Key = key; } catch { key.Dispose(); throw; } }
public override ECParameters ExportExplicitParameters(bool includePrivateParameters) { byte[] blob = ExportFullKeyBlob(includePrivateParameters); try { ECParameters ecparams = new ECParameters(); ECCng.ExportPrimeCurveParameters(ref ecparams, blob, includePrivateParameters); return(ecparams); } finally { Array.Clear(blob, 0, blob.Length); } }
internal string GetCurveName(int callerKeySizeProperty) { // Ensure key\handle is created using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle(callerKeySizeProperty)) { string algorithm = _lastAlgorithm; if (ECCng.IsECNamedCurve(algorithm)) { return(CngKeyLite.GetCurveName(keyHandle)); } // Use hard-coded values (for use with pre-Win10 APIs) return(ECCng.SpecialNistAlgorithmToCurveName(algorithm)); } }
private void ImportKeyBlob(byte[] ecKeyBlob, string curveName, bool includePrivateParameters) { string blobType = includePrivateParameters ? Interop.BCrypt.KeyBlobType.BCRYPT_ECCPRIVATE_BLOB : Interop.BCrypt.KeyBlobType.BCRYPT_ECCPUBLIC_BLOB; SafeNCryptKeyHandle keyHandle = CngKeyLite.ImportKeyBlob(blobType, ecKeyBlob, curveName); Debug.Assert(!keyHandle.IsInvalid); _keyHandle = keyHandle; _lastAlgorithm = ECCng.EcdsaCurveNameToAlgorithm(curveName); int newKeySize = CngKeyLite.GetKeyLength(keyHandle); ForceSetKeySize(newKeySize); _lastKeySize = newKeySize; }
/// <summary> /// Exports the key used by the ECC object into an <see cref="ECParameters"/> object. /// If the key was created as a named curve, the Curve property will contain named curve parameters /// otherwise it will contain explicit parameters. /// </summary> /// <exception cref="CryptographicException"> /// if there was an issue obtaining the curve values. /// </exception> /// <returns>The key and named curve parameters used by the ECC object.</returns> public override ECParameters ExportParameters() { if (_keyBlob == null) { throw new ObjectDisposedException(nameof(ECDiffieHellmanPublicKey)); } if (string.IsNullOrEmpty(_curveName)) { return(ExportExplicitParameters()); } else { ECParameters ecparams = new ECParameters(); ECCng.ExportNamedCurveParameters(ref ecparams, _keyBlob, includePrivateParameters: false); ecparams.Curve = ECCurve.CreateFromFriendlyName(_curveName); return(ecparams); } }
internal static void ExportParameters( CngKey key, bool includePrivateParameters, ref ECParameters ecparams) { string curveName = key.GetCurveName(); if (string.IsNullOrEmpty(curveName)) { byte[] fullKeyBlob = ECCng.ExportFullKeyBlob(key, includePrivateParameters); ECCng.ExportPrimeCurveParameters(ref ecparams, fullKeyBlob, includePrivateParameters); } else { byte[] keyBlob = ECCng.ExportKeyBlob(key, includePrivateParameters); ECCng.ExportNamedCurveParameters(ref ecparams, keyBlob, includePrivateParameters); ecparams.Curve = ECCurve.CreateFromFriendlyName(curveName); } }
/// <summary> /// Exports the key used by the ECC object into an <see cref="ECParameters"/> object. /// If the curve has a name, the Curve property will contain named curve parameters otherwise it will contain explicit parameters. /// </summary> /// <exception cref="CryptographicException"> /// if there was an issue obtaining the curve values. /// </exception> /// <returns>The key and named curve parameters used by the ECC object.</returns> public override ECParameters ExportParameters(bool includePrivateParameters) { ECParameters ecparams = new ECParameters(); string curveName = GetCurveName(out string oidValue); if (string.IsNullOrEmpty(curveName)) { byte[] fullKeyBlob = ExportFullKeyBlob(includePrivateParameters); ECCng.ExportPrimeCurveParameters(ref ecparams, fullKeyBlob, includePrivateParameters); } else { byte[] keyBlob = ExportKeyBlob(includePrivateParameters); ECCng.ExportNamedCurveParameters(ref ecparams, keyBlob, includePrivateParameters); ecparams.Curve = ECCurve.CreateFromOid(new Oid(oidValue, curveName)); } return(ecparams); }
internal static CngKey Import(byte[] keyBlob, string curveName, CngKeyBlobFormat format, CngProvider provider) { if (keyBlob == null) { throw new ArgumentNullException(nameof(keyBlob)); } if (format == null) { throw new ArgumentNullException(nameof(format)); } if (provider == null) { throw new ArgumentNullException(nameof(provider)); } SafeNCryptProviderHandle providerHandle = provider.OpenStorageProvider(); SafeNCryptKeyHandle keyHandle = null; ErrorCode errorCode; if (curveName == null) { errorCode = Interop.NCrypt.NCryptImportKey(providerHandle, IntPtr.Zero, format.Format, IntPtr.Zero, out keyHandle, keyBlob, keyBlob.Length, 0); if (errorCode != ErrorCode.ERROR_SUCCESS) { throw errorCode.ToCryptographicException(); } } else { #if !uap keyHandle = ECCng.ImportKeyBlob(format.Format, keyBlob, curveName, providerHandle); #endif // !uap } CngKey key = new CngKey(providerHandle, keyHandle); // We can't tell directly if an OpaqueTransport blob imported as an ephemeral key or not key.IsEphemeral = format != CngKeyBlobFormat.OpaqueTransportBlob; return(key); }
public static ECDiffieHellmanCngPublicKey FromXmlString(string xml) { if (xml == null) { throw new ArgumentNullException("xml"); } bool isEcdh; ECParameters parameters = Rfc4050KeyFormatter.FromXml(xml, out isEcdh); if (!isEcdh) { throw new ArgumentException(SR.GetString(SR.Cryptography_ArgECDHRequiresECDHKey), "xml"); } CngKeyBlobFormat format; string curveName; byte[] blob = ECCng.EcdhParametersToBlob(ref parameters, out format, out curveName); return(new ECDiffieHellmanCngPublicKey(blob, curveName, format)); }
/// <summary> /// Exports the key used by the ECC object into an <see cref="ECParameters"/> object. /// If the key was created as a named curve, the Curve property will contain named curve parameters /// otherwise it will contain explicit parameters. /// </summary> /// <exception cref="CryptographicException"> /// if there was an issue obtaining the curve values. /// </exception> /// <returns>The key and named curve parameters used by the ECC object.</returns> public override ECParameters ExportParameters() { using (CngKey key = Import()) { ECParameters ecparams = default; string? curveName = key.GetCurveName(out _); if (string.IsNullOrEmpty(curveName)) { byte[] fullKeyBlob = ECCng.ExportFullKeyBlob(key, includePrivateParameters: false); ECCng.ExportPrimeCurveParameters(ref ecparams, fullKeyBlob, includePrivateParameters: false); } else { byte[] keyBlob = ECCng.ExportKeyBlob(key, includePrivateParameters: false); ECCng.ExportNamedCurveParameters(ref ecparams, keyBlob, includePrivateParameters: false); ecparams.Curve = ECCurve.CreateFromFriendlyName(curveName); } return(ecparams); } }
private void ImportFullKeyBlob(byte[] ecfullKeyBlob, bool includePrivateParameters) { #if !NETNATIVE Key = ECCng.ImportFullKeyBlob(ecfullKeyBlob, includePrivateParameters); #endif //!NETNATIVE }
private void ImportKeyBlob(byte[] ecfullKeyBlob, string curveName, bool includePrivateParameters) { #if !NETNATIVE Key = ECCng.ImportKeyBlob(ecfullKeyBlob, curveName, includePrivateParameters); #endif //!NETNATIVE }