Esempio n. 1
0
        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 !);
        }
Esempio n. 2
0
        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;
        }
Esempio n. 3
0
 /// <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;
        }
Esempio n. 5
0
        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;
        }
Esempio n. 6
0
            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);
                }
            }
Esempio n. 7
0
        /// <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();
        }
Esempio n. 9
0
        /// <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;
        }
Esempio n. 10
0
        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);
        }
Esempio n. 11
0
        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;
        }
Esempio n. 13
0
        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);
        }
Esempio n. 14
0
        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);
        }
Esempio n. 17
0
        /// <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();
            }
        }
Esempio n. 20
0
 public AppleCertificateExporter(ICertificatePalCore cert, AsymmetricAlgorithm privateKey)
     : base(cert)
 {
     _privateKey = privateKey;
 }