Repository navigation
PKIResponse creation and decoding #1452
Description
Activity
CMSSignedData expects a ContentInfo - as a SignedData is (usually) always wrapped in a ContentInfo unless it's specified specifically in some other ASN.1 structure. "application/pkcs7-mime" which I think is what you are referring to requires the use of a ContentInfo though. Also encapsulated contentinfo (which is where the ContentInfo object is) should be an OCTET STRING. I have a feeling this should be using the CMSSignedDataGenerator though.
That said, we're certainly interested in ways to improve the API, and occasionally resourcing has meant we've only had time for what is necessary as opposed to what would also be useful. I've had a go at PKIResponse, if you have any further feedback let me know.
Let me just grab the relevant bits for reference:
The Full PKI Response consists of a SignedData or AuthenticatedData encapsulating a PKIResponse content type.
PKIResponse ::= SEQUENCE { controlSequence SEQUENCE SIZE(0..MAX) OF TaggedAttribute, cmsSequence SEQUENCE SIZE(0..MAX) OF TaggedContentInfo, otherMsgSequence SEQUENCE SIZE(0..MAX) OF OtherMsg }Response from server to client:
ContentInfo.contentType = id-signedData ContentInfo.content SignedData.encapContentInfo eContentType = id-ct-PKIResponse eContent controlSequence {102, id-cmc-statusInfoV2, {success, 201}} {103, id-cmc-senderNonce, 10005} {104, id-cmc-recipientNonce, 10001} certificates Newly issued certificate Other certificates SignedData.SignerInfos Signed by CAIn an error response, the
certificateswould be empty.So that looks right. It's the ContentInfo that you want to pass to the CMSSignedData object though (in PKCS land it's the ContentInfo OID that tells everyone what to expect - empty certificates should be fine though. You would want to use a CMSSignedDataGenerator if a SignedData based response is required.
Can you tell me what error you're getting due to the lack of certificates?
Can you tell me what error you're getting due to the lack of certificates?
This is what it is now. I don't remember why I reached that conclusion. Perhaps that was an exception from
CMSSignedDataGeneratorinstead.public class Test { public static void main(String... args) throws Exception { new CMSSignedData(Base64.getDecoder().decode( "MD8CAQMxADAyBggrBgEFBQcMA6AmMCQwHjAcAgEBBggrBgEFBQcHGTENMAsCAQIwAwIBAQIBBzAAMACgAKEAMQA=" )); } }
Exception in thread "main" org.bouncycastle.cms.CMSException: Malformed content. at org.bouncycastle.cms.CMSUtils.readContentInfo(Unknown Source) at org.bouncycastle.cms.CMSUtils.readContentInfo(Unknown Source) at org.bouncycastle.cms.CMSSignedData.<init>(Unknown Source) at Test.main(Test.java:7) Caused by: java.lang.IllegalArgumentException: Bad sequence size: 6 at org.bouncycastle.asn1.cms.ContentInfo.<init>(Unknown Source) at org.bouncycastle.asn1.cms.ContentInfo.getInstance(Unknown Source) ... 4 morewe're certainly interested in ways to improve the API
The immediate problem with what you already have is that, if any
ESTServicemethods fail, there's no simple way to find out why.It's always a bit tricky when you're only dealing with ASN.1 encodings. The message is not a ContentInfo, I think it's just a SignedData for a id-cct-PKIResponse. Are you saying it came back without the encapsulating ContentInfo?
CMSSignedDataexpects aContentInfoI missed that bit earlier, sorry. The message is
err.getEncoded()from the example at the top.My confusion here is that the example from the RFC shows a
SignedDatainside aContentInfo, but theorg.bouncycastle.asn1.cmspackage implementsContentInfoinside aSignedData. But I'm relatively new to all this so maybe I'm reading it wrong?Is a
PKIResponsetherefore supposed to be inside aContentInfoinside aSignedDatainside anotherContentInfo?If I try building that with
CMSSignedDataGenerator, I get this (the data is missing):byte[] responseBody = new CMSSignedDataGenerator() .generate(new PKCS7ProcessableObject(CMCObjectIdentifiers.id_cct_PKIResponse, pkiResponse)) .getEncoding();
0:d=0 hl=2 l= 34 cons: SEQUENCE 2:d=1 hl=2 l= 9 prim: OBJECT :pkcs7-signedData 13:d=1 hl=2 l= 21 cons: cont [ 0 ] 15:d=2 hl=2 l= 19 cons: SEQUENCE 17:d=3 hl=2 l= 1 prim: INTEGER :03 20:d=3 hl=2 l= 0 cons: SET 22:d=3 hl=2 l= 10 cons: SEQUENCE 24:d=4 hl=2 l= 8 prim: OBJECT :id-cct-PKIResponse 34:d=3 hl=2 l= 0 cons: SETConstructing the ASN1 object does work though:
byte[] responseBody = new ContentInfo(CMSObjectIdentifiers.signedData, signedData).getEncoding();
That adds even more steps to the process, further calling out for some more
org.bouncycastle.cmcclasses and/or expandingorg.bouncycastle.est.ESTResponseto be able to returnCMCStatus.@OrangeDog @dghgit can this issue be closed?
There are still no classes for building or querying these objects, other than manually dealing with the complex ASN1 tree.
Rather than all the code above, some additional constructors / accessors could be added to
SimplePKIResponse(or some new classes in the same package) to handleCMCFailInfo.ESTExceptionin particular should them in order to surface the failure reason from its body.Reacted by winfriedgerlachI've added a more complete SimplePKIResponse class as well as a PKIResponseBuilder class for constructing them. These are available on https://www.bouncycastle.org/betas and should appear in github shortly.
Reacted by James Howe- added a commit that references this issue
on May 3, 2026 Closing as assuming current updates are doing the job. If there's a shortfall in the new ones as well, please open another issue.
Are the betas in a public Maven repo somewhere?
Not yet, sorry, publishing to central is a manual process for us, the best I can offer at the moment is the https://www.bouncycastle.org/betas the source should now be synced up to bc-java on github as well.
The APIs look good, but a small note: As the
CMCStatusInfoV2already contains theBodyPartIDinformation, I don't thinkaddStatusInfoV2should need a separate parameter for it?I also realise I only asked for error support in this issue, but the new
PKIResponseBuildershould probably also haveaddCertificateto similarly streamline the success case instead of e.g.CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); gen.addCertificate(new X509CertificateHolder(cert.getEncoded())); CMSSignedData signed = gen.generate(new CMSAbsentContent()); return new SimplePKIResponse(signed.getEncoded());
Good points. I've updated the snapshot, addCertificate is there now. There's an override for addStatusInfoV2 to simplify things, if I read correctly technically it's allowed, although at the moment I'm not sure why, but then I've felt like that about RFCs before. Betas area is updated with the new version.
I can delete so much code 😄
That's what we're here for! Let me know if there's anything still that looks unnecessary.
- added a commit that references this issue
on May 11, 2026
I'm attempting to create a basic EST (RFC 7030) error response. If my reading of RFC 5272 is correct, then it should look like this:
However, unlike
SimplePKIResponse, BC does not appear to provide any convenient holder for this, only the raw ASN1 types. Additionally,CMSSignedDatadoes not count the outer object as valid, as it lacks certificates.As a result, the code to get the status is quite tedious, and would be even more so to account for there being other or different controls:
The code to build such a response on the server side is also tedious, and with no validity checks other than a
size==3.Have I missed something, either in my understanding of what the structure should be, or some classes that make this easier to deal with? If not, then can such things be added, and ideally integrated into
ESTService?