The Version 2 APIs are a result of us having to work around the idiosyncrasies of multiple providers as well as trying to find ways to accommodate some of the newer cryptography APIs that are appearing for small devices. These are often not JCE/JCA provider based, and are generally targeted to specific functionality. Requests for this kind of functionality have been increasing in respect to the lightweight APIs as well, largely due to the market evolving from the devices with single threaded VMs and a 32k footprint of 10 years ago to substantially larger and fully featured VMs we have today.
Broadly speaking the Version 2 APIs are built around the idea of operators, which are interfaces that provide specific types of cryptographic functionality. CMS, CRMF, CMP, TSP, and OCSP messages, to name but a few, as well as certificates, can then be built by providing the appropriate operators to meet the requirements of the protocol.
The result of this is that it is now possible to create things like certificates and CMS messages using the BC lightweight API, and this document is meant to provide some help in seeing how that is done.
For the purposes of the final 1.* release of BC, version 1.46, the version 2 APIs are included in the bcmail package. From 1.47, the version 2 APIs are in the pcpkix packages, and bcmail now only contains the S/MIME package.
Core to creating a certificate is the ability to create a signature.
In the version 2 API an example of certificate creation looks as follows:
We'll start by looking at sigGen first. In a situation where you're using the JCA a builder is provider for creating objects with the ContentSigner interface which have underlying implementations using the JCA. This class is the JcaContentSignerBuilder and in the case where we wanted to create a SHA1withRSA signer, we might create sigGen as follows:
In the above case privKey is simply the PrivateKey object representing the private key we are signing with.
Of course we may actually be wanting to do this using the BC lightweight API. In this case we can use the BcRSAContentSignerBuilder. In this case the
code for creating a SHA1withRSA signature might look as follows:
where lwPrivKey is an RSA private key as described in the BC lightweight API.
Where this gets more interesting is we can now also apply our sigGen value to signing a CMS message as follows:
Of course it might be the case that you do not wish to use either the JCA or the BC lightweight API. If this is the case, then it is just a matter of implementing the ContentSigner interface.
Of course having created a signature it's useful to be able to verify it.
Verification is a little bit more involved than signature creation, the issue being that you really need to know what kind of signature you are trying to verify before you can make sense of it.
In the case of certificates the X509CertificateHolder class provides a method, isSignatureValid which allows you to verify the signature on the certificate the holder class contains. The isSignatureValid method takes a ContentVerifierProvider class, and queries it to create a content verifier capable of verifying the content (in the this case the TBSCertificate structure) and the signature match.
Standard implementations providing the core functionality are provided for both lighweight and provider based implementations.
In the case of the lightweight API, assuming we have a suitable public key in the lwPubKey object, the code for doing the signature verification looks as follows:
A more general class is provided for use with the JCA - in the simple case all you need to do is specify which provider you want to use as follows:
Verifying the signature on a SignerInformation object is a little more complicated as for the most part it requires a separate digest calculator to be available as well. Code for doing this using the general lightweight API to process RSA signatures looks like this:
Of course if you know the digest algorithms to expect it is possible to implement your own DigestCalculatorProvider that is restricted to the necessary algorithms.
In the case of a JCA/JCE provider based solution, where the same provider can be used for both signature verification and digest calculation, you can use the following:
In the case where you need to use different providers or even a provider/lightweight combination you can use the SignerInformationVerifier class to create a verifier.
The certificate generation example about could also have been written as:
likewise in the CMS signing example the required X509CertificateHolder could be created from a JCA X509Certificate so the declaration of sigCert would appear
On the other hand you might only have a byte code representation of the certificate available. In this case you might have said:
The following packages contain version 2 implementations:
- org.bouncycastle.cert - certificate/CRL/attribute certificate generation.
- org.bouncycastle.cert.jcajce - JCA/JCE helper classes for certificate/crl/attribute certificate processing.
- org.bouncycastle.cert.cmp - CMP certificate management protocol
- org.bouncycastle.cert.crmf - CRMF certificate request messaging
- org.bouncycastle.cert.crmf.jcajce - JCA/JCE helper classes for CRMF
- org.bouncycastle.cert.ocsp - OCSP online certificate status protocol.
- org.bouncycastle.cert.ocsp.jcajce - JCA/JCE helper classes for OCSP.
- org.bouncycastle.pkcs - PKCS#10 certification request messaging
- org.bouncycastle.pkcs.jcajce - JCA/JCE helper classes for PKCS#10
- org.bouncycastle.cms - CMS Cryptographic Message Syntax
- org.bouncycastle.cms.bc - lightweight API helper classes for CMS.
- org.bouncycastle.cms.jcajce - JCA/JCE helper classes for CMS.
- org.bouncycastle.operator - generic operator classes and helpers.
- org.bouncycastle.operator.bc - lightweight helper classes for operators
- org.bouncycastle.operator.jcejce - JCA/JCE helper classes for operators.
- org.bouncycastle.mail.smime - S/MIME secure mime implementation.
- org.bouncycastle.tsp - TSP Time Stamp Protocol implementation.