javabouncycastlepkicmp

how to sign a cmp request message correctly? (java, bouncy castle)


I try to revoke certificates over cmp (certificate management protocol) at a certificate authority (the cmp server) and getting the error code "invalid signature key code". I think its becouse of the way i sign the cmp message, something went wrong there.

I build the header with org.bouncycastle.asn1.cmp.PKIHeaderBuilder and the body with org.bouncycastle.asn1.crmf.CertTemplateBuilder:

CertTemplateBuilder builderCer = new CertTemplateBuilder();

// cert to revoke
builderCer.setIssuer(issuer);            
builderCer.setSerialNumber(serial);

//body
ArrayList revDetailsList = new ArrayList();
revDetailsList.add(new RevDetails(builderCer.build()));
RevReqContent revReqContent = new RevReqContent((RevDetails[]) revDetailsList.toArray(new RevDetails[revDetailsList.size()]));
PKIBody body = new PKIBody(PKIBody.TYPE_REVOCATION_REQ, revReqContent); 

// header
X509Name recipient  = new X509Name("CN=recipient");
X509Name sender = new X509Name("CN=sender");
int pvno = 1;
PKIHeaderBuilder builderHeader = new PKIHeaderBuilder(pvno, new GeneralName(sender), new GeneralName(recipient));
AlgorithmIdentifier algId = new AlgorithmIdentifier(new ASN1ObjectIdentifier("1.2.840.10045.4.1"));
builderHeader.setProtectionAlg(algId);
PKIHeader header = builderHeader.build();

Then i have to sign the whole message and there seems to be different ways for it. In extracerts (CMPCertificate) i have to add the public key of the signature, the signature have to be verifiable with this publickey. How do i sign this message for this kind of requisition correctly? I tried org.bouncycastle.asn1.cmp.PKIMessages and org.bouncycastle.cert.cmp.ProtectedPKIMessage.

PKIMessages:

DERBitString signature = new DERBitString(createSignature("signature".getBytes())); 
X509Certificate signercert = convertToX509Cert(certPEM);
CMPCertificate cmpCert = new CMPCertificate(org.bouncycastle.asn1.x509.Certificate.getInstance(signercert.getEncoded()));

PKIMessage message = new PKIMessage(header, body, signature, new CMPCertificate[] { cmpCert });

// createsignature() 
private static byte[] createSignature(byte[] str){
Signature dsa = Signature.getInstance("SHA256WithRSA");
dsa.initSign(privateKey);
dsa.update(str, 0, str.length);
signature = dsa.sign();
return signature;

--> error from cmp server: "SIGNATURE_INVALID_KEY_CODE"

ProtectedPKIMessage:

ContentSigner signer = new JcaContentSignerBuilder("SHA1WithRSAEncryption").setProvider(BouncyCastleProvider.PROVIDER_NAME).build((PrivateKey) ks.getKey(KEYSTORE_ALIAS, KEYSTORE_PWD.toCharArray()));

ProtectedPKIMessage message = new ProtectedPKIMessageBuilder(pvno, new GeneralName(sender), new GeneralName(recipient))
.addCMPCertificate(new X509CertificateHolder(ks.getCertificate(KEYSTORE_ALIAS).getEncoded()))
.setBody(body).build(signer);

--> error from cmp server: "ERROR_READING_CMS_OBJECT_CODE"

Is the way how i sign the cmp request message correct? What is the difference between PKIMessage and the 'protection' argument and org.bouncycastle.cert.cmp.ProtectedPKIMessage?


Solution

  • this is the way i use to sign cmp requests

    GeneralName generalName = new GeneralName(subjectDN);
    ProtectedPKIMessageBuilder pbuilder = new 
    ProtectedPKIMessageBuilder(generalName,
                        protectedPKIMessage.getHeader().getSender());
                pbuilder.setBody(pkibody);
                ContentSigner msgsigner = new 
                JcaContentSignerBuilder(contentSignerBuilder)//
                       .setProvider("BC")//
                       .build(getKey().getPrivate());
    
               ProtectedPKIMessage message = pbuilder.build(msgsigner)
    

    ;