Ejemplo n.º 1
0
        /// <inheritdoc/>
        public object Create(string algorithm, params object[] args)
        {
            if (IsSupportedAlgorithm(algorithm, args))
            {
                if (algorithm.Equals("EdDSA", StringComparison.OrdinalIgnoreCase))
                {
                    var keyMaterial = args[0] as JsonWebKey;
                    if (keyMaterial != null)
                    {
                        //TODO: Probably should check a case where both are defined (or some other combinations).
                        AsymmetricKeyParameter?keyParameter = null;
                        if (keyMaterial.X != null)
                        {
                            var decodedPublicBytes = Base64UrlEncoder.DecodeBytes(keyMaterial.X);
                            keyParameter = new Ed25519PublicKeyParameters(decodedPublicBytes, 0);
                        }
                        else if (keyMaterial.D != null)
                        {
                            var decodedPrivateBytes = Base64UrlEncoder.DecodeBytes(keyMaterial.D);
                            keyParameter = new Ed25519PrivateKeyParameters(decodedPrivateBytes, 0);
                        }
                        else
                        {
                            throw new ArgumentException("Key material needs to be provided");
                        }

                        var securityKey = new BouncyCastleEdDsaSecurityKey(keyParameter, keyMaterial.Crv, this);
                        return(new BouncyCastleEdDsaSignatureProvider(securityKey, algorithm));
                    }

                    throw new ArgumentException($"The key material argument in position args[0] expected is \"{typeof(JsonWebKey)}\".");
                }
            }

            throw new NotSupportedException();
        }
