bc-csharp icon indicating copy to clipboard operation
bc-csharp copied to clipboard

Append externally generated signature into X509 certificate

Open jefjos opened this issue 5 years ago • 0 comments

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?

jefjos avatar Jun 21 '20 18:06 jefjos