bc-csharp
bc-csharp copied to clipboard
Append externally generated signature into X509 certificate
I'm writing a certificate authority using the Bouncy Castle library. I have an external service that signs the TBS certificate. I need to join the TBS certificate, signature and algorithm identifier to form a certificate. Following is some sample code
var conf = new ECKeyGenerationParameters(SecObjectIdentifiers.SecP256r1, new SecureRandom());
var keyGen = new ECKeyPairGenerator("ECDSA");
keyGen.Init(conf);
AsymmetricCipherKeyPair keyPair = keyGen.GenerateKeyPair();
IDictionary<DerObjectIdentifier, string> subjectAttrs = new Dictionary<DerObjectIdentifier, string>();
IList subjectOrdering = new ArrayList();
var orgName = new DerObjectIdentifier("2.5.4.10");
subjectAttrs.Add(orgName, orgNameString);
subjectOrdering.Add(orgName);
var orgUnitName = new DerObjectIdentifier("2.5.4.11");
subjectAttrs.Add(orgUnitName, orgUnitNameString);
subjectOrdering.Add(orgUnitName);
var commonName = new DerObjectIdentifier("2.5.4.3");
subjectAttrs.Add(commonName, commonNameString);
subjectOrdering.Add(commonName);
var rootCertBytes = <load root cert bytes from external source>
X509CertificateParser parser = new X509CertificateParser();
X509Certificate rootCert = parser.ReadCertificate(rootCertBytes);
X509Name subject = new X509Name(subjectOrdering, (IDictionary)subjectAttrs);
V3TbsCertificateGenerator tbsGen = new V3TbsCertificateGenerator();
tbsGen.SetSubject(subject);
tbsGen.SetIssuer(rootCert.IssuerDN);
AlgorithmIdentifier sigAlgId = new AlgorithmIdentifier((DerObjectIdentifier)X9ObjectIdentifiers.ECDsaWithSha256, DerNull.Instance);
tbsGen.SetSignature(sigAlgId);
tbsGen.SetSubjectPublicKeyInfo(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public));
tbsGen.SetSerialNumber(new DerInteger(BigInteger.ValueOf(1)));
tbsGen.SetStartDate(new Time(new DateTime()));
tbsGen.SetEndDate(new Time(new DateTime()));
TbsCertificateStructure tbsCert = tbsGen.GenerateTbsCertificate();
byte[] tbsBytes = tbsCert.GetDerEncoded();
byte[] tbsDigest = DigestUtilities.CalculateDigest("SHA_256", tbsBytes);
byte[] signature =<gets tbsDigest signed by external service with private key of a cert using this API - https://docs.microsoft.com/en-us/rest/api/keyvault/sign/sign>
X509Certificate cert = new X509Certificate(
new X509CertificateStructure(tbsCert, sigAlgId, new DerBitString(signature)));
var stringWriter = new StringWriter();
Org.BouncyCastle.Utilities.IO.Pem.PemWriter pemWriter = new Org.BouncyCastle.Utilities.IO.Pem.PemWriter(stringWriter);
PemObjectGenerator pemObject = new PemObject("CERTIFICATE", cert.GetEncoded());
pemWriter.WriteObject(pemObject);
Console.WriteLine(stringWriter.ToString());
Console.WriteLine(cert.ToString());
When I verify with openssl tool against the issuer certificate, I get the error
error 7 at 0 depth lookup: certificate signature failure
error test-cert: verification failed
26452:error:0D07209B:asn1 encoding routines:ASN1_get_object:too long:crypto\asn1\asn1_lib.c:91:
26452:error:0D068066:asn1 encoding routines:asn1_check_tlen:bad object header:crypto\asn1\tasn_dec.c:1118:
26452:error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error:crypto\asn1\tasn_dec.c:290:Type=ECDSA_SIG
26452:error:0D0C5006:asn1 encoding routines:ASN1_item_verify:EVP lib:crypto\asn1\a_verify.c:170:
I checked that tbsDigest is 32B and the signature returned from external service is 64B. Can you help me understand why Im getting the error?