Пример #1
0
        internal static bool CanProduceSha1Signature(AsymmetricAlgorithm algorithm)
        {
#if NETFRAMEWORK
            algorithm.Dispose();
            return(true);
#else
            // We expect all non-Linux platforms to support SHA1 signatures, currently.
            if (!OperatingSystem.IsLinux())
            {
                return(true);
            }

            switch (algorithm)
            {
            case ECDsa ecdsa:
                try
                {
                    ecdsa.SignData(Array.Empty <byte>(), HashAlgorithmName.SHA1);
                    return(true);
                }
                catch (CryptographicException)
                {
                    return(false);
                }
                finally
                {
                    algorithm.Dispose();
                }

            case RSA rsa:
                try
                {
                    rsa.SignData(Array.Empty <byte>(), HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
                    return(true);
                }
                catch (CryptographicException)
                {
                    return(false);
                }
                finally
                {
                    algorithm.Dispose();
                }

            default:
                throw new NotSupportedException($"Algorithm type {algorithm.GetType()} is not supported.");
            }
#endif
        }
        static Boolean deleteLegacyKey(AsymmetricAlgorithm privateKey)
        {
            if (privateKey == null)
            {
                return(false);
            }
            String keyContainer;
            String provName;
            UInt32 provType;

            switch (privateKey)
            {
            case RSACryptoServiceProvider rsaProv:
                keyContainer = rsaProv.CspKeyContainerInfo.KeyContainerName;
                provName     = rsaProv.CspKeyContainerInfo.ProviderName;
                provType     = (UInt32)rsaProv.CspKeyContainerInfo.ProviderType;
                break;

            case DSACryptoServiceProvider dsaProv:
                keyContainer = dsaProv.CspKeyContainerInfo.KeyContainerName;
                provName     = dsaProv.CspKeyContainerInfo.ProviderName;
                provType     = (UInt32)dsaProv.CspKeyContainerInfo.ProviderType;
                break;

            default:
                privateKey.Dispose();
                return(false);
            }
            IntPtr  phProv  = IntPtr.Zero;
            Boolean status2 = false;
            Boolean status1 = AdvAPI.CryptAcquireContext(
                ref phProv,
                keyContainer,
                provName,
                provType,
                Wincrypt.CRYPT_DELETEKEYSET | nCrypt2.NCRYPT_MACHINE_KEY_FLAG);

            if (!status1)
            {
                status2 = AdvAPI.CryptAcquireContext(
                    ref phProv,
                    keyContainer,
                    provName,
                    provType,
                    Wincrypt.CRYPT_DELETEKEYSET);
            }
            privateKey.Dispose();
            return(status1 || status2);
        }
Пример #3
0
 public void Dispose()
 {
     if (_disposeCryptoProvider && _signingKey != null)
     {
         _signingKey.Dispose();
     }
 }
Пример #4
0
        /// <summary>
        /// Create self signed cert
        /// </summary>
        /// <param name="signature"></param>
        /// <param name="subject"></param>
        /// <returns></returns>
        internal static AsymmetricAlgorithm CreateCsr(this SignatureType signature, string subject,
                                                      out CertificateRequest csr)
        {
            AsymmetricAlgorithm alg = null;

            try {
                if (signature.IsRSA())
                {
                    var rsa = RSA.Create();
                    alg = rsa;
                    csr = new CertificateRequest(X500DistinguishedNameEx.Create(subject),
                                                 rsa, signature.ToHashAlgorithmName(), signature.ToRSASignaturePadding());
                    return(alg);
                }
                if (signature.IsECC())
                {
                    var ecdsa = ECDsa.Create();
                    alg = ecdsa;
                    csr = new CertificateRequest(X500DistinguishedNameEx.Create(subject),
                                                 ecdsa, signature.ToHashAlgorithmName());
                    return(alg);
                }
                throw new ArgumentException("Bad signature");
            }
            catch {
                alg?.Dispose();
                throw;
            }
        }
 private void Dispose(bool Disposing)
 {
     if (!_disposed)
     {
         _asymAlgo.Dispose();
         _disposed = true;
     }
 }
Пример #6
0
        /// <summary>
        /// Performs the actual job of disposing the object.
        /// </summary>
        /// <param name="disposing">
        /// Passes the information whether this method is called by <see cref="IDisposable.Dispose()"/> (explicitly or
        /// implicitly at the end of a <c>using</c> statement), or by the <see cref="M:~Signer()"/>.
        /// </param>
        /// <remarks>
        /// If the method is called with <paramref name="disposing"/><c>==true</c>, i.e. from <see cref="IDisposable.Dispose()"/>, it will try to release all managed resources
        /// (usually aggregated objects which implement <see cref="IDisposable"/> as well) and then it will release all unmanaged resources if any.
        /// If the parameter is <c>false</c> then the method will only try to release the unmanaged resources.
        /// </remarks>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _asymmetric.Dispose();
            }

            base.Dispose(disposing);
        }
