public void Decrypt(RecipientInfo recipientInfo, AsymmetricAlgorithm?privateKey) { if (recipientInfo == null) { throw new ArgumentNullException(nameof(recipientInfo)); } CheckStateForDecryption(); X509Certificate2Collection extraStore = new X509Certificate2Collection(); ContentInfo?contentInfo = _decryptorPal !.TryDecrypt( recipientInfo, null, privateKey, Certificates, extraStore, out Exception? exception); if (exception != null) { throw exception; } SetContentInfo(contentInfo !); }
public CmsSigner(SubjectIdentifierType signerIdentifierType, X509Certificate2?certificate, AsymmetricAlgorithm?privateKey) { switch (signerIdentifierType) { case SubjectIdentifierType.Unknown: _signerIdentifierType = SubjectIdentifierType.IssuerAndSerialNumber; IncludeOption = X509IncludeOption.ExcludeRoot; break; case SubjectIdentifierType.IssuerAndSerialNumber: _signerIdentifierType = signerIdentifierType; IncludeOption = X509IncludeOption.ExcludeRoot; break; case SubjectIdentifierType.SubjectKeyIdentifier: _signerIdentifierType = signerIdentifierType; IncludeOption = X509IncludeOption.ExcludeRoot; break; case SubjectIdentifierType.NoSignature: _signerIdentifierType = signerIdentifierType; IncludeOption = X509IncludeOption.None; break; default: _signerIdentifierType = SubjectIdentifierType.IssuerAndSerialNumber; IncludeOption = X509IncludeOption.ExcludeRoot; break; } Certificate = certificate; DigestAlgorithm = s_defaultAlgorithm.CopyOid(); PrivateKey = privateKey; }
/// <summary> /// Attempt to decrypt the CMS using the specified "cert". If successful, return the ContentInfo that contains the decrypted content. If unsuccessful, return null and set "exception" /// to a valid Exception object. Do not throw the exception as EnvelopedCms will want to continue decryption attempts against other recipients. Only if all the recipients fail to /// decrypt will then EnvelopedCms throw the exception from the last failed attempt. /// </summary> public abstract ContentInfo?TryDecrypt( RecipientInfo recipientInfo, X509Certificate2?cert, AsymmetricAlgorithm?privateKey, X509Certificate2Collection originatorCerts, X509Certificate2Collection extraStore, out Exception?exception);
/// <summary> /// Create a CertificateRequest for the specified subject name, RSA key, and hash algorithm. /// </summary> /// <param name="subjectName"> /// The parsed representation of the subject name for the certificate or certificate request. /// </param> /// <param name="key"> /// An RSA key whose public key material will be included in the certificate or certificate request. /// This key will be used as a private key if <see cref="CreateSelfSigned" /> is called. /// </param> /// <param name="hashAlgorithm"> /// The hash algorithm to use when signing the certificate or certificate request. /// </param> /// <param name="padding"> /// The RSA signature padding to apply if self-signing or being signed with an <see cref="X509Certificate2" />. /// </param> public CertificateRequest( X500DistinguishedName subjectName, RSA key, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { if (subjectName == null) { throw new ArgumentNullException(nameof(subjectName)); } if (key == null) { throw new ArgumentNullException(nameof(key)); } if (string.IsNullOrEmpty(hashAlgorithm.Name)) { throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); } if (padding == null) { throw new ArgumentNullException(nameof(padding)); } SubjectName = subjectName; _key = key; _generator = X509SignatureGenerator.CreateForRSA(key, padding); _rsaPadding = padding; PublicKey = _generator.PublicKey; HashAlgorithm = hashAlgorithm; }
public CmsSigner(ISigner signer, SigningPolicy signingPolicy, SubjectIdentifierType signerIdentifierType, X509Certificate2?certificate, AsymmetricAlgorithm?privateKey) { switch (signerIdentifierType) { case SubjectIdentifierType.Unknown: _signerIdentifierType = SubjectIdentifierType.IssuerAndSerialNumber; IncludeOption = X509IncludeOption.ExcludeRoot; break; case SubjectIdentifierType.IssuerAndSerialNumber: _signerIdentifierType = signerIdentifierType; IncludeOption = X509IncludeOption.ExcludeRoot; break; case SubjectIdentifierType.SubjectKeyIdentifier: _signerIdentifierType = signerIdentifierType; IncludeOption = X509IncludeOption.ExcludeRoot; break; case SubjectIdentifierType.NoSignature: _signerIdentifierType = signerIdentifierType; IncludeOption = X509IncludeOption.None; break; default: _signerIdentifierType = SubjectIdentifierType.IssuerAndSerialNumber; IncludeOption = X509IncludeOption.ExcludeRoot; break; } Certificate = certificate; PrivateKey = privateKey; _signer = signer; SigningPolicy = signingPolicy; }
public override unsafe ContentInfo?TryDecrypt( RecipientInfo recipientInfo, X509Certificate2?cert, AsymmetricAlgorithm?privateKey, X509Certificate2Collection originatorCerts, X509Certificate2Collection extraStore, out Exception?exception) { // When encryptedContent is null Windows seems to decrypt the CEK first, // then return a 0 byte answer. Debug.Assert((cert != null) ^ (privateKey != null)); if (recipientInfo.Pal is ManagedKeyTransPal ktri) { RSA?key = privateKey as RSA; if (privateKey != null && key == null) { exception = new CryptographicException(SR.Cryptography_Cms_Ktri_RSARequired); return(null); } byte[]? cek = ktri.DecryptCek(cert, key, out exception); // Pin CEK to prevent it from getting copied during heap compaction. fixed(byte *pinnedCek = cek) { try { if (exception != null) { return(null); } return(TryDecryptCore( cek !, _envelopedData.EncryptedContentInfo.ContentType, _envelopedData.EncryptedContentInfo.EncryptedContent, _envelopedData.EncryptedContentInfo.ContentEncryptionAlgorithm, out exception)); } finally { if (cek != null) { Array.Clear(cek, 0, cek.Length); } } } } else { exception = new CryptographicException( SR.Cryptography_Cms_RecipientType_NotSupported, recipientInfo.Type.ToString()); return(null); } }
/// <summary> /// Create a CertificateRequest for the specified subject name, ECDSA key, and hash algorithm. /// </summary> /// <param name="subjectName"> /// The parsed representation of the subject name for the certificate or certificate request. /// </param> /// <param name="key"> /// An ECDSA key whose public key material will be included in the certificate or certificate request. /// This key will be used as a private key if <see cref="CreateSelfSigned" /> is called. /// </param> /// <param name="hashAlgorithm"> /// The hash algorithm to use when signing the certificate or certificate request. /// </param> public CertificateRequest(X500DistinguishedName subjectName, ECDsa key, HashAlgorithmName hashAlgorithm) { ArgumentNullException.ThrowIfNull(subjectName); ArgumentNullException.ThrowIfNull(key); ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); SubjectName = subjectName; _key = key; _generator = X509SignatureGenerator.CreateForECDsa(key); PublicKey = _generator.PublicKey; HashAlgorithm = hashAlgorithm; }
public override void Reset() { _lazyRawData = null; _lazySignatureAlgorithm = null; _lazyVersion = 0; _lazySubjectName = null; _lazyIssuerName = null; _lazyPublicKey = null; _lazyPrivateKey = null; _lazyExtensions = null; base.Reset(); }
/// <summary> /// Create a CertificateRequest for the specified subject name, RSA key, and hash algorithm. /// </summary> /// <param name="subjectName"> /// The string representation of the subject name for the certificate or certificate request. /// </param> /// <param name="key"> /// An RSA key whose public key material will be included in the certificate or certificate request. /// This key will be used as a private key if <see cref="CreateSelfSigned" /> is called. /// </param> /// <param name="hashAlgorithm"> /// The hash algorithm to use when signing the certificate or certificate request. /// </param> /// <param name="padding"> /// The RSA signature padding to apply if self-signing or being signed with an <see cref="X509Certificate2" />. /// </param> /// <seealso cref="X500DistinguishedName(string)"/> public CertificateRequest(string subjectName, RSA key, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { ArgumentNullException.ThrowIfNull(subjectName); ArgumentNullException.ThrowIfNull(key); ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); ArgumentNullException.ThrowIfNull(padding); SubjectName = new X500DistinguishedName(subjectName); _key = key; _generator = X509SignatureGenerator.CreateForRSA(key, padding); _rsaPadding = padding; PublicKey = _generator.PublicKey; HashAlgorithm = hashAlgorithm; }
internal static SafeSecKeyRefHandle?GetPrivateKey(AsymmetricAlgorithm?key) { if (key == null) { return(null); } if (key is RSAImplementation.RSASecurityTransforms rsa) { return(rsa.GetKeys().PrivateKey); } if (key is DSAImplementation.DSASecurityTransforms dsa) { return(dsa.GetKeys().PrivateKey); } return(((ECDsaImplementation.ECDsaSecurityTransforms)key).GetKeys().PrivateKey); }
protected override byte[] ExportPkcs8( ICertificatePalCore certificatePal, ReadOnlySpan <char> password) { AsymmetricAlgorithm?alg = null; SafeEvpPKeyHandle? privateKey = ((OpenSslX509CertificateReader)certificatePal).PrivateKeyHandle; try { alg = new RSAOpenSsl(privateKey !); } catch (CryptographicException) { } if (alg == null) { try { alg = new ECDsaOpenSsl(privateKey !); } catch (CryptographicException) { } } if (alg == null) { try { alg = new DSAOpenSsl(privateKey !); } catch (CryptographicException) { } } Debug.Assert(alg != null); return(alg.ExportEncryptedPkcs8PrivateKey(password, s_windowsPbe)); }
/// <summary> /// Create a CertificateRequest for the specified subject name, ECDSA key, and hash algorithm. /// </summary> /// <param name="subjectName"> /// The string representation of the subject name for the certificate or certificate request. /// </param> /// <param name="key"> /// An ECDSA key whose public key material will be included in the certificate or certificate request. /// This key will be used as a private key if <see cref="CreateSelfSigned" /> is called. /// </param> /// <param name="hashAlgorithm"> /// The hash algorithm to use when signing the certificate or certificate request. /// </param> /// <seealso cref="X500DistinguishedName(string)"/> public CertificateRequest(string subjectName, ECDsa key, HashAlgorithmName hashAlgorithm) { if (subjectName == null) { throw new ArgumentNullException(nameof(subjectName)); } if (key == null) { throw new ArgumentNullException(nameof(key)); } if (string.IsNullOrEmpty(hashAlgorithm.Name)) { throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); } SubjectName = new X500DistinguishedName(subjectName); _key = key; _generator = X509SignatureGenerator.CreateForECDsa(key); PublicKey = _generator.PublicKey; HashAlgorithm = hashAlgorithm; }
private static AsymmetricAlgorithm GetPrivateKeyAlgorithm(X509Certificate2 cert, out PAL_KeyAlgorithm algorithm) { AsymmetricAlgorithm?key = cert.GetRSAPrivateKey(); if (key != null) { algorithm = PAL_KeyAlgorithm.RSA; return(key); } key = cert.GetECDsaPrivateKey(); if (key != null) { algorithm = PAL_KeyAlgorithm.EC; return(key); } key = cert.GetDSAPrivateKey(); if (key != null) { algorithm = PAL_KeyAlgorithm.DSA; return(key); } throw new NotSupportedException(SR.net_ssl_io_no_server_cert); }
internal static SafeSecKeyRefHandle?GetPrivateKey(AsymmetricAlgorithm?key) { if (key == null) { return(null); } if (key is RSAImplementation.RSASecurityTransforms rsa) { // Convert data key to legacy CSSM key that can be imported into keychain byte[] rsaPrivateKey = rsa.ExportRSAPrivateKey(); using (PinAndClear.Track(rsaPrivateKey)) { return(Interop.AppleCrypto.ImportEphemeralKey(rsaPrivateKey, true)); } } if (key is DSAImplementation.DSASecurityTransforms dsa) { // DSA always uses legacy CSSM keys do no need to convert return(dsa.GetKeys().PrivateKey); } if (key is ECDsaImplementation.ECDsaSecurityTransforms ecdsa) { // Convert data key to legacy CSSM key that can be imported into keychain byte[] ecdsaPrivateKey = ecdsa.ExportECPrivateKey(); using (PinAndClear.Track(ecdsaPrivateKey)) { return(Interop.AppleCrypto.ImportEphemeralKey(ecdsaPrivateKey, true)); } } Debug.Fail("Invalid key implementation"); return(null); }
/// <summary> /// Create a certificate using the established subject, key, and optional extensions using /// the provided certificate as the issuer. /// </summary> /// <param name="issuerCertificate"> /// An X509Certificate2 instance representing the issuing Certificate Authority (CA). /// </param> /// <param name="notBefore"> /// The oldest date and time where this certificate is considered valid. /// Typically <see cref="DateTimeOffset.UtcNow"/>, plus or minus a few seconds. /// </param> /// <param name="notAfter"> /// The date and time where this certificate is no longer considered valid. /// </param> /// <param name="serialNumber"> /// The serial number to use for the new certificate. This value should be unique per issuer. /// The value is interpreted as an unsigned (big) integer in big endian byte ordering. /// </param> /// <returns> /// An <see cref="X509Certificate2"/> with the specified values. The returned object will /// not assert <see cref="X509Certificate2.HasPrivateKey" />. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="issuerCertificate"/> is null.</exception> /// <exception cref="ArgumentException"> /// The <see cref="X509Certificate2.HasPrivateKey"/> value for <paramref name="issuerCertificate"/> is false. /// </exception> /// <exception cref="ArgumentException"> /// The type of signing key represented by <paramref name="issuerCertificate"/> could not be determined. /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="notAfter"/> represents a date and time before <paramref name="notBefore"/>. /// </exception> /// <exception cref="ArgumentException"><paramref name="serialNumber"/> has length 0.</exception> /// <exception cref="ArgumentException"> /// <paramref name="issuerCertificate"/> has a different key algorithm than the requested certificate. /// </exception> /// <exception cref="InvalidOperationException"> /// <paramref name="issuerCertificate"/> is an RSA certificate and this object was created via a constructor /// which does not accept a <see cref="RSASignaturePadding"/> value. /// </exception> public X509Certificate2 Create( X509Certificate2 issuerCertificate, DateTimeOffset notBefore, DateTimeOffset notAfter, ReadOnlySpan <byte> serialNumber) { if (issuerCertificate == null) { throw new ArgumentNullException(nameof(issuerCertificate)); } if (!issuerCertificate.HasPrivateKey) { throw new ArgumentException(SR.Cryptography_CertReq_IssuerRequiresPrivateKey, nameof(issuerCertificate)); } if (notAfter < notBefore) { throw new ArgumentException(SR.Cryptography_CertReq_DatesReversed); } if (serialNumber.IsEmpty) { throw new ArgumentException(SR.Arg_EmptyOrNullArray, nameof(serialNumber)); } if (issuerCertificate.PublicKey.Oid.Value != PublicKey.Oid.Value) { throw new ArgumentException( SR.Format( SR.Cryptography_CertReq_AlgorithmMustMatch, issuerCertificate.PublicKey.Oid.Value, PublicKey.Oid.Value), nameof(issuerCertificate)); } DateTime notBeforeLocal = notBefore.LocalDateTime; if (notBeforeLocal < issuerCertificate.NotBefore) { throw new ArgumentException( SR.Format( SR.Cryptography_CertReq_NotBeforeNotNested, notBeforeLocal, issuerCertificate.NotBefore), nameof(notBefore)); } DateTime notAfterLocal = notAfter.LocalDateTime; // Round down to the second, since that's the cert accuracy. // This makes one method which uses the same DateTimeOffset for chained notAfters // not need to do the rounding locally. long notAfterLocalTicks = notAfterLocal.Ticks; long fractionalSeconds = notAfterLocalTicks % TimeSpan.TicksPerSecond; notAfterLocalTicks -= fractionalSeconds; notAfterLocal = new DateTime(notAfterLocalTicks, notAfterLocal.Kind); if (notAfterLocal > issuerCertificate.NotAfter) { throw new ArgumentException( SR.Format( SR.Cryptography_CertReq_NotAfterNotNested, notAfterLocal, issuerCertificate.NotAfter), nameof(notAfter)); } // Check the Basic Constraints and Key Usage extensions to help identify inappropriate certificates. // Note that this is not a security check. The system library backing X509Chain will use these same criteria // to determine if a chain is valid; and a user can easily call the X509SignatureGenerator overload to // bypass this validation. We're simply helping them at signing time understand that they've // chosen the wrong cert. var basicConstraints = (X509BasicConstraintsExtension?)issuerCertificate.Extensions[Oids.BasicConstraints2]; var keyUsage = (X509KeyUsageExtension?)issuerCertificate.Extensions[Oids.KeyUsage]; if (basicConstraints == null) { throw new ArgumentException(SR.Cryptography_CertReq_BasicConstraintsRequired, nameof(issuerCertificate)); } if (!basicConstraints.CertificateAuthority) { throw new ArgumentException(SR.Cryptography_CertReq_IssuerBasicConstraintsInvalid, nameof(issuerCertificate)); } if (keyUsage != null && (keyUsage.KeyUsages & X509KeyUsageFlags.KeyCertSign) == 0) { throw new ArgumentException(SR.Cryptography_CertReq_IssuerKeyUsageInvalid, nameof(issuerCertificate)); } AsymmetricAlgorithm?key = null; string keyAlgorithm = issuerCertificate.GetKeyAlgorithm(); X509SignatureGenerator generator; try { switch (keyAlgorithm) { case Oids.Rsa: if (_rsaPadding == null) { throw new InvalidOperationException(SR.Cryptography_CertReq_RSAPaddingRequired); } RSA?rsa = issuerCertificate.GetRSAPrivateKey(); key = rsa; generator = X509SignatureGenerator.CreateForRSA(rsa !, _rsaPadding); break; case Oids.EcPublicKey: ECDsa?ecdsa = issuerCertificate.GetECDsaPrivateKey(); key = ecdsa; generator = X509SignatureGenerator.CreateForECDsa(ecdsa !); break; default: throw new ArgumentException( SR.Format(SR.Cryptography_UnknownKeyAlgorithm, keyAlgorithm), nameof(issuerCertificate)); } return(Create(issuerCertificate.SubjectName, generator, notBefore, notAfter, serialNumber)); } finally { key?.Dispose(); } }
/// <summary> /// Verifies the asymmetric signature of some data blob. /// </summary> /// <param name="signingPublicKey">The public key used to verify the signature.</param> /// <param name="data">The data that was signed.</param> /// <param name="signature">The signature.</param> /// <param name="signingAlgorithm">The signing algorithm.</param> /// <returns> /// A value indicating whether the signature is valid. /// </returns> internal static bool VerifySignatureWithTolerantHashAlgorithm(byte[] signingPublicKey, byte[] data, byte[] signature, AsymmetricAlgorithm? signingAlgorithm = null) { if (signingAlgorithm.HasValue) { var key = WinRTCrypto.AsymmetricKeyAlgorithmProvider.OpenAlgorithm(signingAlgorithm.Value) .ImportPublicKey(signingPublicKey, CryptoSettings.PublicKeyFormat); return WinRTCrypto.CryptographicEngine.VerifySignature(key, data, signature); } var key1 = WinRTCrypto.AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithm.RsaSignPkcs1Sha1) .ImportPublicKey(signingPublicKey, CryptoSettings.PublicKeyFormat); var key2 = WinRTCrypto.AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithm.RsaSignPkcs1Sha256) .ImportPublicKey(signingPublicKey, CryptoSettings.PublicKeyFormat); return WinRTCrypto.CryptographicEngine.VerifySignature(key1, data, signature) || WinRTCrypto.CryptographicEngine.VerifySignature(key2, data, signature); }
/// <summary> /// Downloads a <see cref="PayloadReference"/> that is referenced from an incoming inbox item. /// </summary> /// <param name="inboxItem">The inbox item that referenced the <see cref="PayloadReference"/>.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The task representing the asynchronous operation.</returns> protected virtual async Task <PayloadReference> DownloadPayloadReferenceAsync(IncomingList.IncomingItem inboxItem, CancellationToken cancellationToken) { Requires.NotNull(inboxItem, "inboxItem"); var responseMessage = await this.HttpClient.GetAsync(inboxItem.Location, cancellationToken).ConfigureAwait(false); if (responseMessage.StatusCode == HttpStatusCode.NotFound) { // delete inbox item and move on. await this.DeletePayloadReferenceAsync(inboxItem.Location, cancellationToken).ConfigureAwait(false); this.Log("Missing payload reference.", null); return(null); } responseMessage.EnsureSuccessStatusCode(); var responseStream = await responseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false); var responseStreamCopy = new MemoryStream(); await responseStream.CopyToAsync(responseStreamCopy, 4096, cancellationToken).ConfigureAwait(false); responseStreamCopy.Position = 0; var encryptedKey = await responseStreamCopy.ReadSizeAndBufferAsync(cancellationToken).ConfigureAwait(false); var key = WinRTCrypto.CryptographicEngine.Decrypt(this.Endpoint.EncryptionKey, encryptedKey); var iv = await responseStreamCopy.ReadSizeAndBufferAsync(cancellationToken).ConfigureAwait(false); var ciphertextStream = await responseStreamCopy.ReadSizeAndStreamAsync(cancellationToken).ConfigureAwait(false); var encryptedVariables = new SymmetricEncryptionVariables(key, iv); var plainTextPayloadStream = new MemoryStream(); await this.CryptoServices.DecryptAsync(ciphertextStream, plainTextPayloadStream, encryptedVariables, cancellationToken).ConfigureAwait(false); plainTextPayloadStream.Position = 0; AsymmetricAlgorithm?signingHashAlgorithm = null; //// Encoding.UTF8.GetString(await plainTextPayloadStream.ReadSizeAndBufferAsync(cancellationToken)); byte[] signature = await plainTextPayloadStream.ReadSizeAndBufferAsync(cancellationToken).ConfigureAwait(false); long payloadStartPosition = plainTextPayloadStream.Position; var signedBytes = new byte[plainTextPayloadStream.Length - plainTextPayloadStream.Position]; await plainTextPayloadStream.ReadAsync(signedBytes, 0, signedBytes.Length).ConfigureAwait(false); plainTextPayloadStream.Position = payloadStartPosition; var plainTextPayloadReader = new BinaryReader(plainTextPayloadStream); var recipientPublicSigningKeyBuffer = plainTextPayloadReader.ReadSizeAndBuffer(); var creationDateUtc = DateTime.FromBinary(plainTextPayloadReader.ReadInt64()); var notificationAuthor = Utilities.DeserializeDataContract <Endpoint>(plainTextPayloadReader); var messageReference = Utilities.DeserializeDataContract <PayloadReference>(plainTextPayloadReader); messageReference.ReferenceLocation = inboxItem.Location; if (messageReference.HashAlgorithmName == null) { messageReference.HashAlgorithmName = Utilities.GuessHashAlgorithmFromLength(messageReference.Hash.Length).GetHashAlgorithmName(); } if (!CryptoProviderExtensions.VerifySignatureWithTolerantHashAlgorithm(notificationAuthor.SigningKeyPublicMaterial, signedBytes, signature, signingHashAlgorithm)) { throw new InvalidMessageException(); } if (!Utilities.AreEquivalent(recipientPublicSigningKeyBuffer, this.Endpoint.PublicEndpoint.SigningKeyPublicMaterial)) { throw new InvalidMessageException(Strings.MisdirectedMessage); } return(messageReference); }
public sealed override unsafe ContentInfo?TryDecrypt( RecipientInfo recipientInfo, X509Certificate2?cert, AsymmetricAlgorithm?privateKey, X509Certificate2Collection originatorCerts, X509Certificate2Collection extraStore, out Exception?exception) { Debug.Assert((cert != null) ^ (privateKey != null)); if (privateKey != null) { RSA?key = privateKey as RSA; if (key == null) { exception = new CryptographicException(SR.Cryptography_Cms_Ktri_RSARequired); return(null); } ContentInfo contentInfo = _hCryptMsg.GetContentInfo(); byte[]? cek = AnyOS.ManagedPkcsPal.ManagedKeyTransPal.DecryptCekCore( cert, key, recipientInfo.EncryptedKey, recipientInfo.KeyEncryptionAlgorithm.Oid.Value, recipientInfo.KeyEncryptionAlgorithm.Parameters, out exception); // Pin CEK to prevent it from getting copied during heap compaction. fixed(byte *pinnedCek = cek) { try { if (exception != null) { return(null); } return(AnyOS.ManagedPkcsPal.ManagedDecryptorPal.TryDecryptCore( cek !, contentInfo.ContentType.Value !, contentInfo.Content, _contentEncryptionAlgorithm, out exception)); } finally { if (cek != null) { Array.Clear(cek, 0, cek.Length); } } } } Debug.Assert(recipientInfo != null); Debug.Assert(cert != null); Debug.Assert(originatorCerts != null); Debug.Assert(extraStore != null); CryptKeySpec keySpec; exception = TryGetKeySpecForCertificate(cert, out keySpec); if (exception != null) { return(null); } // .NET Framework compat: We pass false for "silent" here (thus allowing crypto providers to display UI.) const bool Silent = false; // Note: Using CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG rather than CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG // because wrapping an NCrypt wrapper over CAPI keys unconditionally causes some legacy features // (such as RC4 support) to break. const bool PreferNCrypt = false; using (SafeProvOrNCryptKeyHandle? hKey = PkcsPalWindows.GetCertificatePrivateKey(cert, Silent, PreferNCrypt, out _, out exception)) { if (hKey == null) { return(null); } RecipientInfoType type = recipientInfo.Type; switch (type) { case RecipientInfoType.KeyTransport: exception = TryDecryptTrans((KeyTransRecipientInfo)recipientInfo, hKey, keySpec); break; case RecipientInfoType.KeyAgreement: exception = TryDecryptAgree((KeyAgreeRecipientInfo)recipientInfo, hKey, keySpec, originatorCerts, extraStore); break; default: // Since only the framework can construct RecipientInfo's, we're at fault if we get here. So it's okay to assert and throw rather than // returning to the caller. Debug.Fail($"Unexpected RecipientInfoType: {type}"); throw new NotSupportedException(); } if (exception != null) { return(null); } // If we got here, we successfully decrypted. Return the decrypted content. return(_hCryptMsg.GetContentInfo()); } }
private byte[] Build( X509Certificate2 issuerCertificate, BigInteger crlNumber, DateTimeOffset nextUpdate, DateTimeOffset thisUpdate, HashAlgorithmName hashAlgorithm, RSASignaturePadding?rsaSignaturePadding) { ArgumentNullException.ThrowIfNull(issuerCertificate); if (!issuerCertificate.HasPrivateKey) { throw new ArgumentException( SR.Cryptography_CertReq_IssuerRequiresPrivateKey, nameof(issuerCertificate)); } if (crlNumber < 0) { throw new ArgumentOutOfRangeException(nameof(crlNumber), SR.ArgumentOutOfRange_NeedNonNegNum); } if (nextUpdate <= thisUpdate) { throw new ArgumentException(SR.Cryptography_CRLBuilder_DatesReversed); } ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); // Check the Basic Constraints and Key Usage extensions to help identify inappropriate certificates. // Note that this is not a security check. The system library backing X509Chain will use these same criteria // to determine if the CRL is valid; and a user can easily call the X509SignatureGenerator overload to // bypass this validation. We're simply helping them at signing time understand that they've // chosen the wrong cert. var basicConstraints = (X509BasicConstraintsExtension?)issuerCertificate.Extensions[Oids.BasicConstraints2]; var keyUsage = (X509KeyUsageExtension?)issuerCertificate.Extensions[Oids.KeyUsage]; var subjectKeyIdentifier = (X509SubjectKeyIdentifierExtension?)issuerCertificate.Extensions[Oids.SubjectKeyIdentifier]; if (basicConstraints == null) { throw new ArgumentException( SR.Cryptography_CertReq_BasicConstraintsRequired, nameof(issuerCertificate)); } if (!basicConstraints.CertificateAuthority) { throw new ArgumentException( SR.Cryptography_CertReq_IssuerBasicConstraintsInvalid, nameof(issuerCertificate)); } if (keyUsage != null && (keyUsage.KeyUsages & X509KeyUsageFlags.CrlSign) == 0) { throw new ArgumentException( SR.Cryptography_CRLBuilder_IssuerKeyUsageInvalid, nameof(issuerCertificate)); } AsymmetricAlgorithm?key = null; string keyAlgorithm = issuerCertificate.GetKeyAlgorithm(); X509SignatureGenerator generator; try { switch (keyAlgorithm) { case Oids.Rsa: if (rsaSignaturePadding is null) { throw new ArgumentException(SR.Cryptography_CertReq_RSAPaddingRequired); } RSA?rsa = issuerCertificate.GetRSAPrivateKey(); key = rsa; generator = X509SignatureGenerator.CreateForRSA(rsa !, rsaSignaturePadding); break; case Oids.EcPublicKey: ECDsa?ecdsa = issuerCertificate.GetECDsaPrivateKey(); key = ecdsa; generator = X509SignatureGenerator.CreateForECDsa(ecdsa !); break; default: throw new ArgumentException( SR.Format(SR.Cryptography_UnknownKeyAlgorithm, keyAlgorithm), nameof(issuerCertificate)); } X509AuthorityKeyIdentifierExtension akid; if (subjectKeyIdentifier is not null) { akid = X509AuthorityKeyIdentifierExtension.CreateFromSubjectKeyIdentifier(subjectKeyIdentifier); } else { akid = X509AuthorityKeyIdentifierExtension.CreateFromIssuerNameAndSerialNumber( issuerCertificate.IssuerName, issuerCertificate.SerialNumberBytes.Span); } return(Build( issuerCertificate.SubjectName, generator, crlNumber, nextUpdate, thisUpdate, hashAlgorithm, akid)); } finally { key?.Dispose(); } }
public AppleCertificateExporter(ICertificatePalCore cert, AsymmetricAlgorithm privateKey) : base(cert) { _privateKey = privateKey; }