public static void HandleDuplication() { using (CngKey key = CngKey.Import(TestData.Key_ECDiffieHellmanP256, CngKeyBlobFormat.GenericPublicBlob)) { SafeNCryptKeyHandle keyHandle1 = key.Handle; SafeNCryptKeyHandle keyHandle2 = key.Handle; Assert.NotSame(keyHandle1, keyHandle2); keyHandle1.Dispose(); keyHandle2.Dispose(); // Make sure that disposing the spawned off handles didn't dispose the original. Set and get a custom property to ensure // the original is still in good condition. string propertyName = "Are you alive"; bool hasProperty = key.HasProperty(propertyName, CngPropertyOptions.CustomProperty); Assert.False(hasProperty); byte[] propertyValue = { 1, 2, 3 }; CngProperty property = new CngProperty(propertyName, propertyValue, CngPropertyOptions.CustomProperty); key.SetProperty(property); byte[] actualValue = key.GetProperty(propertyName, CngPropertyOptions.CustomProperty).GetValue(); Assert.Equal<byte>(propertyValue, actualValue); } }
public CngKey GetOrGenerateKey(int keySize, CngAlgorithm algorithm) { // If our key size was changed, we need to generate a new key. if (_lazyKey != null) { if (_lazyKey.KeySize != keySize) DisposeKey(); } // If we don't have a key yet, we need to generate one now. if (_lazyKey == null) { CngKeyCreationParameters creationParameters = new CngKeyCreationParameters() { ExportPolicy = CngExportPolicies.AllowPlaintextExport, }; CngProperty keySizeProperty = new CngProperty(KeyPropertyName.Length, BitConverter.GetBytes(keySize), CngPropertyOptions.None); creationParameters.Parameters.Add(keySizeProperty); _lazyKey = CngKey.Create(algorithm, null, creationParameters); } return _lazyKey; }
private void Reset() { if (IV != null) { CngProperty prop = new CngProperty(Interop.NCrypt.NCRYPT_INITIALIZATION_VECTOR, IV, CngPropertyOptions.None); _cngKey !.SetProperty(prop); } }
public static void SetPropertyNullCornerCase() { using (CngKey key = CngKey.Import(TestData.Key_ECDiffieHellmanP256, CngKeyBlobFormat.GenericPublicBlob)) { const string propertyName = "CustomNullProperty"; CngProperty p = new CngProperty(propertyName, null, CngPropertyOptions.CustomProperty); Assert.ThrowsAny<CryptographicException>(() => key.SetProperty(p)); } }
public static void SetPropertyNullCornerCase() { using (CngKey key = CngKey.Import(TestData.Key_ECDiffieHellmanP256, CngKeyBlobFormat.GenericPublicBlob)) { const string propertyName = "CustomNullProperty"; CngProperty p = new CngProperty(propertyName, null, CngPropertyOptions.CustomProperty); Assert.ThrowsAny <CryptographicException>(() => key.SetProperty(p)); } }
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); }
/// <summary> /// Create a RSA based certificate (to be used with encryption) with the given options /// </summary> /// <param name="buildOptions">Allows for more advanced configuration</param> /// <returns>An exportable X509Certificate2 object (with private key)</returns> public static X509Certificate2 CreateNewCertificate(RSACertificateBuilderOptions buildOptions) { if (buildOptions == null) { throw new ArgumentNullException("buildOptions"); } string keyName = buildOptions.RSAKeyName ?? "RSAKey"; CngKey objCngKey = null; if (CngKey.Exists(keyName)) { objCngKey = CngKey.Open(keyName); objCngKey.Delete(); } var creationParameters = new CngKeyCreationParameters(); creationParameters.ExportPolicy = CngExportPolicies.AllowExport; creationParameters.KeyUsage = CngKeyUsages.AllUsages; creationParameters.Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider; var keySizeProperty = new CngProperty("Length", BitConverter.GetBytes(buildOptions.KeySize ?? 4096), CngPropertyOptions.None); creationParameters.Parameters.Add(keySizeProperty); objCngKey = CngKey.Create(CngAlgorithm2.Rsa, keyName, creationParameters); var name = new X500DistinguishedName(buildOptions.FullSubjectName); X509CertificateSignatureAlgorithm certAlg; switch (buildOptions.HashingMethod ?? HashingMethods.Sha256) { case HashingMethods.Sha1: certAlg = X509CertificateSignatureAlgorithm.RsaSha1; break; case HashingMethods.Sha256: certAlg = X509CertificateSignatureAlgorithm.RsaSha256; break; case HashingMethods.Sha384: certAlg = X509CertificateSignatureAlgorithm.RsaSha384; break; case HashingMethods.Sha512: certAlg = X509CertificateSignatureAlgorithm.RsaSha512; break; default: throw new InvalidOperationException("Selected hashing method is not supported"); } var options = new X509CertificateCreationParameters(name) { SignatureAlgorithm = certAlg, TakeOwnershipOfKey = true }; return objCngKey.CreateSelfSignedCertificate(options); }
public static void AddKeyToCng(string providerName, string containerName) { CngKeyCreationParameters keyParams = new CngKeyCreationParameters(); keyParams.Provider = new CngProvider(providerName); keyParams.KeyCreationOptions = CngKeyCreationOptions.OverwriteExistingKey; CngProperty keySizeProperty = new CngProperty("Length", BitConverter.GetBytes(2048), CngPropertyOptions.None); keyParams.Parameters.Add(keySizeProperty); CngKey mycngKey = CngKey.Create(CngAlgorithm.Rsa, containerName, keyParams); }
/// <summary> /// Decrypts the message using an exchange private key that has a pin. /// </summary> /// <param name="encryptedMessage">Encrypted message as base64 string to be decrypted</param> /// <param name="privateKey">Private exchange key to decrypt the message</param> /// <param name="padding">Padding mode to be used with the decryption</param> /// <param name="pin">The private key pin</param> /// <returns>Decrypted message as byte array</returns> /// <exception cref="ArgumentException">There is null in the parameters or one of the parameters empty</exception> /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.-or- The parameters parameter has missing fields. -or- The padding mode is not supported. -or- The certificate context is invalid. -or- wrong pin has been inputed.</exception> /// <exception cref="FormatException">The length of string, ignoring white-space characters, is not zero or a multiple of 4. -or-The format of s is invalid. string contains a non-base-64 character, more than two padding characters, or a non-white space-character among the padding characters.</exception> public static byte[] Decrypt(string encryptedMessage, X509Certificate2 privateKey, RSAEncryptionPadding padding, string pin) { try { byte[] decodedEncryptedBytes = Convert.FromBase64String(encryptedMessage); RSA rsa = privateKey.GetRSAPrivateKey(); RSACng rsaCng = rsa as RSACng; if (rsaCng != null) { // Set the PIN, an explicit null terminator is required to this Unicode/UCS-2 string. byte[] propertyBytes; if (pin[pin.Length - 1] == '\0') { propertyBytes = Encoding.Unicode.GetBytes(pin); } else { propertyBytes = new byte[Encoding.Unicode.GetByteCount(pin) + 2]; Encoding.Unicode.GetBytes(pin, 0, pin.Length, propertyBytes, 0); } const string NCRYPT_PIN_PROPERTY = "SmartCardPin"; CngProperty pinProperty = new CngProperty( NCRYPT_PIN_PROPERTY, propertyBytes, CngPropertyOptions.None); rsaCng.Key.SetProperty(pinProperty); return(rsaCng.Decrypt(decodedEncryptedBytes, padding)); } throw new CryptographicException("The key is not compatible with Cryptography Next Generation (CNG)"); } catch (CryptographicException ex) { throw ex; } catch (ArgumentNullException ex) { throw ex; } catch (FormatException ex) { throw ex; } }
public static void SetPropertyZeroLengthCornerCase() { using (CngKey key = CngKey.Import(TestData.Key_ECDiffieHellmanP256, CngKeyBlobFormat.GenericPublicBlob)) { const string propertyName = "CustomZeroLengthProperty"; CngProperty p = new CngProperty(propertyName, new byte[0], CngPropertyOptions.CustomProperty); key.SetProperty(p); CngProperty p2 = key.GetProperty(propertyName, CngPropertyOptions.CustomProperty); Assert.Equal(propertyName, p2.Name); Assert.Equal(CngPropertyOptions.CustomProperty, p2.Options); // This one is odd. CNG keys can have properties with zero length but CngKey.GetProperty() transforms this into null. Assert.Equal(null, p2.GetValue()); } }
// // The first parameter is a delegate that instantiates a CngKey rather than a CngKey itself. That's because CngKeys are stateful objects // and concurrent encryptions on the same CngKey will corrupt each other. // // The delegate must instantiate a new CngKey, based on a new underlying NCryptKeyHandle, each time is called. // public BasicSymmetricCipherNCrypt(Func <CngKey> cngKeyFactory, CipherMode cipherMode, int blockSizeInBytes, byte[] iv, bool encrypting) : base(iv, blockSizeInBytes) { _encrypting = encrypting; _cngKey = cngKeyFactory(); CngProperty chainingModeProperty = cipherMode switch { CipherMode.ECB => s_ECBMode, CipherMode.CBC => s_CBCMode, _ => throw new CryptographicException(SR.Cryptography_InvalidCipherMode), }; _cngKey.SetProperty(chainingModeProperty); Reset(); }
public static void SetPropertyZeroLengthCornerCase() { using (CngKey key = CngKey.Import(TestData.Key_ECDiffieHellmanP256, CngKeyBlobFormat.GenericPublicBlob)) { const string propertyName = "CustomZeroLengthProperty"; CngProperty p = new CngProperty(propertyName, new byte[0], CngPropertyOptions.CustomProperty); key.SetProperty(p); CngProperty p2 = key.GetProperty(propertyName, CngPropertyOptions.CustomProperty); Assert.Equal(propertyName, p2.Name); Assert.Equal(CngPropertyOptions.CustomProperty, p2.Options); // This one is odd. CNG keys can have properties with zero length but CngKey.GetProperty() transforms this into null. Assert.Null(p2.GetValue()); } }
public static void GetAndSetProperties() { using (CngKey key = CngKey.Import(TestData.Key_ECDiffieHellmanP256, CngKeyBlobFormat.GenericPublicBlob)) { string propertyName = "Are you there"; bool hasProperty = key.HasProperty(propertyName, CngPropertyOptions.CustomProperty); Assert.False(hasProperty); byte[] propertyValue = { 1, 2, 3 }; CngProperty property = new CngProperty(propertyName, propertyValue, CngPropertyOptions.CustomProperty); key.SetProperty(property); byte[] actualValue = key.GetProperty(propertyName, CngPropertyOptions.CustomProperty).GetValue(); Assert.Equal <byte>(propertyValue, actualValue); } }
public static void GetAndSetProperties() { using (CngKey key = CngKey.Import(TestData.Key_ECDiffieHellmanP256, CngKeyBlobFormat.GenericPublicBlob)) { string propertyName = "Are you there"; bool hasProperty = key.HasProperty(propertyName, CngPropertyOptions.CustomProperty); Assert.False(hasProperty); byte[] propertyValue = { 1, 2, 3 }; CngProperty property = new CngProperty(propertyName, propertyValue, CngPropertyOptions.CustomProperty); key.SetProperty(property); byte[] actualValue = key.GetProperty(propertyName, CngPropertyOptions.CustomProperty).GetValue(); Assert.Equal<byte>(propertyValue, actualValue); } }
/// <summary> /// Set an arbitrary property on the key /// </summary> public void SetProperty(CngProperty property) { unsafe { byte[] propertyValue = property.GetValueWithoutCopying(); // Desktop compat. It would have nicer to throw an ArgumentNull exception or something... if (propertyValue == null) throw ErrorCode.NTE_INVALID_PARAMETER.ToCryptographicException(); fixed (byte* pinnedPropertyValue = propertyValue.MapZeroLengthArrayToNonNullPointer()) { ErrorCode errorCode = Interop.NCrypt.NCryptSetProperty(_keyHandle, property.Name, pinnedPropertyValue, propertyValue.Length, property.Options); if (errorCode != ErrorCode.ERROR_SUCCESS) throw errorCode.ToCryptographicException(); } } }
internal static void SetAccessRuleOnKSPKey(CngKey key, string accountName, CryptoKeyRights keyAccessMask) { const string NCRYPT_SECURITY_DESCR_PROPERTY = "Security Descr"; const CngPropertyOptions DACL_SECURITY_INFORMATION = (CngPropertyOptions)4; // retrieve existing permissions var existingACL = key.GetProperty(NCRYPT_SECURITY_DESCR_PROPERTY, DACL_SECURITY_INFORMATION); // add new rule CryptoKeySecurity keySec = new CryptoKeySecurity(); keySec.SetSecurityDescriptorBinaryForm(existingACL.GetValue()); keySec.AddAccessRule(new CryptoKeyAccessRule(accountName, keyAccessMask, AccessControlType.Allow)); // put back CngProperty updatedACL = new CngProperty(existingACL.Name, keySec.GetSecurityDescriptorBinaryForm(), CngPropertyOptions.Persist | DACL_SECURITY_INFORMATION); key.SetProperty(updatedACL); }
/// <summary> /// Computes the hash value of the specified byte array using the specified hash algorithm, /// and signs the resulting hash value using a certificate with a pin. /// https://stackoverflow.com/questions/42626742/how-can-i-set-pin-for-a-x509certificate2-programmatically /// </summary> /// <param name="data">Data (not hash) to be signed</param> /// <param name="privateKey">The private key used for signing</param> /// <param name="hashAlgorithm">The hash algorithm used in hashing the data before signing</param> /// <param name="padding">The padding that will be used in the signature</param> /// <param name="pin">The private key pin</param> /// <returns>Return signed hash as byte array, or null if fails</returns> /// <exception cref="ArgumentException">There is null in the parameters or one of the parameters empty</exception> /// <exception cref="CryptographicException">The cryptographic service provider (CSP) cannot be acquired.-or- The parameters parameter has missing fields. -or- The padding mode is not supported. -or- The certificate context is invalid. -or- wrong pin has been inputed.</exception> public static byte[] SignData(byte[] data, X509Certificate2 privateKey, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, string pin) { try { RSA rsa = privateKey.GetRSAPrivateKey(); RSACng rsaCng = rsa as RSACng; if (rsaCng != null) { // Set the PIN, an explicit null terminator is required to this Unicode/UCS-2 string. byte[] propertyBytes; if (pin[pin.Length - 1] == '\0') { propertyBytes = Encoding.Unicode.GetBytes(pin); } else { propertyBytes = new byte[Encoding.Unicode.GetByteCount(pin) + 2]; Encoding.Unicode.GetBytes(pin, 0, pin.Length, propertyBytes, 0); } const string NCRYPT_PIN_PROPERTY = "SmartCardPin"; CngProperty pinProperty = new CngProperty( NCRYPT_PIN_PROPERTY, propertyBytes, CngPropertyOptions.None); rsaCng.Key.SetProperty(pinProperty); return(rsaCng.SignData(data, hashAlgorithm, padding)); } throw new CryptographicException("The key is not compatible with Cryptography Next Generation (CNG)"); } catch (ArgumentException ex) { throw ex; } catch (CryptographicException ex) { throw ex; } }
public static void AddKeyToCng(string providerName, string containerName) { #if NET5_0_OR_GREATER System.Diagnostics.Debug.Assert(OperatingSystem.IsWindows()); #endif CngKeyCreationParameters keyParams = new CngKeyCreationParameters(); keyParams.Provider = new CngProvider(providerName); keyParams.KeyCreationOptions = CngKeyCreationOptions.None; CngProperty keySizeProperty = new CngProperty("Length", BitConverter.GetBytes(2048), CngPropertyOptions.None); keyParams.Parameters.Add(keySizeProperty); // Add Cng Key only if not exists. if (!CngKey.Exists(containerName)) { CngKey mycngKey = CngKey.Create(CngAlgorithm.Rsa, containerName, keyParams); } }
public static RSACng GetOrCreateRSACng(string rsaKeyName) { Guard.AgainstNullOrEmpty(rsaKeyName, nameof(rsaKeyName)); CngKey cngKey; if (CngKey.Exists(rsaKeyName)) { cngKey = CngKey.Open(rsaKeyName); } else { var cngLengthProperty = new CngProperty( _lengthPropertyName, BitConverter.GetBytes(KeySize), CngPropertyOptions.None); var cngKeyCreationParameters = new CngKeyCreationParameters { KeyUsage = CngKeyUsages.AllUsages, ExportPolicy = CngExportPolicies.AllowPlaintextExport | CngExportPolicies.AllowExport | CngExportPolicies.AllowArchiving | CngExportPolicies.AllowPlaintextArchiving }; cngKeyCreationParameters.Parameters.Add(cngLengthProperty); cngKey = CngKey.Create(CngAlgorithm.Rsa, rsaKeyName, cngKeyCreationParameters); } return(new RSACng(cngKey) { KeySize = KeySize }); }
public CngKey GetOrGenerateKey(int keySize, CngAlgorithm algorithm) { // If our key size was changed from the key we're using, we need to generate a new key. if (_lazyKey != null && _lazyKey.KeySize != keySize) { _lazyKey.Dispose(); _lazyKey = null; } // If we don't have a key yet, we need to generate a random one now. if (_lazyKey == null) { CngKeyCreationParameters creationParameters = new CngKeyCreationParameters() { ExportPolicy = CngExportPolicies.AllowPlaintextExport, }; CngProperty keySizeProperty = new CngProperty(KeyPropertyName.Length, BitConverter.GetBytes(keySize), CngPropertyOptions.None); creationParameters.Parameters.Add(keySizeProperty); _lazyKey = CngKey.Create(algorithm, null, creationParameters); } return(_lazyKey); }
public static void OverwriteProperties() { using (CngKey key = CngKey.Import(TestData.Key_ECDiffieHellmanP256, CngKeyBlobFormat.GenericPublicBlob)) { string propertyName = "Are you there"; bool hasProperty = key.HasProperty(propertyName, CngPropertyOptions.CustomProperty); Assert.False(hasProperty); // Set it once. byte[] propertyValue = { 1, 2, 3 }; CngProperty property = new CngProperty(propertyName, propertyValue, CngPropertyOptions.CustomProperty); key.SetProperty(property); // Set it again. propertyValue = new byte[] { 5, 6, 7 }; property = new CngProperty(propertyName, propertyValue, CngPropertyOptions.CustomProperty); key.SetProperty(property); CngProperty retrievedProperty = key.GetProperty(propertyName, CngPropertyOptions.CustomProperty); Assert.Equal(propertyName, retrievedProperty.Name); Assert.Equal <byte>(propertyValue, retrievedProperty.GetValue()); Assert.Equal(CngPropertyOptions.CustomProperty, retrievedProperty.Options); } }
public void SetProperty(CngProperty property) { NCryptNative.SetProperty(this.m_keyHandle, property.Name, property.Value, property.Options); }
private void Reset() { if (IV != null) { CngProperty prop = new CngProperty(Interop.NCrypt.NCRYPT_INITIALIZATION_VECTOR, IV, CngPropertyOptions.None); _cngKey.SetProperty(prop); } }
/// <summary> /// Tries to generate and RSA Key in the given provider with this keyName. /// </summary> /// <param name="providerName">Name of the provider</param> /// <param name="keyName">Name of the key</param> /// <param name="keyLength">Length of the key to generate</param> /// <returns>true if successful, false if that key already exists.</returns> public bool TryGenerateLocalRSAKey(string providerName, string keyName, int keyLength = 2048) { CngProvider provider = new CngProvider(providerName); bool keyExists = doesKeyExists(provider, keyName); if (keyExists) { //Key already exists. Can't create it. return(false); } CryptoKeySecurity sec = new CryptoKeySecurity(); CngKeyCreationParameters keyParams = null; if (IsMicrosoftSoftwareKSP(provider)) { sec.AddAccessRule( new CryptoKeyAccessRule( new SecurityIdentifier(sidType: WellKnownSidType.BuiltinAdministratorsSid, domainSid: null), cryptoKeyRights: CryptoKeyRights.FullControl, type: AccessControlType.Allow)); sec.AddAccessRule( new CryptoKeyAccessRule( new SecurityIdentifier(sidType: WellKnownSidType.BuiltinSystemOperatorsSid, domainSid: null), cryptoKeyRights: CryptoKeyRights.GenericRead, type: AccessControlType.Allow)); const string NCRYPT_SECURITY_DESCR_PROPERTY = "Security Descr"; const CngPropertyOptions DACL_SECURITY_INFORMATION = (CngPropertyOptions)4; CngProperty permissions = new CngProperty( NCRYPT_SECURITY_DESCR_PROPERTY, sec.GetSecurityDescriptorBinaryForm(), CngPropertyOptions.Persist | DACL_SECURITY_INFORMATION); keyParams = new CngKeyCreationParameters() { ExportPolicy = CngExportPolicies.None, Provider = provider, Parameters = { new CngProperty("Length", BitConverter.GetBytes(keyLength), CngPropertyOptions.None), permissions }, KeyCreationOptions = CngKeyCreationOptions.MachineKey }; using (CngKey key = CngKey.Create(CngAlgorithm.Rsa, keyName, keyParams)) { if (key == null) { return(false); } return(true); } } else { keyParams = new CngKeyCreationParameters() { ExportPolicy = CngExportPolicies.None, Provider = provider, Parameters = { new CngProperty("Length", BitConverter.GetBytes(keyLength), CngPropertyOptions.None) } }; using (CngKey key = CngKey.Create(CngAlgorithm.Rsa, keyName, keyParams)) { if (key == null) { return(false); } // nothing to do inside here, except to return without throwing an exception return(true); } } }
/// <summary> /// Sign an XML file. /// </summary> /// <param name="xmlDoc"> XML document object that holds the XML data</param> /// <param name="signingKey">The certificate which will be used in signing the XML document</param> /// <param name="addKey">Flag to indicate if the public key should be included in the signed XML document or not</param> /// <param name="pin">The pin of the CNG certificate.</param> /// <exception cref="ArgumentNullException">Private key is null or any of the passed arguments is null.</exception> /// <exception cref="CryptographicException">The key value is not an RSA key, or the key is unreadable.</exception> /// <exception cref="NotSupportedException">The key algorithm for this private key is not supported.</exception> /// <exception cref="CryptographicUnexpectedOperationException">The X.509 keys do not match.</exception> /// <exception cref="ArgumentException">The cryptographic service provider key is null.</exception> private static void SignXml(XmlDocument xmlDoc, X509Certificate2 signingKey, bool addKey, string pin) { if (signingKey == null) { throw new ArgumentNullException("signingKey is null"); } // Create RSA signing key and save it in the container. RSACng key = null; // Try to load the RSA CNG key into key container. try { RSA rsa = signingKey.GetRSAPrivateKey(); key = rsa as RSACng; if (key != null) { // Set the PIN, an explicit null terminator is required to this Unicode/UCS-2 string. byte[] propertyBytes; if (pin[pin.Length - 1] == '\0') { propertyBytes = Encoding.Unicode.GetBytes(pin); } else { propertyBytes = new byte[Encoding.Unicode.GetByteCount(pin) + 2]; Encoding.Unicode.GetBytes(pin, 0, pin.Length, propertyBytes, 0); } const string NCRYPT_PIN_PROPERTY = "SmartCardPin"; CngProperty pinProperty = new CngProperty( NCRYPT_PIN_PROPERTY, propertyBytes, CngPropertyOptions.None); key.Key.SetProperty(pinProperty); } else { throw new CryptographicException("The key is not compatible with Cryptography Next Generation (CNG)"); } } catch (ArgumentException ex) { throw ex; } catch (CryptographicException ex) { throw ex; } // Check arguments. if (xmlDoc == null) { throw new ArgumentNullException("xmlDoc is null"); } // Create a SignedXml object. SignedXml signedXml = new SignedXml(xmlDoc) { // Add the key to the SignedXml document. SigningKey = key ?? throw new ArgumentNullException("Private key is null") }; // Add public key of the certificate if (addKey) { KeyInfo keyInfo = new KeyInfo(); KeyInfoX509Data keyInfoData = new KeyInfoX509Data(signingKey); keyInfo.AddClause(keyInfoData); signedXml.KeyInfo = keyInfo; } // Create a reference to be signed. Reference reference = new Reference(); reference.Uri = ""; // Add an enveloped transformation to the reference. XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform(); reference.AddTransform(env); // Add the reference to the SignedXml object. signedXml.AddReference(reference); // Compute the signature. signedXml.ComputeSignature(); // Get the XML representation of the signature and save // it to an XmlElement object. XmlElement xmlDigitalSignature = signedXml.GetXml(); // Append the element to the XML document. xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true)); }
/// <summary> /// Create a RSA based certificate (to be used with encryption) with the given options /// </summary> /// <param name="buildOptions">Allows for more advanced configuration</param> /// <returns>An exportable X509Certificate2 object (with private key)</returns> public static X509Certificate2 CreateNewCertificate(RSACertificateBuilderOptions buildOptions) { if (buildOptions == null) { throw new ArgumentNullException("buildOptions"); } string keyName = buildOptions.RSAKeyName ?? "RSAKey"; CngKey objCngKey = null; if (CngKey.Exists(keyName)) { objCngKey = CngKey.Open(keyName); objCngKey.Delete(); } var creationParameters = new CngKeyCreationParameters(); creationParameters.ExportPolicy = CngExportPolicies.AllowExport; creationParameters.KeyUsage = CngKeyUsages.AllUsages; creationParameters.Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider; var keySizeProperty = new CngProperty("Length", BitConverter.GetBytes(buildOptions.KeySize ?? 4096), CngPropertyOptions.None); creationParameters.Parameters.Add(keySizeProperty); objCngKey = CngKey.Create(CngAlgorithm2.Rsa, keyName, creationParameters); var name = new X500DistinguishedName(buildOptions.FullSubjectName); X509CertificateSignatureAlgorithm certAlg; switch (buildOptions.HashingMethod ?? HashingMethods.Sha256) { case HashingMethods.Sha1: certAlg = X509CertificateSignatureAlgorithm.RsaSha1; break; case HashingMethods.Sha256: certAlg = X509CertificateSignatureAlgorithm.RsaSha256; break; case HashingMethods.Sha384: certAlg = X509CertificateSignatureAlgorithm.RsaSha384; break; case HashingMethods.Sha512: certAlg = X509CertificateSignatureAlgorithm.RsaSha512; break; default: throw new InvalidOperationException("Selected hashing method is not supported"); } var options = new X509CertificateCreationParameters(name) { SignatureAlgorithm = certAlg, TakeOwnershipOfKey = true }; return(objCngKey.CreateSelfSignedCertificate(options)); }
public void SetProperty(CngProperty property) { Contract.Assert(m_keyHandle != null); NCryptNative.SetProperty(m_keyHandle, property.Name, property.Value, property.Options); }
/// <summary> /// Creates CngKey Elliptic Curve Key from given (x,y) curve point - public part /// and optional d - private part /// </summary> /// <param name="x">x coordinate of curve point</param> /// <param name="y">y coordinate of curve point</param> /// <param name="d">optional private part</param> /// <returns>CngKey for given (x,y) and d</returns> public static CngKey New(byte[] x, byte[] y, byte[] d = null, CngKeyUsages usage = CngKeyUsages.Signing) { if (x.Length != y.Length) { throw new ArgumentException("X,Y and D must be same size"); } if (d != null && x.Length != d.Length) { throw new ArgumentException("X,Y and D must be same size"); } if (usage != CngKeyUsages.Signing && usage != CngKeyUsages.KeyAgreement) { throw new ArgumentException("Usage parameter expected to be set either 'CngKeyUsages.Signing' or 'CngKeyUsages.KeyAgreement"); } bool signing = usage == CngKeyUsages.Signing; int partSize = x.Length; byte[] magic; if (partSize == 32) { magic = (d == null) ? signing ? BCRYPT_ECDSA_PUBLIC_P256_MAGIC : BCRYPT_ECDH_PUBLIC_P256_MAGIC : signing ? BCRYPT_ECDSA_PRIVATE_P256_MAGIC : BCRYPT_ECDH_PRIVATE_P256_MAGIC; } else if (partSize == 48) { magic = (d == null) ? signing ? BCRYPT_ECDSA_PUBLIC_P384_MAGIC : BCRYPT_ECDH_PUBLIC_P384_MAGIC : signing ? BCRYPT_ECDSA_PRIVATE_P384_MAGIC : BCRYPT_ECDH_PRIVATE_P384_MAGIC; } else if (partSize == 66) { magic = (d == null) ? signing ? BCRYPT_ECDSA_PUBLIC_P521_MAGIC : BCRYPT_ECDH_PUBLIC_P521_MAGIC : signing ? BCRYPT_ECDSA_PRIVATE_P521_MAGIC : BCRYPT_ECDH_PRIVATE_P521_MAGIC; } else { throw new ArgumentException("Size of X,Y or D must equal to 32, 48 or 66 bytes"); } byte[] partLength = BitConverter.GetBytes(partSize); CngKeyBlobFormat blobType; byte[] blob; if (d == null) { blob = Arrays.Concat(magic, partLength, x, y); blobType = CngKeyBlobFormat.EccPublicBlob; } else { blob = Arrays.Concat(magic, partLength, x, y, d); blobType = CngKeyBlobFormat.EccPrivateBlob; } CngKey key = CngKey.Import(blob, blobType); CngProperty exportable = new CngProperty( "Export Policy", BitConverter.GetBytes((int)(CngExportPolicies.AllowPlaintextExport)), CngPropertyOptions.Persist ); key.SetProperty(exportable); return(key); }
public void SetProperty(CngProperty property) { throw new NotImplementedException (); }
public static void OverwriteProperties() { using (CngKey key = CngKey.Import(TestData.Key_ECDiffieHellmanP256, CngKeyBlobFormat.GenericPublicBlob)) { string propertyName = "Are you there"; bool hasProperty = key.HasProperty(propertyName, CngPropertyOptions.CustomProperty); Assert.False(hasProperty); // Set it once. byte[] propertyValue = { 1, 2, 3 }; CngProperty property = new CngProperty(propertyName, propertyValue, CngPropertyOptions.CustomProperty); key.SetProperty(property); // Set it again. propertyValue = new byte[] { 5, 6, 7 }; property = new CngProperty(propertyName, propertyValue, CngPropertyOptions.CustomProperty); key.SetProperty(property); CngProperty retrievedProperty = key.GetProperty(propertyName, CngPropertyOptions.CustomProperty); Assert.Equal(propertyName, retrievedProperty.Name); Assert.Equal<byte>(propertyValue, retrievedProperty.GetValue()); Assert.Equal(CngPropertyOptions.CustomProperty, retrievedProperty.Options); } }
public static void NullValueRoundtrip() { CngProperty property = new CngProperty("banana", null, CngPropertyOptions.CustomProperty); Assert.Null(property.GetValue()); }
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; }
/// <summary> /// Import a key from a file for use on the machine. /// </summary> /// <param name="providerName"></param> /// <param name="filePath"></param> public bool ImportKeyToKSP(string providerName, string keyName, string filePath, bool makeExportable = false) { CngProvider provider = new CngProvider(providerName); bool keyExists = doesKeyExists(provider, keyName); if (keyExists) { //Key already exists. Can't create it. return(false); } CryptoKeySecurity sec = new CryptoKeySecurity(); CngKeyCreationParameters keyParams = null; byte[] keyBlob = File.ReadAllBytes(filePath); CngProperty keyBlobProp = new CngProperty(new CngKeyBlobFormat("RSAFULLPRIVATEBLOB").Format, keyBlob, CngPropertyOptions.None); if (IsMicrosoftSoftwareKSP(provider)) { sec.AddAccessRule( new CryptoKeyAccessRule( new SecurityIdentifier(sidType: WellKnownSidType.BuiltinAdministratorsSid, domainSid: null), cryptoKeyRights: CryptoKeyRights.FullControl, type: AccessControlType.Allow)); sec.AddAccessRule( new CryptoKeyAccessRule( new SecurityIdentifier(sidType: WellKnownSidType.BuiltinSystemOperatorsSid, domainSid: null), cryptoKeyRights: CryptoKeyRights.GenericRead, type: AccessControlType.Allow)); const string NCRYPT_SECURITY_DESCR_PROPERTY = "Security Descr"; const CngPropertyOptions DACL_SECURITY_INFORMATION = (CngPropertyOptions)4; CngProperty permissions = new CngProperty( NCRYPT_SECURITY_DESCR_PROPERTY, sec.GetSecurityDescriptorBinaryForm(), CngPropertyOptions.Persist | DACL_SECURITY_INFORMATION); keyParams = new CngKeyCreationParameters() { ExportPolicy = makeExportable ? CngExportPolicies.AllowExport | CngExportPolicies.AllowPlaintextExport : CngExportPolicies.None, Provider = provider, Parameters = { permissions, keyBlobProp }, KeyCreationOptions = CngKeyCreationOptions.MachineKey }; using (CngKey key = CngKey.Create(CngAlgorithm.Rsa, keyName, keyParams)) { if (key == null) { return(false); } return(true); } } else { keyParams = new CngKeyCreationParameters() { ExportPolicy = makeExportable ? CngExportPolicies.AllowExport | CngExportPolicies.AllowPlaintextExport : CngExportPolicies.None, Provider = provider, Parameters = { keyBlobProp }, KeyCreationOptions = CngKeyCreationOptions.MachineKey }; using (CngKey key = CngKey.Create(CngAlgorithm.Rsa, keyName, keyParams)) { if (key == null) { return(false); } // nothing to do inside here, except to return without throwing an exception return(true); } } }
public void SetProperty(CngProperty property) { }