Ejemplo n.º 2
0
        /// <summary>
        ///     Generates the certificate.
        /// </summary>
        /// <param name="subjectName">Name of the subject.</param>
        /// <param name="issuerName">Name of the issuer.</param>
        /// <param name="validFrom">The valid from.</param>
        /// <param name="validTo">The valid to.</param>
        /// <param name="keyStrength">The key strength.</param>
        /// <param name="signatureAlgorithm">The signature algorithm.</param>
        /// <param name="issuerPrivateKey">The issuer private key.</param>
        /// <param name="hostName">The host name</param>
        /// <returns>X509Certificate2 instance.</returns>
        /// <exception cref="PemException">Malformed sequence in RSA private key</exception>
        private static X509Certificate2 generateCertificate(string?hostName,
                                                            string subjectName,
                                                            string issuerName, DateTime validFrom,
                                                            DateTime validTo, int keyStrength       = 2048,
                                                            string signatureAlgorithm               = "SHA256WithRSA",
                                                            AsymmetricKeyParameter?issuerPrivateKey = null)
        {
            // Generating Random Numbers
            var randomGenerator = new CryptoApiRandomGenerator();
            var secureRandom    = new SecureRandom(randomGenerator);

            // The Certificate Generator
            var certificateGenerator = new X509V3CertificateGenerator();

            // Serial Number
            var serialNumber =
                BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), secureRandom);

            certificateGenerator.SetSerialNumber(serialNumber);

            // Issuer and Subject Name
            var subjectDn = new X509Name(subjectName);
            var issuerDn  = new X509Name(issuerName);

            certificateGenerator.SetIssuerDN(issuerDn);
            certificateGenerator.SetSubjectDN(subjectDn);

            certificateGenerator.SetNotBefore(validFrom);
            certificateGenerator.SetNotAfter(validTo);

            if (hostName != null)
            {
                // add subject alternative names
                var nameType = GeneralName.DnsName;
                if (IPAddress.TryParse(hostName, out _))
                {
                    nameType = GeneralName.IPAddress;
                }

                var subjectAlternativeNames = new Asn1Encodable[] { new GeneralName(nameType, hostName) };

                var subjectAlternativeNamesExtension = new DerSequence(subjectAlternativeNames);
                certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName.Id, false,
                                                  subjectAlternativeNamesExtension);
            }

            // Subject Public Key
            var keyGenerationParameters = new KeyGenerationParameters(secureRandom, keyStrength);
            var keyPairGenerator        = new RsaKeyPairGenerator();

            keyPairGenerator.Init(keyGenerationParameters);
            var subjectKeyPair = keyPairGenerator.GenerateKeyPair();

            certificateGenerator.SetPublicKey(subjectKeyPair.Public);

            // Set certificate intended purposes to only Server Authentication
            certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage.Id, false,
                                              new ExtendedKeyUsage(KeyPurposeID.IdKPServerAuth));
            if (issuerPrivateKey == null)
            {
                certificateGenerator.AddExtension(X509Extensions.BasicConstraints.Id, true, new BasicConstraints(true));
            }

            var signatureFactory = new Asn1SignatureFactory(signatureAlgorithm,
                                                            issuerPrivateKey ?? subjectKeyPair.Private, secureRandom);

            // Self-sign the certificate
            var certificate = certificateGenerator.Generate(signatureFactory);

            // Corresponding private key
            var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);

            var seq = (Asn1Sequence)Asn1Object.FromByteArray(privateKeyInfo.ParsePrivateKey().GetDerEncoded());

            if (seq.Count != 9)
            {
                throw new PemException("Malformed sequence in RSA private key");
            }

            var rsa       = RsaPrivateKeyStructure.GetInstance(seq);
            var rsaparams = new RsaPrivateCrtKeyParameters(rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent,
                                                           rsa.Prime1, rsa.Prime2, rsa.Exponent1,
                                                           rsa.Exponent2, rsa.Coefficient);

            // Set private key onto certificate instance
            var x509Certificate = withPrivateKey(certificate, rsaparams);

            if (!doNotSetFriendlyName)
            {
                try
                {
                    x509Certificate.FriendlyName = ProxyConstants.CNRemoverRegex.Replace(subjectName, string.Empty);
                }
                catch (PlatformNotSupportedException)
                {
                    doNotSetFriendlyName = true;
                }
            }

            return(x509Certificate);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Parse bytes to a usable certificate
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="friendlyName"></param>
        /// <param name="pk"></param>
        /// <returns></returns>
        private X509Certificate2Collection ParseCertificate(byte[] bytes, string friendlyName, AsymmetricKeyParameter?pk)
        {
            // Build pfx archive including any intermediates provided
            _log.Verbose("Parsing certificate from {bytes} bytes received", bytes.Length);
            var          text        = Encoding.UTF8.GetString(bytes);
            var          pfx         = new bc.Pkcs.Pkcs12Store();
            var          startIndex  = 0;
            const string startString = "-----BEGIN CERTIFICATE-----";
            const string endString   = "-----END CERTIFICATE-----";

            while (true)
            {
                startIndex = text.IndexOf(startString, startIndex);
                if (startIndex < 0)
                {
                    break;
                }
                var endIndex = text.IndexOf(endString, startIndex);
                if (endIndex < 0)
                {
                    break;
                }
                endIndex += endString.Length;
                var pem = text[startIndex..endIndex];
Ejemplo n.º 4
0
        public async Task <Target> Generate()
        {
            // Read CSR
            string csrString;

            if (string.IsNullOrEmpty(_options.CsrFile))
            {
                _log.Error("No CsrFile specified in options");
                return(new NullTarget());
            }
            try
            {
                csrString = File.ReadAllText(_options.CsrFile);
            }
            catch (Exception ex)
            {
                _log.Error(ex, "Unable to read CSR from {CsrFile}", _options.CsrFile);
                return(new NullTarget());
            }

            // Parse CSR
            List <Identifier> alternativeNames;
            Identifier        commonName;

            byte[] csrBytes;
            try
            {
                var pem = _pem.ParsePem <Pkcs10CertificationRequest>(csrString);
                if (pem == null)
                {
                    throw new Exception("Unable decode PEM bytes to Pkcs10CertificationRequest");
                }
                var info = pem.GetCertificationRequestInfo();
                csrBytes         = pem.GetEncoded();
                commonName       = ParseCn(info);
                alternativeNames = ParseSan(info).ToList();
                if (!alternativeNames.Contains(commonName))
                {
                    alternativeNames.Add(commonName);
                }
            }
            catch (Exception ex)
            {
                _log.Error(ex, "Unable to parse CSR");
                return(new NullTarget());
            }

            AsymmetricKeyParameter?pkBytes = null;

            if (!string.IsNullOrWhiteSpace(_options.PkFile))
            {
                // Read PK
                string pkString;
                try
                {
                    pkString = File.ReadAllText(_options.PkFile);
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Unable to read private key from {PkFile}", _options.PkFile);
                    return(new NullTarget());
                }

                // Parse PK
                try
                {
                    var keyPair = _pem.ParsePem <AsymmetricCipherKeyPair>(pkString);

                    pkBytes = keyPair != null ?
                              keyPair.Private :
                              _pem.ParsePem <AsymmetricKeyParameter>(pkString);

                    if (pkBytes == null)
                    {
                        throw new Exception("No private key found");
                    }
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Unable to parse private key");
                    return(new NullTarget());
                }
            }

            var ret = new Target($"[{nameof(Csr)}] {_options.CsrFile}",
                                 commonName,
                                 new List <TargetPart> {
                new TargetPart(alternativeNames)
            })
            {
                UserCsrBytes = csrBytes,
                PrivateKey   = pkBytes
            };

            return(ret);
        }
Ejemplo n.º 5
0
        public CertificateStore(ReadOnlySpan <byte> pkcs12, string?password = null)
        {
            password = password._NonNull();

            // 2019/8/15 to Fix the Linux .NET Core bug: https://github.com/dotnet/corefx/issues/30946
            ReadOnlyMemory <byte> pkcs12Normalized = CertificateUtil.NormalizePkcs12MemoryData(pkcs12, password);

            using (MemoryStream ms = new MemoryStream())
            {
                ms.Write(pkcs12Normalized.Span);
                ms._SeekToBegin();

                Pkcs12Store p12 = new Pkcs12Store(ms, password.ToCharArray());

                foreach (object?aliasObject in p12.Aliases)
                {
                    if (aliasObject != null)
                    {
                        string alias = (string)aliasObject;

                        if (alias._IsNullOrZeroLen() == false)
                        {
                            AsymmetricKeyParameter?privateKeyParam = null;

                            AsymmetricKeyEntry?key = p12.GetKey(alias);
                            if (key != null)
                            {
                                if (key.Key.IsPrivate == false)
                                {
                                    throw new ApplicationException("Key.IsPrivate == false");
                                }

                                privateKeyParam = key.Key;
                            }

                            X509CertificateEntry[] certs = p12.GetCertificateChain(alias);

                            List <Certificate> certList = new List <Certificate>();

                            if (certs != null)
                            {
                                foreach (X509CertificateEntry cert in certs)
                                {
                                    Certificate certObj = new Certificate(cert.Certificate);

                                    certList.Add(certObj);
                                }
                            }

                            if (certList.Count >= 1)
                            {
                                PrivKey?privateKey = null;

                                if (privateKeyParam != null)
                                {
                                    privateKey = new PrivKey(new AsymmetricCipherKeyPair(certList[0].PublicKey.PublicKeyData, privateKeyParam));
                                }
                                else
                                {
                                    throw new ApplicationException("No private key found.");
                                }

                                CertificateStoreContainer container = new CertificateStoreContainer(alias, certList.ToArray(), privateKey);

                                this.InternalContainers.Add(alias, container);
                            }
                        }
                    }
                }

                if (this.InternalContainers.Count == 0)
                {
                    throw new ApplicationException("There are no certificate aliases in the PKCS#12 file.");
                }
            }

            InitFields();
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Signs the signature file's content using the given certificate, and returns the RSA signature.
        /// </summary>
        /// <param name="signatureFileData">Content of the signature file to be signed</param>
        /// <param name="pemCertData">PEM data of the certificate and private key for signing</param>
        /// <returns>The RSA signature</returns>
        private byte[] GetSignature(byte[] signatureFileData, string pemCertData)
        {
            var(cert, privateKey) = LoadCertificate(pemCertData);

            var certStore = X509StoreFactory.Create("Certificate/Collection", new X509CollectionStoreParameters(new List <X509Certificate> {
                cert
            }));
            CmsSignedDataGenerator dataGen = new();

            dataGen.AddCertificates(certStore);
            dataGen.AddSigner(privateKey, cert, CmsSignedGenerator.EncryptionRsa, CmsSignedGenerator.DigestSha256);

            // Content is detached - i.e. not included in the signature block itself
            CmsProcessableByteArray detachedContent = new(signatureFileData);
            var signedContent = dataGen.Generate(detachedContent, false);

            // Get the signature in the proper ASN.1 structure for java to parse it properly.  Lots of trial and error
            var                 signerInfos            = signedContent.GetSignerInfos();
            var                 signer                 = signerInfos.GetSigners().Cast <SignerInformation>().First();
            SignerInfo          signerInfo             = signer.ToSignerInfo();
            Asn1EncodableVector digestAlgorithmsVector = new();

            digestAlgorithmsVector.Add(new AlgorithmIdentifier(new DerObjectIdentifier("2.16.840.1.101.3.4.2.1"), DerNull.Instance));
            ContentInfo         encapContentInfo = new(new DerObjectIdentifier("1.2.840.113549.1.7.1"), null);
            Asn1EncodableVector asnVector        = new()
            {
                X509CertificateStructure.GetInstance(Asn1Object.FromByteArray(cert.GetEncoded()))
            };
            Asn1EncodableVector signersVector = new() { signerInfo.ToAsn1Object() };
            SignedData          signedData    = new(new DerSet(digestAlgorithmsVector), encapContentInfo, new BerSet(asnVector), null, new DerSet(signersVector));
            ContentInfo         contentInfo   = new(new DerObjectIdentifier("1.2.840.113549.1.7.2"), signedData);

            return(contentInfo.GetDerEncoded());
        }

        /// <summary>
        /// Loads the certificate and private key from the given PEM data
        /// </summary>
        /// <param name="pemData"></param>
        /// <returns>The loaded certificate and private key</returns>
        /// <exception cref="System.Security.SecurityException">If the certificate or private key failed to load</exception>
        private (X509Certificate certificate, AsymmetricKeyParameter privateKey) LoadCertificate(string pemData)
        {
            X509Certificate?       cert       = null;
            AsymmetricKeyParameter?privateKey = null;

            using (var reader = new StringReader(pemData))
            {
                // Iterate through the PEM objects until we find the public or private key
                var    pemReader = new PemReader(reader);
                object pemObject;
                while ((pemObject = pemReader.ReadObject()) != null)
                {
                    cert ??= pemObject as X509Certificate;
                    privateKey ??= (pemObject as AsymmetricCipherKeyPair)?.Private;
                }
            }
            if (cert == null)
            {
                throw new System.Security.SecurityException("Certificate could not be loaded from PEM data.");
            }

            if (privateKey == null)
            {
                throw new System.Security.SecurityException("Private Key could not be loaded from PEM data.");
            }

            return(cert, privateKey);
        }