/// <summary> /// Create a self-signed certificate using the established subject, key, and optional /// extensions. /// </summary> /// <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> /// <returns> /// An <see cref="X509Certificate2"/> with the specified values. The returned object will /// assert <see cref="X509Certificate2.HasPrivateKey" />. /// </returns> /// <exception cref="ArgumentException"> /// <paramref name="notAfter"/> represents a date and time before <paramref name="notAfter"/>. /// </exception> /// <exception cref="InvalidOperationException"> /// A constructor was used which did not accept a signing key. /// </exception>> /// <exception cref="CryptographicException"> /// Other errors during the certificate creation process. /// </exception> public X509Certificate2 CreateSelfSigned(DateTimeOffset notBefore, DateTimeOffset notAfter) { if (notAfter < notBefore) { throw new ArgumentException(SR.Cryptography_CertReq_DatesReversed); } if (_key == null) { throw new InvalidOperationException(SR.Cryptography_CertReq_NoKeyProvided); } Debug.Assert(_generator != null); byte[] serialNumber = new byte[8]; RandomNumberGenerator.Fill(serialNumber); using (X509Certificate2 certificate = Create( SubjectName, _generator, notBefore, notAfter, serialNumber)) { RSA rsa = _key as RSA; if (rsa != null) { return(certificate.CopyWithPrivateKey(rsa)); } ECDsa ecdsa = _key as ECDsa; if (ecdsa != null) { return(certificate.CopyWithPrivateKey(ecdsa)); } Gost3410 gost3410 = _key as Gost3410; if (gost3410 != null) { return(certificate.CopyWithPrivateKey(gost3410)); } Gost3410_2012_256 gost3410_2012_256 = _key as Gost3410_2012_256; if (gost3410_2012_256 != null) { return(certificate.CopyWithPrivateKey(gost3410_2012_256)); } Gost3410_2012_512 gost3410_2012_512 = _key as Gost3410_2012_512; if (gost3410_2012_512 != null) { return(certificate.CopyWithPrivateKey(gost3410_2012_512)); } } Debug.Fail($"Key was of no known type: {_key?.GetType().FullName ?? "null"}"); throw new CryptographicException(); }
/// <summary> /// Export private key /// </summary> /// <param name="certificate"></param> /// <returns></returns> internal static X509Certificate2 CopyWithPrivateKey(this X509Certificate2 certificate, AsymmetricAlgorithm key) { if (key is RSA rsa) { return(certificate.CopyWithPrivateKey(rsa)); } if (key is ECDsa ecdsa) { return(certificate.CopyWithPrivateKey(ecdsa)); } return(null); }
private static X509Certificate2 SetEcDsaPrivateKey(X509Certificate2 cert, string privateKey) { string[] keyParts = privateKey.Split('-', StringSplitOptions.RemoveEmptyEntries); byte[] keyBytes = Convert.FromBase64String(keyParts[1]); ECDsa eccPrivateKey = ECDsa.Create(); if (eccPrivateKey == null) { throw new PlatformNotSupportedException("Unable to create ECDsa"); } switch (keyParts[0]) { case "BEGIN PRIVATE KEY": eccPrivateKey.ImportPkcs8PrivateKey(keyBytes, out _); break; case "BEGIN EC PRIVATE KEY": eccPrivateKey.ImportECPrivateKey(keyBytes, out _); break; default: throw new ArgumentException("Invalid PrivateKey String", nameof(privateKey)); } return(cert.CopyWithPrivateKey(eccPrivateKey).FixForWindows()); }
private static X509Certificate2 CreateSelfSignedCertificateBasedOnCertificateAuthorityPrivateKey(string subjectName, string issuerName, AsymmetricKeyParameter issuerPrivKey) { const int keyStrength = 2048; // Generating Random Numbers CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator(); SecureRandom random = new SecureRandom(randomGenerator); ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA512WITHRSA", issuerPrivKey, random); // The Certificate Generator X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator(); certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage.Id, true, new ExtendedKeyUsage(KeyPurposeID.IdKPServerAuth)); // Serial Number BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random); certificateGenerator.SetSerialNumber(serialNumber); // Issuer and Subject Name X509Name subjectDN = new X509Name("CN=" + subjectName); X509Name issuerDN = new X509Name("CN=" + issuerName); certificateGenerator.SetIssuerDN(issuerDN); certificateGenerator.SetSubjectDN(subjectDN); // Valid For DateTime notBefore = DateTime.UtcNow.Date; DateTime notAfter = notBefore.AddMonths(2); certificateGenerator.SetNotBefore(notBefore); certificateGenerator.SetNotAfter(notAfter); // Subject Public Key AsymmetricCipherKeyPair subjectKeyPair; var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength); var keyPairGenerator = new RsaKeyPairGenerator(); keyPairGenerator.Init(keyGenerationParameters); subjectKeyPair = keyPairGenerator.GenerateKeyPair(); certificateGenerator.SetPublicKey(subjectKeyPair.Public); // selfsign certificate X509Certificate certificate = certificateGenerator.Generate(signatureFactory); // merge into X509Certificate2 X509Certificate2 x509i = new X509Certificate2(DotNetUtilities.ToX509Certificate(certificate)); var rsa = DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)subjectKeyPair.Private); X509Certificate2 x509 = x509i.CopyWithPrivateKey(rsa); x509.FriendlyName = subjectName; return(x509); }
private static X509Certificate2 SetRsaPrivateKey(X509Certificate2 cert, string privateKey) { string[] keyParts = privateKey.Split('-', StringSplitOptions.RemoveEmptyEntries); byte[] keyBytes = Convert.FromBase64String(keyParts[1]); RSA rsaPrivateKey = RSA.Create(); switch (keyParts[0]) { case "BEGIN PRIVATE KEY": rsaPrivateKey.ImportPkcs8PrivateKey(keyBytes, out _); break; case "BEGIN RSA PRIVATE KEY": rsaPrivateKey.ImportRSAPrivateKey(keyBytes, out _); break; default: throw new ArgumentException("Invalid PrivateKey String", nameof(privateKey)); } return(cert.CopyWithPrivateKey(rsaPrivateKey).FixForWindows()); }