Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
 private static void SetExportPolicy(CngKey key, CngExportPolicies policy)
 {
     key.SetProperty(
         new CngProperty(
             "Export Policy",
             BitConverter.GetBytes((int)policy),
             CngPropertyOptions.Persist));
 }
Пример #4
0
 /// <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();
         }
     }
 }
Пример #5
0
        /// <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();
                        }
                    }
                }
            }
        }
Пример #6
0
        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");
        }
Пример #8
0
        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();
                }
            }
        }
Пример #9
0
 /// <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();
     }
 }
Пример #10
0
    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);
                    }
                }
        }
    }