Пример #7
0
        /// <summary>
        /// Performs the actual job of disposing the object.
        /// </summary>
        /// <param name="disposing">
        /// Passes the information whether this method is called by <see cref="Dispose()"/> (explicitly or
        /// implicitly at the end of a <c>using</c> statement), or by the <see cref="M:~RsaXmlSigner"/>.
        /// </param>
        /// <remarks>
        /// If the method is called with <paramref name="disposing"/><c>==true</c>, i.e. from <see cref="Dispose()"/>,
        /// it will try to release all managed resources (usually aggregated objects which implement <see cref="IDisposable"/> as well)
        /// and then it will release all unmanaged resources if any. If the parameter is <c>false</c> then
        /// the method will only try to release the unmanaged resources.
        /// </remarks>
        protected virtual void Dispose(bool disposing)
        {
            // if it is disposed or in a process of disposing - return.
            if (Interlocked.Exchange(ref _disposed, 1) != 0)
            {
                return;
            }

            if (disposing)
            {
                _asymmetric.Dispose();
            }
        }
Пример #8
0
        /// <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"/> is null or has length 0.</exception>
        public X509Certificate2 Create(
            X509Certificate2 issuerCertificate,
            DateTimeOffset notBefore,
            DateTimeOffset notAfter,
            byte[] serialNumber)
        {
            if (issuerCertificate == null)
            {
                throw new ArgumentNullException(nameof(issuerCertificate));
            }
            if (!issuerCertificate.HasPrivateKey)
            {
                throw new ArgumentException(SR.Cryptography_CertReq_IssuerRequiresPrivateKey, nameof(issuerCertificate));
            }

            AsymmetricAlgorithm key = null;
            string keyAlgorithm     = issuerCertificate.GetKeyAlgorithm();
            X509SignatureGenerator generator;

            try
            {
                switch (keyAlgorithm)
                {
                case Oids.RsaRsa:
                    RSA rsa = issuerCertificate.GetRSAPrivateKey();
                    key       = rsa;
                    generator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1);
                    break;

                case Oids.Ecc:
                    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();
            }
        }
        private void Dispose(bool disposing)
        {
            if (_disposed)
            {
                return;
            }

            if (disposing)
            {
                if (_asymAlgo != null)
                {
                    _asymAlgo.Dispose();
                }
            }

            _disposed = true;
        }
Пример #10
0
 void releaseUnmanagedResources()
 {
     // dispose public key handle
     phPubKey.Dispose();
     if (isCng)
     {
         // dispose CNG private key handle
         phPrivKey.Dispose();
     }
     else
     {
         // dispose legacy private CSP key
         legacyKey?.Dispose();
         legacyKey = null;
     }
     //TODO: Crypt32.CertFreeCertificateContext(SignerCertificate.Handle);
     SignerCertificate = null;
     disposed          = true;
 }
Пример #11
0
        public void TearDown()
        {
            try
            {
                _publicKey.Dispose();
            }
            finally
            {
                _publicKey = null;
            }

            try
            {
                _privateKey.Dispose();
            }
            finally
            {
                _privateKey = null;
            }
        }
Пример #12
0
        protected bool VerifyWithClientCertificate(byte[] data, byte[] signature, SignatureAlgorithm signatureAlgorithm)
        {
            AsymmetricAlgorithm asymmetric = null;
            var cert = _clientCertificates.First();

            if (cert.PublicKey.Oid.FriendlyName == "RSA")
            {
                asymmetric = cert.GetRSAPublicKey();
            }
            else if (cert.PublicKey.Oid.FriendlyName == "ECC")
            {
                asymmetric = cert.GetECDsaPublicKey();
            }
            else
            {
                throw new NotSupportedException($"Client Certificate Type {cert.PublicKey.Oid.FriendlyName} NotSupported");
            }
            var verified = _params.Cipher.SignatureVerify(data, signature, signatureAlgorithm, asymmetric);

            asymmetric.Dispose();
            return(verified);
        }
Пример #13
0
        protected byte[] MakeSignatureWithCertificate(byte[] signdata)
        {
            AsymmetricAlgorithm asymmetric = null;

            using (var cert = new X509Certificate2(_prvkeyfile))
            {
                if (cert.PublicKey.Oid.FriendlyName == "RSA")
                {
                    asymmetric = cert.GetRSAPrivateKey();
                }
                else if (cert.PublicKey.Oid.FriendlyName == "ECC")
                {
                    asymmetric = cert.GetECDsaPrivateKey();
                }
                else
                {
                    throw new NotSupportedException($"Server Certificate Type {cert.PublicKey.Oid.FriendlyName} NotSupported");
                }
            }
            var signature = _params.Cipher.Signature(signdata, _params.SignatureAlgorithm, asymmetric);

            asymmetric.Dispose();
            return(signature);
        }
        /// <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();
            }
        }
        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();
            }
        }