如何正确签署 cmp 请求消息? (java,充气城堡)

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

我尝试在证书颁发机构(cmp 服务器)通过 cmp(证书管理协议)吊销证书并得到错误代码 "invalid signature key code"。我认为这是因为我签署 cmp 消息的方式,那里出了点问题。

我用 org.bouncycastle.asn1.cmp.PKIHeaderBuilder 构建 header,用 org.bouncycastle.asn1.crmf.CertTemplateBuilder:

构建 body
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();

然后我必须在整个消息上签名,而且似乎有不同的方式。在 extracerts (CMPCertificate) 中,我必须添加签名的 public 密钥,必须使用此 public 密钥验证签名。我如何正确地为这种申请签署这条消息?我尝试了 org.bouncycastle.asn1.cmp.PKIMessages 和 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;

--> 来自 cmp 服务器的错误:"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);

--> 来自 cmp 服务器的错误:"ERROR_READING_CMS_OBJECT_CODE"

我签署 cmp 请求消息的方式是否正确? PKIMessage 和 'protection' 参数与 org.bouncycastle.cert.cmp.ProtectedPKIMessage 有什么区别?

这是我用来签署 cmp 请求的方式

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)

;

我还通过使用 PKIMessage(不是 ProtectedPKIMessage)找到了另一个解决方案:

// ProtectedPart from bouncy castle
ProtectedPart protectedPart = new ProtectedPart(header, body);

Signature signature = Signature.getInstance("1.2.840.113549.1.1.11", "BC");
signature.initSign((PrivateKey) key);
signature.update(protectedPart.getEncoded());
byte[] sigBytes = signature.sign();
DERBitString signatureDER = new DERBitString(sigBytes);

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