internal static RSA MakeExportable(this RSA rsa) { if (rsa is RSACng rsaCng) { const CngExportPolicies Exportability = CngExportPolicies.AllowExport | CngExportPolicies.AllowPlaintextExport; if ((rsaCng.Key.ExportPolicy & Exportability) == CngExportPolicies.AllowExport) { RSA copy = RSA.Create(); copy.ImportEncryptedPkcs8PrivateKey( nameof(MakeExportable), rsa.ExportEncryptedPkcs8PrivateKey( nameof(MakeExportable), new PbeParameters( PbeEncryptionAlgorithm.TripleDes3KeyPkcs12, HashAlgorithmName.SHA1, 2048)), out _); return(copy); } } return(rsa); }
internal static ECDsa MakeExportable(this ECDsa ecdsa) { if (ecdsa is ECDsaCng dsaCng) { const CngExportPolicies Exportability = CngExportPolicies.AllowExport | CngExportPolicies.AllowPlaintextExport; if ((dsaCng.Key.ExportPolicy & Exportability) == CngExportPolicies.AllowExport) { ECDsa copy = ECDsa.Create(); copy.ImportEncryptedPkcs8PrivateKey( (ReadOnlySpan <char>)nameof(MakeExportable), ecdsa.ExportEncryptedPkcs8PrivateKey( (ReadOnlySpan <char>)nameof(MakeExportable), new PbeParameters( PbeEncryptionAlgorithm.TripleDes3KeyPkcs12, HashAlgorithmName.SHA1, 2048)), out _); return(copy); } } return(ecdsa); }
private static void SetExportPolicy(CngKey key, CngExportPolicies policy) { key.SetProperty( new CngProperty( "Export Policy", BitConverter.GetBytes((int)policy), CngPropertyOptions.Persist)); }
/// <summary> /// Modify a CNG key's export policy. /// </summary> public static void SetExportPolicy(this SafeNCryptKeyHandle keyHandle, CngExportPolicies exportPolicy) { unsafe { ErrorCode errorCode = Interop.NCrypt.NCryptSetProperty(keyHandle, KeyPropertyName.ExportPolicy, &exportPolicy, sizeof(CngExportPolicies), CngPropertyOptions.Persist); if (errorCode != ErrorCode.ERROR_SUCCESS) { throw errorCode.ToCryptographicException(); } } }
/// <summary> /// Setup the key properties specified in the key creation parameters /// </summary> private static void InitializeKeyProperties(SafeNCryptKeyHandle keyHandle, CngKeyCreationParameters creationParameters) { unsafe { if (creationParameters.ExportPolicy.HasValue) { CngExportPolicies exportPolicy = creationParameters.ExportPolicy.Value; keyHandle.SetExportPolicy(exportPolicy); } if (creationParameters.KeyUsage.HasValue) { CngKeyUsages keyUsage = creationParameters.KeyUsage.Value; ErrorCode errorCode = Interop.NCrypt.NCryptSetProperty(keyHandle, KeyPropertyName.KeyUsage, &keyUsage, sizeof(CngKeyUsages), CngPropertyOptions.Persist); if (errorCode != ErrorCode.ERROR_SUCCESS) { throw errorCode.ToCryptographicException(); } } if (creationParameters.ParentWindowHandle != IntPtr.Zero) { IntPtr parentWindowHandle = creationParameters.ParentWindowHandle; ErrorCode errorCode = Interop.NCrypt.NCryptSetProperty(keyHandle, KeyPropertyName.ParentWindowHandle, &parentWindowHandle, sizeof(IntPtr), CngPropertyOptions.None); if (errorCode != ErrorCode.ERROR_SUCCESS) { throw errorCode.ToCryptographicException(); } } CngUIPolicy uiPolicy = creationParameters.UIPolicy; if (uiPolicy != null) { InitializeKeyUiPolicyProperties(keyHandle, uiPolicy); } // Iterate over the custom properties, setting those as well. foreach (CngProperty property in creationParameters.Parameters) { byte[] value = property.GetValueWithoutCopying(); int valueLength = (value == null) ? 0 : value.Length; fixed(byte *pValue = value.MapZeroLengthArrayToNonNullPointer()) { ErrorCode errorCode = Interop.NCrypt.NCryptSetProperty(keyHandle, property.Name, pValue, valueLength, property.Options); if (errorCode != ErrorCode.ERROR_SUCCESS) { throw errorCode.ToCryptographicException(); } } } } }
public override void ImportParameters(DSAParameters parameters) { if (parameters.P == null || parameters.Q == null || parameters.G == null || parameters.Y == null) { throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MissingFields); } // J is not required and is not even used on CNG blobs. It should however be less than P (J == (P-1) / Q). This validation check // is just to maintain parity with DSACryptoServiceProvider, which also performs this check. if (parameters.J != null && parameters.J.Length >= parameters.P.Length) { throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPJ); } bool hasPrivateKey = parameters.X != null; int keySizeInBytes = parameters.P.Length; int keySizeInBits = keySizeInBytes * 8; if (parameters.G.Length != keySizeInBytes || parameters.Y.Length != keySizeInBytes) { throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPGY); } if (hasPrivateKey && parameters.X.Length != parameters.Q.Length) { throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedQX); } using (MemoryStream ms = new MemoryStream()) { using (BinaryWriter bw = new BinaryWriter(ms)) { if (keySizeInBits <= MaxV1KeySize) { GenerateV1DsaBlob(bw, parameters, keySizeInBytes, hasPrivateKey); } else { GenerateV2DsaBlob(bw, parameters, keySizeInBytes, hasPrivateKey); } } ms.Flush(); byte[] blob = ms.ToArray(); CngKey cngKey = CngKey.Import(blob, hasPrivateKey ? CngKeyBlobFormat.GenericPrivateBlob : CngKeyBlobFormat.GenericPublicBlob); CngExportPolicies exportPolicy = cngKey.ExportPolicy | CngExportPolicies.AllowPlaintextExport; cngKey.SetProperty(new CngProperty(NCryptNative.KeyPropertyName.ExportPolicy, BitConverter.GetBytes((int)exportPolicy), CngPropertyOptions.None)); Key = cngKey; } }
private static PrivateKeyAlgorithmAndBytes AttemptToResolvePrivateKeyFromUserCertificate(X509Certificate2 userCertificate) { if (!userCertificate.HasPrivateKey) { throw new InvalidOperationException("In-memory certificate must have a private key assigned to it"); } #if (!NET45 && !NETSTANDARD1_3) const CngExportPolicies requiredPrivateKeyExportPolicies = CngExportPolicies.AllowPlaintextExport; CngKeyBlobFormat exportFormat = CngKeyBlobFormat.Pkcs8PrivateBlob; #if (!NET46) DSACng dsaCng = userCertificate.GetDSAPrivateKey() as DSACng; if (dsaCng != null) { using (dsaCng) { if (!dsaCng.Key.ExportPolicy.HasFlag(requiredPrivateKeyExportPolicies)) { throw new InvalidOperationException("In-memory certificate must be marked as exportable when importing to be used"); } return(new PrivateKeyAlgorithmAndBytes( PrivateKeyAlgorithm.DSA, dsaCng.Key.Export(exportFormat))); } } #endif RSACng rsaCng = userCertificate.GetRSAPrivateKey() as RSACng; if (rsaCng != null) { using (rsaCng) { if (!rsaCng.Key.ExportPolicy.HasFlag(requiredPrivateKeyExportPolicies)) { throw new InvalidOperationException("In-memory certificate must be marked as exportable when importing to be used"); } return(new PrivateKeyAlgorithmAndBytes( PrivateKeyAlgorithm.RSA, rsaCng.Key.Export(exportFormat))); } } #endif throw new InvalidOperationException("In-memory certificate has an unknown type of private key and cannot be used"); }
private static void SetExportable(SafeNCryptKeyHandle keyHandle) { CngExportPolicies exportPolicy = CngExportPolicies.AllowPlaintextExport; unsafe { ErrorCode errorCode = Interop.NCrypt.NCryptSetProperty( keyHandle, KeyPropertyName.ExportPolicy, &exportPolicy, sizeof(CngExportPolicies), CngPropertyOptions.Persist); if (errorCode != ErrorCode.ERROR_SUCCESS) { throw errorCode.ToCryptographicException(); } } }
/// <summary> /// Modify a CNG key's export policy. /// </summary> public static void SetExportPolicy(this SafeNCryptKeyHandle keyHandle, CngExportPolicies exportPolicy) { unsafe { ErrorCode errorCode = Interop.NCrypt.NCryptSetProperty(keyHandle, KeyPropertyName.ExportPolicy, &exportPolicy, sizeof(CngExportPolicies), CngPropertyOptions.Persist); if (errorCode != ErrorCode.ERROR_SUCCESS) throw errorCode.ToCryptographicException(); } }
private static unsafe void ImportEncryptedPkcs8Overwrite( byte[] encryptedPkcs8, string keyName, SafeNCryptProviderHandle provHandle, bool machineScope, string password) { SafeNCryptKeyHandle keyHandle; fixed(char *passwordPtr = password) fixed(char *keyNamePtr = keyName) fixed(byte *blobPtr = encryptedPkcs8) { NativeMethods.NCrypt.NCryptBuffer *buffers = stackalloc NativeMethods.NCrypt.NCryptBuffer[2]; buffers[0] = new NativeMethods.NCrypt.NCryptBuffer { BufferType = NativeMethods.NCrypt.BufferType.PkcsSecret, cbBuffer = checked (2 * (password.Length + 1)), pvBuffer = new IntPtr(passwordPtr), }; if (buffers[0].pvBuffer == IntPtr.Zero) { buffers[0].cbBuffer = 0; } buffers[1] = new NativeMethods.NCrypt.NCryptBuffer { BufferType = NativeMethods.NCrypt.BufferType.PkcsName, cbBuffer = checked (2 * (keyName.Length + 1)), pvBuffer = new IntPtr(keyNamePtr), }; NativeMethods.NCrypt.NCryptBufferDesc desc = new NativeMethods.NCrypt.NCryptBufferDesc { cBuffers = 2, pBuffers = (IntPtr)buffers, ulVersion = 0, }; NativeMethods.NCrypt.NCryptImportFlags flags = NativeMethods.NCrypt.NCryptImportFlags.NCRYPT_OVERWRITE_KEY_FLAG | NativeMethods.NCrypt.NCryptImportFlags.NCRYPT_DO_NOT_FINALIZE_FLAG; if (machineScope) { flags |= NativeMethods.NCrypt.NCryptImportFlags.NCRYPT_MACHINE_KEY_FLAG; } int errorCode = NativeMethods.NCrypt.NCryptImportKey( provHandle, IntPtr.Zero, NCRYPT_PKCS8_PRIVATE_KEY_BLOB, ref desc, out keyHandle, new IntPtr(blobPtr), encryptedPkcs8.Length, flags); if (errorCode != 0) { keyHandle.Dispose(); throw new Win32Exception(errorCode); } using (keyHandle) using (CngKey cngKey = CngKey.Open(keyHandle, CngKeyHandleOpenOptions.None)) { const CngExportPolicies desiredPolicies = CngExportPolicies.AllowExport | CngExportPolicies.AllowPlaintextExport; cngKey.SetProperty( new CngProperty( "Export Policy", BitConverter.GetBytes((int)desiredPolicies), CngPropertyOptions.Persist)); int error = NativeMethods.NCrypt.NCryptFinalizeKey(keyHandle, 0); if (error != 0) { throw new Win32Exception(error); } } } }