private static void CreateKeys() { aliceKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256); alicePubKeyBlod = aliceKey.Export(CngKeyBlobFormat.GenericPublicBlob); bobKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256); bobPubKeyBlob = bobKey.Export(CngKeyBlobFormat.GenericPublicBlob); }
public static byte[] DeriveKey(CngKey externalPubKey, CngKey privateKey, int keyBitLength, byte[] algorithmId, byte[] partyVInfo, byte[] partyUInfo, byte[] suppPubInfo) { using (var cng = new ECDiffieHellmanCng(privateKey)) { using (SafeNCryptSecretHandle hSecretAgreement = cng.DeriveSecretAgreementHandle(externalPubKey)) { using (var algIdBuffer = new NCrypt.NCryptBuffer(NCrypt.KDF_ALGORITHMID, algorithmId)) using (var pviBuffer = new NCrypt.NCryptBuffer(NCrypt.KDF_PARTYVINFO, partyVInfo)) using (var pvuBuffer = new NCrypt.NCryptBuffer(NCrypt.KDF_PARTYUINFO, partyUInfo)) using (var spiBuffer = new NCrypt.NCryptBuffer(NCrypt.KDF_SUPPPUBINFO, suppPubInfo)) { using (var parameters = new NCrypt.NCryptBufferDesc(algIdBuffer, pviBuffer, pvuBuffer, spiBuffer)) { uint derivedSecretByteSize; uint status = NCrypt.NCryptDeriveKey(hSecretAgreement, "SP800_56A_CONCAT", parameters, null, 0, out derivedSecretByteSize, 0); if (status != BCrypt.ERROR_SUCCESS) throw new CryptographicException(string.Format("NCrypt.NCryptDeriveKey() failed with status code:{0}", status)); var secretKey = new byte[derivedSecretByteSize]; status = NCrypt.NCryptDeriveKey(hSecretAgreement, "SP800_56A_CONCAT", parameters, secretKey, derivedSecretByteSize, out derivedSecretByteSize, 0); if (status != BCrypt.ERROR_SUCCESS) throw new CryptographicException(string.Format("NCrypt.NCryptDeriveKey() failed with status code:{0}", status)); return Arrays.LeftmostBits(secretKey, keyBitLength); } } } } }
private static X509Certificate2 CreateSelfSignedCertificate(CngKey key, X500DistinguishedName subjectName) { using (SafeCertContextHandle selfSignedCertHandle = CreateSelfSignedCertificate(key, true, subjectName.RawData, X509CertificateCreationOptions.None, // NONE RsaSha1Oid, DateTime.UtcNow, DateTime.UtcNow.AddYears(1))) { X509Certificate2 certificate = null; bool addedRef = false; RuntimeHelpers.PrepareConstrainedRegions(); try { selfSignedCertHandle.DangerousAddRef(ref addedRef); certificate = new X509Certificate2(selfSignedCertHandle.DangerousGetHandle()); } finally { if (addedRef) { selfSignedCertHandle.DangerousRelease(); } } key.Dispose(); return certificate; } }
/// <summary> /// Decrypts a ProcessedPacket. /// </summary> /// <param name="InitializationVector">Initialization vec to be used by AES.</param> /// <param name="PrivateKey">Private key to be used.</param> /// <param name="PubKeyBlob">Public key blob to be used.</param> /// <param name="StreamToDecrypt">The stream to decrypt.</param> /// <returns>A decrypted stream.</returns> public static byte[] DecryptData(byte[] InitializationVector, CngKey PrivateKey, byte[] PubKeyBlob, byte[] DataToDecrypt) { using (var Algorithm = new ECDiffieHellmanCng(PrivateKey)) { using (CngKey PubKey = CngKey.Import(PubKeyBlob, CngKeyBlobFormat.EccPublicBlob)) { byte[] SymmetricKey = Algorithm.DeriveKeyMaterial(PubKey); Console.WriteLine("DecryptedStream: Created symmetric key with " + "public key information: {0}", Convert.ToBase64String(SymmetricKey)); AesCryptoServiceProvider AES = new AesCryptoServiceProvider(); AES.Key = SymmetricKey; AES.IV = InitializationVector; int NBytes = AES.BlockSize >> 3; //No idea... using (ICryptoTransform Decryptor = AES.CreateDecryptor()) { using (MemoryStream DecryptedStream = new MemoryStream()) { var cs = new CryptoStream(DecryptedStream, Decryptor, CryptoStreamMode.Write); cs.Write(DataToDecrypt, NBytes, DataToDecrypt.Length - NBytes); cs.FlushFinalBlock(); return DecryptedStream.ToArray(); } } } } }
public byte[] DeriveKeyMaterial(CngKey otherPartyPublicKey) { Contract.Ensures(Contract.Result<byte[]>() != null); Contract.Ensures(this.Key.Handle != null); return default(byte[]); }
public override void Write(CngKey key, Stream stream) { int keySize; byte[] x; byte[] y; var keyBlob = key.Export(CngKeyBlobFormat.EccPublicBlob); unsafe { fixed(byte* pKeyBlob = keyBlob) { var pBcryptBlob = (BCRYPT_ECCKEY_BLOB*) pKeyBlob; var offset = Marshal.SizeOf(typeof (BCRYPT_ECCKEY_BLOB)); keySize = pBcryptBlob->KeySizeBytes; x = new byte[keySize]; y = new byte[keySize]; Buffer.BlockCopy(keyBlob, offset, x, 0, keySize); offset += keySize; Buffer.BlockCopy(keyBlob, offset, y, 0, keySize); } } WriteInternal(keySize, x, y, stream); }
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 !NETNATIVE keyHandle = ECCng.ImportKeyBlob(format.Format, keyBlob, curveName, providerHandle); #endif //!NETNATIVE } 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 ECDsaCng(CngKey key) { Contract.Ensures(LegalKeySizesValue != null); Contract.Ensures(m_key != null && m_key.AlgorithmGroup == CngAlgorithmGroup.ECDsa); if (key == null) { throw new ArgumentNullException("key"); } if (key.AlgorithmGroup != CngAlgorithmGroup.ECDsa) { throw new ArgumentException(SR.GetString(SR.Cryptography_ArgECDsaRequiresECDsaKey), "key"); } if (!NCryptNative.NCryptSupported) { throw new PlatformNotSupportedException(SR.GetString(SR.Cryptography_PlatformNotSupported)); } LegalKeySizesValue = s_legalKeySizes; // Make a copy of the key so that we continue to work if it gets disposed before this algorithm // // This requires an assert for UnmanagedCode since we'll need to access the raw handles of the key // and the handle constructor of CngKey. The assert is safe since ECDsaCng will never expose the // key handles to calling code (without first demanding UnmanagedCode via the Handle property of // CngKey). // // We also need to dispose of the key handle since CngKey.Handle returns a duplicate new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); using (SafeNCryptKeyHandle keyHandle = key.Handle) { Key = CngKey.Open(keyHandle, key.IsEphemeral ? CngKeyHandleOpenOptions.EphemeralKey : CngKeyHandleOpenOptions.None); } CodeAccessPermission.RevertAssert(); KeySize = m_key.KeySize; }
public static CngKey Create(CngAlgorithm algorithm, string keyName, CngKeyCreationParameters creationParameters) { if (algorithm == null) throw new ArgumentNullException("algorithm"); if (creationParameters == null) creationParameters = new CngKeyCreationParameters(); SafeNCryptProviderHandle providerHandle = creationParameters.Provider.OpenStorageProvider(); SafeNCryptKeyHandle keyHandle; ErrorCode errorCode = Interop.NCrypt.NCryptCreatePersistedKey(providerHandle, out keyHandle, algorithm.Algorithm, keyName, 0, creationParameters.KeyCreationOptions); if (errorCode != ErrorCode.ERROR_SUCCESS) throw errorCode.ToCryptographicException(); InitializeKeyProperties(keyHandle, creationParameters); errorCode = Interop.NCrypt.NCryptFinalizeKey(keyHandle, 0); if (errorCode != ErrorCode.ERROR_SUCCESS) throw errorCode.ToCryptographicException(); CngKey key = new CngKey(providerHandle, keyHandle); // No name translates to an ephemeral key if (keyName == null) { key.IsEphemeral = true; } return key; }
public static void CreateKeys() { // 根据算法创建密钥对 aliceKeySignature = CngKey.Create(CngAlgorithm.ECDsaP256); // 导出密钥对中的公钥 alicePubKeyBlob = aliceKeySignature.Export(CngKeyBlobFormat.GenericPublicBlob); }
private static byte[] Sign(byte[] message, byte[] prikey) { var Secp256r1_G = HexString2Bytes("04" + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"); var PublicKey = Neo.Cryptography.ECC.ECCurve.Secp256r1.G * prikey; var pubkey = PublicKey.EncodePoint(false).Skip(1).ToArray(); //#if NET461 const int ECDSA_PRIVATE_P256_MAGIC = 0x32534345; prikey = BitConverter.GetBytes(ECDSA_PRIVATE_P256_MAGIC).Concat(BitConverter.GetBytes(32)).Concat(pubkey).Concat(prikey).ToArray(); using (System.Security.Cryptography.CngKey key = System.Security.Cryptography.CngKey.Import(prikey, System.Security.Cryptography.CngKeyBlobFormat.EccPrivateBlob)) using (System.Security.Cryptography.ECDsaCng ecdsa = new System.Security.Cryptography.ECDsaCng(key)) //#else // using (var ecdsa = System.Security.Cryptography.ECDsa.Create(new System.Security.Cryptography.ECParameters // { // Curve = System.Security.Cryptography.ECCurve.NamedCurves.nistP256, // D = prikey, // Q = new System.Security.Cryptography.ECPoint // { // X = pubkey.Take(32).ToArray(), // Y = pubkey.Skip(32).ToArray() // } // })) //#endif { return(ecdsa.SignData(message, System.Security.Cryptography.HashAlgorithmName.SHA256)); } }
public ECDSASigner(string privateKey) //konstruktor do importowania klucza { this.privateKey = Base58CheckEncoding.DecodePlain(privateKey); CngPrivateKey = CngKey.Import(this.privateKey, CngKeyBlobFormat.EccPrivateBlob); ECDSA = new ECDsaCng(CngPrivateKey); ECDSA.HashAlgorithm = CngAlgorithm.Sha256; }
public static bool Verify(byte[] securedInput, byte[] signature, CngKey key, CngAlgorithm hash, int saltSize) { using (HashAlgorithm algo = HashAlgorithm(hash)) { return VerifyHash(algo.ComputeHash(securedInput),signature, key, hash.Algorithm, saltSize); } }
public static byte[] Sign(byte[] input, CngKey key, CngAlgorithm hash, int saltSize) { using (HashAlgorithm algo = HashAlgorithm(hash)) { return SignHash(algo.ComputeHash(input), key, hash.Algorithm, saltSize); } }
public static void CreateKey() { aliceKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256); bobKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256); alicePubKeyBlob = aliceKey.Export(CngKeyBlobFormat.EccPublicBlob); bobPubKeyBlob = bobKey.Export(CngKeyBlobFormat.EccPublicBlob); }
private bool IsSignatureValid(byte[] hash, byte[] signature, CngKey key) { using (var signingAlg = new RSACng(key)) { return signingAlg.VerifyHash(hash, signature, HashAlgorithmName.SHA384, RSASignaturePadding.Pss); } }
public static CngKey Duplicate(CngKey key) { using (SafeNCryptKeyHandle keyHandle = key.Handle) { return CngKey.Open(keyHandle, key.IsEphemeral ? CngKeyHandleOpenOptions.EphemeralKey : CngKeyHandleOpenOptions.None); } }
/// <summary> /// Initializes a new instance of the <see cref="CngCryptographicKey"/> class. /// </summary> /// <param name="key">The key.</param> /// <param name="eccPrivateKeyBlob">The ECC Private key blob from which this key was imported, if applicable.</param> internal CngCryptographicKey(CngKey key, byte[] eccPrivateKeyBlob) { Requires.NotNull(key, "key"); this.key = key; this.eccPrivateKeyBlob = eccPrivateKeyBlob.CloneArray(); }
internal ECDiffieHellmanCngPublicKey(CngKey key) : base(key.Export(CngKeyBlobFormat.EccPublicBlob)) { this.m_format = CngKeyBlobFormat.EccPublicBlob; new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); this.m_key = CngKey.Open(key.Handle, key.IsEphemeral ? CngKeyHandleOpenOptions.EphemeralKey : CngKeyHandleOpenOptions.None); CodeAccessPermission.RevertAssert(); }
private void CreateKeys() { _aliceKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP521); _bobKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP521); _alicePubKeyBlob = _aliceKey.Export(CngKeyBlobFormat.EccPublicBlob); _bobPubKeyBlob = _bobKey.Export(CngKeyBlobFormat.EccPublicBlob); }
private string Curve(CngKey key) { if (key.Algorithm == CngAlgorithm.ECDiffieHellmanP256) return "P-256"; if (key.Algorithm == CngAlgorithm.ECDiffieHellmanP384) return "P-384"; if (key.Algorithm == CngAlgorithm.ECDiffieHellmanP521) return "P-521"; throw new ArgumentException("Unknown curve type " + key.Algorithm); }
public override string ToXmlString() { if (this.m_key == null) { this.m_key = this.Import(); } return Rfc4050KeyFormatter.ToXml(this.m_key); }
public void WritePublicKey(CngKey cngKey) { var writer = GetWriterFor(cngKey.Algorithm); _stream.Write(Headerbytes, 0, Headerbytes.Count()); writer.Write(cngKey, _stream); _stream.Write(Footerbytes, 0, Footerbytes.Count()); }
private byte[] AddSignatureToHash(byte[] hash, CngKey key) { using (var signingAlg = new RSACng(key)) { byte[] signed = signingAlg.SignHash(hash, HashAlgorithmName.SHA384, RSASignaturePadding.Pss); return signed; } }
/// <summary> /// Exports a private key. /// </summary> /// <param name="Path">The path to export to.</param> /// <param name="PrivateKey">The key to export.</param> public static void ExportKey(string Path, CngKey PrivateKey) { using (BinaryWriter Writer = new BinaryWriter(File.Create(Path))) { Writer.Write((byte)PrivateKey.Export(CngKeyBlobFormat.EccPrivateBlob).Length); Writer.Write(PrivateKey.Export(CngKeyBlobFormat.EccPrivateBlob)); } }
/// <summary> /// Wrap an existing key handle with a CngKey object /// </summary> public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions) { if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (keyHandle.IsClosed || keyHandle.IsInvalid) throw new ArgumentException(SR.Cryptography_OpenInvalidHandle, "keyHandle"); SafeNCryptKeyHandle keyHandleCopy = keyHandle.Duplicate(); // Get a handle to the key's provider. SafeNCryptProviderHandle providerHandle = new SafeNCryptProviderHandle(); IntPtr rawProviderHandle = keyHandle.GetPropertyAsIntPtr(KeyPropertyName.ProviderHandle, CngPropertyOptions.None); providerHandle.SetHandleValue(rawProviderHandle); // Set up a key object wrapping the handle CngKey key = null; try { key = new CngKey(providerHandle, keyHandleCopy); bool openingEphemeralKey = (keyHandleOpenOptions & CngKeyHandleOpenOptions.EphemeralKey) == CngKeyHandleOpenOptions.EphemeralKey; // // If we're wrapping a handle to an ephemeral key, we need to make sure that IsEphemeral is // set up to return true. In the case that the handle is for an ephemeral key that was created // by the CLR, then we don't have anything to do as the IsEphemeral CLR property will already // be setup. However, if the key was created outside of the CLR we will need to setup our // ephemeral detection property. // // This enables consumers of CngKey objects to always be able to rely on the result of // calling IsEphemeral, and also allows them to safely access the Name property. // // Finally, if we detect that this is an ephemeral key that the CLR created but we were not // told that it was an ephemeral key we'll throw an exception. This prevents us from having // to decide who to believe -- the key property or the caller of the API. Since other code // relies on the ephemeral flag being set properly to avoid tripping over bugs in CNG, we // need to reject the case that we suspect that the flag is incorrect. // if (!key.IsEphemeral && openingEphemeralKey) { key.IsEphemeral = true; } else if (key.IsEphemeral && !openingEphemeralKey) { throw new ArgumentException(SR.Cryptography_OpenEphemeralKeyHandleWithoutEphemeralFlag, "keyHandleOpenOptions"); } } catch { // Make sure that we don't leak the handle the CngKey duplicated if (key != null) key.Dispose(); throw; } return key; }
/// <summary> /// Creates a new ECDsaCng object that will use the specified key. The key's /// <see cref="CngKey.AlgorithmGroup" /> must be ECDsa. This constructor /// creates a copy of the key. Hence, the caller can safely dispose of the /// passed in key and continue using the ECDsaCng object. /// </summary> /// <param name="key">Key to use for ECDsa operations</param> /// <exception cref="ArgumentException">if <paramref name="key" /> is not an ECDsa key</exception> /// <exception cref="ArgumentNullException">if <paramref name="key" /> is null.</exception> public ECDsaCng(CngKey key) { if (key == null) throw new ArgumentNullException("key"); if (key.AlgorithmGroup != CngAlgorithmGroup.ECDsa) throw new ArgumentException(SR.Cryptography_ArgECDsaRequiresECDsaKey, "key"); Key = CngAlgorithmCore.Duplicate(key); }
/// <summary> /// Creates a new DSACng object that will use the specified key. The key's /// <see cref="CngKey.AlgorithmGroup" /> must be Dsa. This constructor /// creates a copy of the key. Hence, the caller can safely dispose of the /// passed in key and continue using the DSACng object. /// </summary> /// <param name="key">Key to use for DSA operations</param> /// <exception cref="ArgumentException">if <paramref name="key" /> is not an DSA key</exception> /// <exception cref="ArgumentNullException">if <paramref name="key" /> is null.</exception> public DSACng(CngKey key) { if (key == null) throw new ArgumentNullException(nameof(key)); if (key.AlgorithmGroup != CngAlgorithmGroup.Dsa) throw new ArgumentException(SR.Cryptography_ArgDSARequiresDSAKey, nameof(key)); Key = CngAlgorithmCore.Duplicate(key); }
/// <summary> /// Creates a new ECDsaCng object that will use the specified key. The key's /// <see cref="CngKey.AlgorithmGroup" /> must be ECDsa. This constructor /// creates a copy of the key. Hence, the caller can safely dispose of the /// passed in key and continue using the ECDsaCng object. /// </summary> /// <param name="key">Key to use for ECDsa operations</param> /// <exception cref="ArgumentException">if <paramref name="key" /> is not an ECDsa key</exception> /// <exception cref="ArgumentNullException">if <paramref name="key" /> is null.</exception> public ECDsaCng(CngKey key) { if (key == null) throw new ArgumentNullException(nameof(key)); if (!IsEccAlgorithmGroup(key.AlgorithmGroup)) throw new ArgumentException(SR.Cryptography_ArgECDsaRequiresECDsaKey, nameof(key)); Key = CngAlgorithmCore.Duplicate(key); }
/// <summary> /// Creates a new RSACng object that will use the specified key. The key's /// <see cref="CngKey.AlgorithmGroup" /> must be Rsa. This constructor /// creates a copy of the key. Hence, the caller can safely dispose of the /// passed in key and continue using the RSACng object. /// </summary> /// <param name="key">Key to use for RSA operations</param> /// <exception cref="ArgumentException">if <paramref name="key" /> is not an RSA key</exception> /// <exception cref="ArgumentNullException">if <paramref name="key" /> is null.</exception> public RSACng(CngKey key) { if (key == null) throw new ArgumentNullException("key"); if (key.AlgorithmGroup != CngAlgorithmGroup.Rsa) throw new ArgumentException(SR.Cryptography_ArgRSAaRequiresRSAKey, "key"); _legalKeySizesValue = s_legalKeySizes; Key = CngAsymmetricAlgorithmCore.Duplicate(key); }
public RSACng(CngKey key) { if (key == null) throw new ArgumentNullException("key"); LegalKeySizesValue = s_legalKeySizes; new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); Key = CngKey.Open(key.Handle, key.IsEphemeral ? CngKeyHandleOpenOptions.EphemeralKey : CngKeyHandleOpenOptions.None); CodeAccessPermission.RevertAssert(); }
public static byte[] SignData(byte[] prikey, byte[] data) { var PublicKey = ThinNeo.Cryptography.ECC.ECCurve.Secp256r1.G * prikey; byte[] pubkey = PublicKey.EncodePoint(false).Skip(1).ToArray(); //签名的私钥 byte[] first = { 0x45, 0x43, 0x53, 0x32, 0x20, 0x00, 0x00, 0x00 }; byte[] signprikey = first.Concat(pubkey).Concat(prikey).ToArray(); using (System.Security.Cryptography.CngKey key = System.Security.Cryptography.CngKey.Import(signprikey, System.Security.Cryptography.CngKeyBlobFormat.EccPrivateBlob)) { using (System.Security.Cryptography.ECDsaCng ecdsa = new System.Security.Cryptography.ECDsaCng(key)) { var hashsrc = sha256.ComputeHash(data); var signdata = ecdsa.SignHash(hashsrc); return(signdata); } } }
/// <summary> /// Given a second party's public key, derive shared key material /// </summary> public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey) { Contract.Ensures(Contract.Result <byte[]>() != null); Contract.Assert(m_kdf >= ECDiffieHellmanKeyDerivationFunction.Hash && m_kdf <= ECDiffieHellmanKeyDerivationFunction.Tls); if (otherPartyPublicKey == null) { throw new ArgumentNullException("otherPartyPublicKey"); } // We can only work with ECDiffieHellmanCngPublicKeys ECDiffieHellmanCngPublicKey otherKey = otherPartyPublicKey as ECDiffieHellmanCngPublicKey; if (otherPartyPublicKey == null) { throw new ArgumentException(SR.GetString(SR.Cryptography_ArgExpectedECDiffieHellmanCngPublicKey)); } using (CngKey import = otherKey.Import()) { return(DeriveKeyMaterial(import)); } }
public static CngKey Create(CngAlgorithm algorithm, string keyName, CngKeyCreationParameters creationParameters) { if (algorithm == null) { throw new ArgumentNullException("algorithm"); } if (creationParameters == null) { creationParameters = new CngKeyCreationParameters(); } if (!NCryptNative.NCryptSupported) { throw new PlatformNotSupportedException(System.SR.GetString("Cryptography_PlatformNotSupported")); } if (keyName != null) { KeyContainerPermissionAccessEntry accessEntry = new KeyContainerPermissionAccessEntry(keyName, KeyContainerPermissionFlags.Create) { ProviderName = creationParameters.Provider.Provider }; KeyContainerPermission permission = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags); permission.AccessEntries.Add(accessEntry); permission.Demand(); } SafeNCryptProviderHandle provider = NCryptNative.OpenStorageProvider(creationParameters.Provider.Provider); SafeNCryptKeyHandle keyHandle = NCryptNative.CreatePersistedKey(provider, algorithm.Algorithm, keyName, creationParameters.KeyCreationOptions); SetKeyProperties(keyHandle, creationParameters); NCryptNative.FinalizeKey(keyHandle); CngKey key = new CngKey(provider, keyHandle); if (keyName == null) { key.IsEphemeral = true; } return(key); }
/// <summary> /// Constructs the core to use a stored CNG key. /// </summary> public CngSymmetricAlgorithmCore(ICngSymmetricAlgorithm outer, string keyName, CngProvider provider, CngKeyOpenOptions openOptions) { ArgumentNullException.ThrowIfNull(keyName); ArgumentNullException.ThrowIfNull(provider); _outer = outer; _keyName = keyName; _provider = provider; _optionOptions = openOptions; using (CngKey cngKey = ProduceCngKey()) { CngAlgorithm actualAlgorithm = cngKey.Algorithm; string algorithm = _outer.GetNCryptAlgorithmIdentifier(); if (algorithm != actualAlgorithm.Algorithm) { throw new CryptographicException(SR.Format(SR.Cryptography_CngKeyWrongAlgorithm, actualAlgorithm.Algorithm, algorithm)); } _outer.BaseKeySize = cngKey.KeySize; } }
/// <summary> /// Restore a key from XML /// </summary> internal static CngKey FromXml(string xml) { Contract.Requires(xml != null); Contract.Ensures(Contract.Result <CngKey>() != null); // Load the XML into an XPathNavigator to access sub elements using (TextReader textReader = new StringReader(xml)) using (XmlTextReader xmlReader = new XmlTextReader(textReader)) { XPathDocument document = new XPathDocument(xmlReader); XPathNavigator navigator = document.CreateNavigator(); // Move into the root element - we don't do a specific namespace check here for compatibility // with XML that Windows generates. if (!navigator.MoveToFirstChild()) { throw new ArgumentException(SR.GetString(SR.Cryptography_MissingDomainParameters)); } // First figure out which algorithm this key belongs to CngAlgorithm algorithm = ReadAlgorithm(navigator); // Then read out the public key value if (!navigator.MoveToNext(XPathNodeType.Element)) { throw new ArgumentException(SR.GetString(SR.Cryptography_MissingPublicKey)); } BigInteger x; BigInteger y; ReadPublicKey(navigator, out x, out y); // Finally, convert them into a key blob to import into a CngKey byte[] keyBlob = NCryptNative.BuildEccPublicBlob(algorithm.Algorithm, x, y); return(CngKey.Import(keyBlob, CngKeyBlobFormat.EccPublicBlob)); } }
/// <summary> /// Get a handle to the secret agreement generated between two parties /// </summary> public SafeNCryptSecretHandle DeriveSecretAgreementHandle(ECDiffieHellmanPublicKey otherPartyPublicKey) { if (otherPartyPublicKey == null) { throw new ArgumentNullException(nameof(otherPartyPublicKey)); } if (otherPartyPublicKey is ECDiffieHellmanCngPublicKey otherKey) { using (CngKey importedKey = otherKey.Import()) { return(DeriveSecretAgreementHandle(importedKey)); } } ECParameters otherPartyParameters = otherPartyPublicKey.ExportParameters(); using (ECDiffieHellmanCng otherPartyCng = (ECDiffieHellmanCng)Create(otherPartyParameters)) using (otherKey = (ECDiffieHellmanCngPublicKey)otherPartyCng.PublicKey) using (CngKey importedKey = otherKey.Import()) { return(DeriveSecretAgreementHandle(importedKey)); } }
public BasicSymmetricCipherLiteNCrypt( Func <CngKey> cngKeyFactory, CipherMode cipherMode, int blockSizeInBytes, ReadOnlySpan <byte> iv, bool encrypting, int paddingSizeInBytes) { BlockSizeInBytes = blockSizeInBytes; PaddingSizeInBytes = paddingSizeInBytes; _encrypting = encrypting; _key = cngKeyFactory(); CngProperty chainingModeProperty = cipherMode switch { CipherMode.ECB => s_ECBMode, CipherMode.CBC => s_CBCMode, CipherMode.CFB => s_CFBMode, _ => throw new CryptographicException(SR.Cryptography_InvalidCipherMode), }; _key.SetProperty(chainingModeProperty); Reset(iv); }
public void Dispose() { _key?.Dispose(); _key = null !; }
private CngKey GetKey( #if !NETNATIVE ECCurve?curve = null #endif ) { CngKey key = null; CngAlgorithm algorithm = null; int keySize = 0; #if !NETNATIVE if (curve != null) { if (curve.Value.IsNamed) { // Map curve name to algorithm to support pre-Win10 curves CngAlgorithm alg = CngKey.EcdsaCurveNameToAlgorithm(curve.Value.Oid.FriendlyName); if (CngKey.IsECNamedCurve(alg.Algorithm)) { key = _core.GetOrGenerateKey(curve.Value); } else { // 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); } key = _core.GetOrGenerateKey(keySize, alg); } ForceSetKeySize(key.KeySize); } else if (curve.Value.IsExplicit) { key = _core.GetOrGenerateKey(curve.Value); ForceSetKeySize(key.KeySize); } else { throw new PlatformNotSupportedException(string.Format(SR.Cryptography_CurveNotSupported, curve.Value.CurveType.ToString())); } } else if (_core.IsKeyGeneratedNamedCurve()) { key = _core.GetOrGenerateKey(null); } else #endif { // Map the current key size to a CNG algorithm name keySize = KeySize; switch (keySize) { case 256: algorithm = CngAlgorithm.ECDsaP256; break; case 384: algorithm = CngAlgorithm.ECDsaP384; break; case 521: algorithm = CngAlgorithm.ECDsaP521; break; default: Debug.Fail("Should not have invalid key size"); throw new ArgumentException(SR.Cryptography_InvalidKeySize); } key = _core.GetOrGenerateKey(keySize, algorithm); } return(key); }
public ECDiffieHellmanCng(CngKey key !!) { if (key.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman)
/// <summary> /// Wrap an existing key handle with a CngKey object /// </summary> public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions) { if (keyHandle == null) { throw new ArgumentNullException(nameof(keyHandle)); } if (keyHandle.IsClosed || keyHandle.IsInvalid) { throw new ArgumentException(SR.Cryptography_OpenInvalidHandle, nameof(keyHandle)); } SafeNCryptKeyHandle keyHandleCopy = keyHandle.Duplicate(); // Get a handle to the key's provider. SafeNCryptProviderHandle providerHandle = new SafeNCryptProviderHandle(); IntPtr rawProviderHandle = keyHandle.GetPropertyAsIntPtr(KeyPropertyName.ProviderHandle, CngPropertyOptions.None); providerHandle.SetHandleValue(rawProviderHandle); // Set up a key object wrapping the handle CngKey?key = null; try { key = new CngKey(providerHandle, keyHandleCopy); bool openingEphemeralKey = (keyHandleOpenOptions & CngKeyHandleOpenOptions.EphemeralKey) == CngKeyHandleOpenOptions.EphemeralKey; // // If we're wrapping a handle to an ephemeral key, we need to make sure that IsEphemeral is // set up to return true. In the case that the handle is for an ephemeral key that was created // by the CLR, then we don't have anything to do as the IsEphemeral CLR property will already // be setup. However, if the key was created outside of the CLR we will need to setup our // ephemeral detection property. // // This enables consumers of CngKey objects to always be able to rely on the result of // calling IsEphemeral, and also allows them to safely access the Name property. // // Finally, if we detect that this is an ephemeral key that the CLR created but we were not // told that it was an ephemeral key we'll throw an exception. This prevents us from having // to decide who to believe -- the key property or the caller of the API. Since other code // relies on the ephemeral flag being set properly to avoid tripping over bugs in CNG, we // need to reject the case that we suspect that the flag is incorrect. // if (!key.IsEphemeral && openingEphemeralKey) { key.IsEphemeral = true; } else if (key.IsEphemeral && !openingEphemeralKey) { throw new ArgumentException(SR.Cryptography_OpenEphemeralKeyHandleWithoutEphemeralFlag, nameof(keyHandleOpenOptions)); } } catch { // Make sure that we don't leak the handle the CngKey duplicated if (key != null) { key.Dispose(); } throw; } return(key); }
public SafeNCryptSecretHandle DeriveSecretAgreementHandle(CngKey otherPartyPublicKey) { throw new NotImplementedException(); }
internal static CngKey Import(byte[] keyBlob, ECCurve?curve, CngKeyBlobFormat format, CngProvider provider) { #endif //!NETNATIVE 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; ErrorCode errorCode; #if !NETNATIVE if (curve == null) #endif //!NETNATIVE { 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(); } } #if !NETNATIVE else { // Call with Oid.FriendlyName because .Value will result in an invalid parameter error Debug.Assert(curve.Value.IsNamed); string curveName = curve.Value.Oid.FriendlyName; using (SafeUnicodeStringHandle safeCurveName = new SafeUnicodeStringHandle(curveName)) { var desc = new Interop.BCrypt.BCryptBufferDesc(); var buff = new Interop.BCrypt.BCryptBuffer(); IntPtr descPtr = IntPtr.Zero; IntPtr buffPtr = IntPtr.Zero; try { descPtr = Marshal.AllocHGlobal(Marshal.SizeOf(desc)); buffPtr = Marshal.AllocHGlobal(Marshal.SizeOf(buff)); buff.cbBuffer = (curveName.Length + 1) * 2; // Add 1 for null terminator buff.BufferType = Interop.BCrypt.NCryptBufferDescriptors.NCRYPTBUFFER_ECC_CURVE_NAME; buff.pvBuffer = safeCurveName.DangerousGetHandle(); Marshal.StructureToPtr(buff, buffPtr, false); desc.cBuffers = 1; desc.pBuffers = buffPtr; desc.ulVersion = Interop.BCrypt.BCRYPTBUFFER_VERSION; Marshal.StructureToPtr(desc, descPtr, false); errorCode = Interop.NCrypt.NCryptImportKey(providerHandle, IntPtr.Zero, format.Format, descPtr, out keyHandle, keyBlob, keyBlob.Length, 0); } finally { Marshal.FreeHGlobal(descPtr); Marshal.FreeHGlobal(buffPtr); } } if (errorCode != ErrorCode.ERROR_SUCCESS) { Exception e = errorCode.ToCryptographicException(); if (errorCode == ErrorCode.NTE_INVALID_PARAMETER) { throw new PlatformNotSupportedException(string.Format(SR.Cryptography_CurveNotSupported, curveName), e); } throw e; } } #endif //!NETNATIVE 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 ECDsaCng(CngKey key) { Contract.Ensures(this.Key.AlgorithmGroup != null); Contract.Ensures(this.Key.AlgorithmGroup == System.Security.Cryptography.CngAlgorithmGroup.ECDsa); Contract.Ensures(this.LegalKeySizesValue != null); }
public byte[] DeriveKeyMaterial(CngKey otherPartyPublicKey) { if (otherPartyPublicKey == null) { throw new ArgumentNullException(nameof(otherPartyPublicKey)); } if (otherPartyPublicKey.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman) { throw new ArgumentException(SR.Cryptography_ArgECDHRequiresECDHKey, nameof(otherPartyPublicKey)); } if (otherPartyPublicKey.KeySize != KeySize) { throw new ArgumentException(SR.Cryptography_ArgECDHKeySizeMismatch, nameof(otherPartyPublicKey)); } // Setting the flag to UseSecretAsHmacKey even when the KDF isn't HMAC, because that's what NetFx does. Interop.NCrypt.SecretAgreementFlags flags = UseSecretAgreementAsHmacKey ? Interop.NCrypt.SecretAgreementFlags.UseSecretAsHmacKey : Interop.NCrypt.SecretAgreementFlags.None; using (SafeNCryptSecretHandle handle = DeriveSecretAgreementHandle(otherPartyPublicKey)) { switch (KeyDerivationFunction) { case ECDiffieHellmanKeyDerivationFunction.Hash: return(Interop.NCrypt.DeriveKeyMaterialHash( handle, HashAlgorithm.Algorithm, _secretPrepend, _secretAppend, flags)); case ECDiffieHellmanKeyDerivationFunction.Hmac: return(Interop.NCrypt.DeriveKeyMaterialHmac( handle, HashAlgorithm.Algorithm, _hmacKey, _secretPrepend, _secretAppend, flags)); case ECDiffieHellmanKeyDerivationFunction.Tls: if (_label == null || _seed == null) { throw new InvalidOperationException(SR.Cryptography_TlsRequiresLabelAndSeed); } return(Interop.NCrypt.DeriveKeyMaterialTls( handle, _label, _seed, flags)); default: Debug.Fail($"Unknown KDF ({KeyDerivationFunction})"); // Match NetFx behavior goto case ECDiffieHellmanKeyDerivationFunction.Tls; } } }
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(string.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(string.Format("Unknown algorithm {0}", alg.ToString())); 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(string.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(string.Format(SR.Cryptography_CurveNotSupported, target), e); } throw; } }
internal static byte[] ExportFullKeyBlob(CngKey key, bool includePrivateParameters) { CngKeyBlobFormat blobFormat = includePrivateParameters ? CngKeyBlobFormat.EccFullPrivateBlob : CngKeyBlobFormat.EccFullPublicBlob; return(key.Export(blobFormat)); }
public ECDsaCng(CngKey key !!) { if (!IsEccAlgorithmGroup(key.AlgorithmGroup))
public CngKey Import() { return(CngKey.Import(this.ToByteArray(), this.BlobFormat)); }
public Microsoft.Win32.SafeHandles.SafeNCryptSecretHandle DeriveSecretAgreementHandle(CngKey otherPartyPublicKey) { Contract.Ensures(this.Key.Handle != null); return(default(Microsoft.Win32.SafeHandles.SafeNCryptSecretHandle)); }
public DSACng(CngKey key !!) { if (key.AlgorithmGroup != CngAlgorithmGroup.Dsa)
public DSACng(System.Security.Cryptography.CngKey key) { }
public override void ImportParameters(RSAParameters parameters) { if (parameters.Exponent == null || parameters.Modulus == null) { throw new ArgumentException(SR.GetString(SR.Cryptography_InvalidRsaParameters)); } bool publicOnly = parameters.P == null || parameters.Q == null; // // We need to build a key blob structured as follows: // BCRYPT_RSAKEY_BLOB header // byte[cbPublicExp] publicExponent - Exponent // byte[cbModulus] modulus - Modulus // -- Private only -- // byte[cbPrime1] prime1 - P // byte[cbPrime2] prime2 - Q // int blobSize = Marshal.SizeOf(typeof(BCryptNative.BCRYPT_RSAKEY_BLOB)) + parameters.Exponent.Length + parameters.Modulus.Length; if (!publicOnly) { blobSize += parameters.P.Length + parameters.Q.Length; } byte[] rsaBlob = new byte[blobSize]; unsafe { fixed(byte *pRsaBlob = rsaBlob) { // Build the header BCryptNative.BCRYPT_RSAKEY_BLOB *pBcryptBlob = (BCryptNative.BCRYPT_RSAKEY_BLOB *)pRsaBlob; pBcryptBlob->Magic = publicOnly ? BCryptNative.KeyBlobMagicNumber.RsaPublic : BCryptNative.KeyBlobMagicNumber.RsaPrivate; pBcryptBlob->BitLength = parameters.Modulus.Length * 8; pBcryptBlob->cbPublicExp = parameters.Exponent.Length; pBcryptBlob->cbModulus = parameters.Modulus.Length; if (!publicOnly) { pBcryptBlob->cbPrime1 = parameters.P.Length; pBcryptBlob->cbPrime2 = parameters.Q.Length; } int offset = Marshal.SizeOf(typeof(BCryptNative.BCRYPT_RSAKEY_BLOB)); // Copy the exponent Buffer.BlockCopy(parameters.Exponent, 0, rsaBlob, offset, parameters.Exponent.Length); offset += parameters.Exponent.Length; // Copy the modulus Buffer.BlockCopy(parameters.Modulus, 0, rsaBlob, offset, parameters.Modulus.Length); offset += parameters.Modulus.Length; if (!publicOnly) { // Copy P Buffer.BlockCopy(parameters.P, 0, rsaBlob, offset, parameters.P.Length); offset += parameters.P.Length; // Copy Q Buffer.BlockCopy(parameters.Q, 0, rsaBlob, offset, parameters.Q.Length); offset += parameters.Q.Length; } } } Key = CngKey.Import(rsaBlob, publicOnly ? s_rsaPublicBlob : s_rsaPrivateBlob); }
public ECDsaCng(CngKey key) { throw new NotImplementedException(); }
public static CngKey Duplicate(CngKey key) { return(CngKey.Open(key.HandleNoDuplicate, key.IsEphemeral ? CngKeyHandleOpenOptions.EphemeralKey : CngKeyHandleOpenOptions.None)); }
internal static ECParameters ExportPrimeCurveParameters(CngKey key, bool includePrivateParameters) { byte[] ecBlob = ExportFullKeyBlob(key, 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 ECParameters ecParams = new ECParameters(); 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; return(ecParams); } } }
/// <summary> /// <para> /// ImportParameters will replace the existing key that RSACng is working with by creating a /// new CngKey for the parameters structure. If the parameters structure contains only an /// exponent and modulus, then only a public key will be imported. If the parameters also /// contain P and Q values, then a full key pair will be imported. /// </para> /// </summary> /// <exception cref="ArgumentException"> /// if <paramref name="parameters" /> contains neither an exponent nor a modulus. /// </exception> /// <exception cref="CryptographicException"> /// if <paramref name="parameters" /> is not a valid RSA key or if <paramref name="parameters" /// /> is a full key pair and the default KSP is used. /// </exception> public override void ImportParameters(RSAParameters parameters) { unsafe { if (parameters.Exponent == null || parameters.Modulus == null) { throw new CryptographicException(SR.Cryptography_InvalidRsaParameters); } bool includePrivate; if (parameters.D == null) { includePrivate = false; if (parameters.P != null || parameters.DP != null || parameters.Q != null || parameters.DQ != null || parameters.InverseQ != null) { throw new CryptographicException(SR.Cryptography_InvalidRsaParameters); } } else { includePrivate = true; if (parameters.P == null || parameters.DP == null || parameters.Q == null || parameters.DQ == null || parameters.InverseQ == null) { throw new CryptographicException(SR.Cryptography_InvalidRsaParameters); } } // // We need to build a key blob structured as follows: // // BCRYPT_RSAKEY_BLOB header // byte[cbPublicExp] publicExponent - Exponent // byte[cbModulus] modulus - Modulus // -- Only if "includePrivate" is true -- // byte[cbPrime1] prime1 - P // byte[cbPrime2] prime2 - Q // ------------------ // int blobSize = sizeof(BCRYPT_RSAKEY_BLOB) + parameters.Exponent.Length + parameters.Modulus.Length; if (includePrivate) { blobSize += parameters.P.Length + parameters.Q.Length; } byte[] rsaBlob = new byte[blobSize]; fixed(byte *pRsaBlob = rsaBlob) { // Build the header BCRYPT_RSAKEY_BLOB *pBcryptBlob = (BCRYPT_RSAKEY_BLOB *)pRsaBlob; pBcryptBlob->Magic = includePrivate ? KeyBlobMagicNumber.BCRYPT_RSAPRIVATE_MAGIC : KeyBlobMagicNumber.BCRYPT_RSAPUBLIC_MAGIC; pBcryptBlob->BitLength = parameters.Modulus.Length * 8; pBcryptBlob->cbPublicExp = parameters.Exponent.Length; pBcryptBlob->cbModulus = parameters.Modulus.Length; if (includePrivate) { pBcryptBlob->cbPrime1 = parameters.P.Length; pBcryptBlob->cbPrime2 = parameters.Q.Length; } int offset = sizeof(BCRYPT_RSAKEY_BLOB); Emit(rsaBlob, ref offset, parameters.Exponent); Emit(rsaBlob, ref offset, parameters.Modulus); if (includePrivate) { Emit(rsaBlob, ref offset, parameters.P); Emit(rsaBlob, ref offset, parameters.Q); } // We better have computed the right allocation size above! Debug.Assert(offset == blobSize, "offset == blobSize"); } CngKeyBlobFormat blobFormat = includePrivate ? s_rsaPrivateBlob : s_rsaPublicBlob; CngKey newKey = CngKey.Import(rsaBlob, blobFormat); newKey.ExportPolicy |= CngExportPolicies.AllowPlaintextExport; Key = newKey; } }
public byte[] DeriveKeyMaterial(CngKey otherPartyPublicKey) { Contract.Ensures(Contract.Result <byte[]>() != null); Contract.Assert(m_kdf >= ECDiffieHellmanKeyDerivationFunction.Hash && m_kdf <= ECDiffieHellmanKeyDerivationFunction.Tls); if (otherPartyPublicKey == null) { throw new ArgumentNullException("otherPartyPublicKey"); } if (otherPartyPublicKey.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman) { throw new ArgumentException(SR.GetString(SR.Cryptography_ArgECDHRequiresECDHKey), "otherPartyPublicKey"); } if (otherPartyPublicKey.KeySize != KeySize) { throw new ArgumentException(SR.GetString(SR.Cryptography_ArgECDHKeySizeMismatch), "otherPartyPublicKey"); } NCryptNative.SecretAgreementFlags flags = UseSecretAgreementAsHmacKey ? NCryptNative.SecretAgreementFlags.UseSecretAsHmacKey : NCryptNative.SecretAgreementFlags.None; // We require access to the handles for generating key material. This is safe since we will never // expose these handles to user code new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); // This looks horribly wrong - but accessing the handle property actually returns a duplicate handle, which // we need to dispose of - otherwise, we're stuck keepign the resource alive until the GC runs. This explicitly // is not disposing of the handle underlying the key dispite what the syntax looks like. using (SafeNCryptKeyHandle localKey = Key.Handle) using (SafeNCryptKeyHandle otherKey = otherPartyPublicKey.Handle) { CodeAccessPermission.RevertAssert(); // // Generating key material is a two phase process. // 1. Generate the secret agreement // 2. Pass the secret agreement through a KDF to get key material // using (SafeNCryptSecretHandle secretAgreement = NCryptNative.DeriveSecretAgreement(localKey, otherKey)) { if (KeyDerivationFunction == ECDiffieHellmanKeyDerivationFunction.Hash) { byte[] secretAppend = SecretAppend == null ? null : SecretAppend.Clone() as byte[]; byte[] secretPrepend = SecretPrepend == null ? null : SecretPrepend.Clone() as byte[]; return(NCryptNative.DeriveKeyMaterialHash(secretAgreement, HashAlgorithm.Algorithm, secretPrepend, secretAppend, flags)); } else if (KeyDerivationFunction == ECDiffieHellmanKeyDerivationFunction.Hmac) { byte[] hmacKey = HmacKey == null ? null : HmacKey.Clone() as byte[]; byte[] secretAppend = SecretAppend == null ? null : SecretAppend.Clone() as byte[]; byte[] secretPrepend = SecretPrepend == null ? null : SecretPrepend.Clone() as byte[]; return(NCryptNative.DeriveKeyMaterialHmac(secretAgreement, HashAlgorithm.Algorithm, hmacKey, secretPrepend, secretAppend, flags)); } else { Debug.Assert(KeyDerivationFunction == ECDiffieHellmanKeyDerivationFunction.Tls, "Unknown KDF"); byte[] label = Label == null ? null : Label.Clone() as byte[]; byte[] seed = Seed == null ? null : Seed.Clone() as byte[]; if (label == null || seed == null) { throw new InvalidOperationException(SR.GetString(SR.Cryptography_TlsRequiresLabelAndSeed)); } return(NCryptNative.DeriveKeyMaterialTls(secretAgreement, label, seed, flags)); } } } }