If you have Root.key and Root.pfx file and you would like to create new PFX file, below is the solution.
I have used.
- .NET Core 6.0 with Visual Studio 2022 Ver 17.4.3
- "Portable.BouncyCastle" Version 1.9.0 from Nuget
- "Microsoft.Extensions.Configuration" Version 7.0.0 from Nuget
Here the working solution, use in your class and use it
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.X509;
using System.Security.Cryptography.X509Certificates;
{
string
RootKeyFilePath = @"C:\Test\RootFile.key";
string
RootPfxFilePath = @"C:\Test\RootFile.pfx";
string pass = "Pass123#";
string newPFXFileName
= @"C:\Test\NewCertificate.pfx";
string subject = "E=test@test.com,
CN=Test Name, OU=ORG, O=LSGS, L=Orlando, ST=MN,C=US";
try
{
using var reader =
File.OpenText(RootKeyFilePath);
AsymmetricKeyParameter? myCAprivateKey
= ((AsymmetricCipherKeyPair)new
Org.BouncyCastle.OpenSsl.PemReader(reader).ReadObject())?.Private;
X509Certificate2
MyCert = GenerateSelfSignedCertificate(subject, certificate.Issuer.Replace("S=","ST="),
myCAprivateKey, pass);
byte[] certData =
MyCert.Export(X509ContentType.Pfx, pass);
File.WriteAllBytes(newPFXFileName,
certData);
}
catch (Exception exc){Console.WriteLine(exc.Message);}
public
X509Certificate2 GenerateSelfSignedCertificate(string subjectName, string issuerName,
AsymmetricKeyParameter? issuerPrivKey, string pass)
{
const int keyStrength =
2048;
CryptoApiRandomGenerator
randomGenerator = new CryptoApiRandomGenerator();
SecureRandom
random = new SecureRandom(randomGenerator);
X509V3CertificateGenerator certificateGenerator = new
X509V3CertificateGenerator();
BigInteger
serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One,
BigInteger.ValueOf(Int64.MaxValue), random);
certificateGenerator.SetSerialNumber(serialNumber);
// Signature Algorithm
const string
signatureAlgorithm = "SHA256WithRSA";
certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);
// Issuer and Subject Name
X509Name
subjectDN = new X509Name(subjectName);
X509Name
issuerDN = new X509Name(issuerName);
certificateGenerator.SetIssuerDN(issuerDN);
certificateGenerator.SetSubjectDN(subjectDN);
// Valid For
DateTime
notBefore = DateTime.UtcNow.Date;
DateTime
notAfter = notBefore.AddYears(10);
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);
// Generating the Certificate
AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;
// selfsign certificate
Org.BouncyCastle.X509.X509Certificate
certificate = certificateGenerator.Generate(issuerPrivKey, random);
// correcponding private key
PrivateKeyInfo
info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);
// merge into X509Certificate2
X509Certificate2
x509 = new
System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded(), pass,
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet |
X509KeyStorageFlags.Exportable);
//Asn1Sequence
seq =(Asn1Sequence)Asn1Object.FromStream(info.PrivateKeyData.GetDerEncoded());
Asn1Sequence seq
=(Asn1Sequence)Asn1Object.FromStream(info.PrivateKeyData.GetOctetStream());
{
//throw new
PemException("malformed sequence in RSA private key");
}
RsaPrivateKeyStructure rsa = new RsaPrivateKeyStructure(seq);
RsaPrivateCrtKeyParameters rsaparams = new RsaPrivateCrtKeyParameters(
rsa.Modulus,
rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1,
rsa.Exponent2, rsa.Coefficient);
//x509.PrivateKey
= DotNetUtilities.ToRSA(rsaparams);
//use this one
var rsa1 = DotNetUtilities.ToRSA(rsaparams);
var cert = x509.CopyWithPrivateKey(rsa1);
return cert;
}
Troubleshoots-1
subject should have all correct object , if you pass wrong object then will get error
Error: "Unknown object id - S - passed to distinguished name"
like: string subject = "E=test@test.com, CN=Test Name, OU=ORG, O=LSGS, L=Orlando, S=MN,C=US";
Ref: for all correct object to be used see here Distinguished Names | Microsoft Learn
Troubleshoots-2
If you are typing wrong password for key certificate, you will get following error