Soporte al cliente de CMP

Esta página proporciona ejemplos de código y otra información necesaria para crear un cliente CMP. Estos ejemplos de código no se mantienen y podrían no ser compatibles con futuras versiones de BouncyCastle.

Mensaje (inicial) de solicitud de certificado protegido por HMAC (modo RA)

// Just preparations
final BigInteger certReqId = BigInteger.valueOf( 1 );
final byte [] senderNonce = "12345" .getBytes();
final byte [] transactionId = "23456" .getBytes();
KeyPairGenerator kpi = KeyPairGenerator.getInstance( "RSA" );
kpi.initialize( 1024 );
KeyPair keyPair = kpi.generateKeyPair();
// Now on to the CMP
CertificateRequestMessageBuilder msgbuilder = new CertificateRequestMessageBuilder(certReqId);
X500Name issuerDN = new X500Name( "CN=ManagementCA" );
X500Name subjectDN = new X500Name( "CN=user" );
msgbuilder.setIssuer(issuerDN);
msgbuilder.setSubject(subjectDN);
final byte [] bytes = keyPair.getPublic().getEncoded();
final ByteArrayInputStream bIn = new ByteArrayInputStream(bytes);
final ASN1InputStream dIn = new ASN1InputStream(bIn);
final SubjectPublicKeyInfo keyInfo = new SubjectPublicKeyInfo((ASN1Sequence)dIn.readObject());
dIn.close();
msgbuilder.setPublicKey(keyInfo);
GeneralName sender = new GeneralName(subjectDN);
msgbuilder.setAuthInfoSender(sender);
// RAVerified POP
msgbuilder.setProofOfPossessionRaVerified();
CertificateRequestMessage msg = msgbuilder.build();
org.bouncycastle.asn1.crmf.CertReqMessages msgs = new org.bouncycastle.asn1.crmf.CertReqMessages(msg.toASN1Structure());
org.bouncycastle.asn1.cmp.PKIBody pkibody = new org.bouncycastle.asn1.cmp.PKIBody(org.bouncycastle.asn1.cmp.PKIBody.TYPE_INIT_REQ, msgs);
// Message protection and final message
GeneralName recipient = new GeneralName(issuerDN);
ProtectedPKIMessageBuilder pbuilder = new ProtectedPKIMessageBuilder(sender, recipient);
pbuilder.setMessageTime( new Date());
// senderNonce
pbuilder.setSenderNonce(senderNonce);
// TransactionId
pbuilder.setTransactionID(transactionId);
// Key Id used (required) by the recipient to do a lot of stuff
pbuilder.setSenderKID( "KeyID" .getBytes());
pbuilder.setBody(pkibody);
JcePKMACValuesCalculator jcePkmacCalc = new JcePKMACValuesCalculator();
Identificador de algoritmo final AlgorithmIdentifier digAlg = new AlgorithmIdentifier( new ASN1ObjectIdentifier( "1.3.14.3.2.26" )); // SHA1
Identificador de algoritmo final AlgorithmIdentifier macAlg = new AlgorithmIdentifier( new ASN1ObjectIdentifier( "1.2.840.113549.2.7" )); // HMAC/SHA1
jcePkmacCalc.setup(digAlg, macAlg);
PKMACBuilder macbuilder = new PKMACBuilder(jcePkmacCalc);
MacCalculator macCalculator = macbuilder.build( "password" .toCharArray());
ProtectedPKIMessage message = pbuilder.build(macCalculator);

Mensaje de solicitud de revocación protegido por HMAC (modo RA)

// Just preparations
final byte [] senderNonce = "12345" .getBytes();
final byte [] transactionId = "23456" .getBytes();
BigInteger serNo = new BigInteger( "aabbccdd" );
X500Name issuerDN = new X500Name( "CN=ManagementCA" );
X500Name userDN = new X500Name( "CN=user" );
// Cert template too tell which cert we want to revoke
CertTemplateBuilder myCertTemplate = new CertTemplateBuilder();
myCertTemplate.setIssuer(issuerDN);
myCertTemplate.setSubject(userDN);
myCertTemplate.setSerialNumber( new ASN1Integer(serNo));
// Extension telling revocation reason
ExtensionsGenerator extgen = new ExtensionsGenerator();
CRLReason crlReason = CRLReason.lookup(CRLReason.cessationOfOperation);
extgen.addExtension(Extension.reasonCode, false , crlReason);
Extensions exts = extgen.generate();
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(myCertTemplate.build());
v.add(exts);
ASN1Sequence seq = new DERSequence(v);
RevDetails myRevDetails = RevDetails.getInstance(seq);
RevReqContent myRevReqContent = new RevReqContent(myRevDetails);
PKIBody myPKIBody = new PKIBody(PKIBody.TYPE_REVOCATION_REQ, myRevReqContent); // revocation request
// Message protection and final message
GeneralName sender = new GeneralName(userDN);
GeneralName recipient = new GeneralName(issuerDN);
ProtectedPKIMessageBuilder pbuilder = new ProtectedPKIMessageBuilder(sender, recipient);
pbuilder.setMessageTime( new Date());
// senderNonce
pbuilder.setSenderNonce(senderNonce);
// TransactionId
pbuilder.setTransactionID(transactionId);
// Key Id used (required) by the recipient to do a lot of stuff
pbuilder.setSenderKID( "KeyId" .getBytes());
pbuilder.setBody(myPKIBody);
JcePKMACValuesCalculator jcePkmacCalc = new JcePKMACValuesCalculator();
Identificador de algoritmo final AlgorithmIdentifier digAlg = new AlgorithmIdentifier( new ASN1ObjectIdentifier( "1.3.14.3.2.26" )); // SHA1
Identificador de algoritmo final AlgorithmIdentifier macAlg = new AlgorithmIdentifier( new ASN1ObjectIdentifier( "1.2.840.113549.2.7" )); // HMAC/SHA1
jcePkmacCalc.setup(digAlg, macAlg);
PKMACBuilder macbuilder = new PKMACBuilder(jcePkmacCalc);
MacCalculator macCalculator = macbuilder.build( "password" .toCharArray());
ProtectedPKIMessage message = pbuilder.build(macCalculator);

Mensaje protegido por firma (modo cliente)

CertificateRequestMessageBuilder msgbuilder = new CertificateRequestMessageBuilder(BigInteger.valueOf(certReqId));
X509NameEntryConverter dnconverter = new X509DefaultEntryConverter();
X500Name issuerDN = X500Name.getInstance( new X509Name( "CN=ManagementCA" ).toASN1Object());
X500Name subjectDN = X500Name.getInstance( new X509Name( "CN=user" , dnconverter).toASN1Object());
msgbuilder.setIssuer(issuerDN);
msgbuilder.setSubject(subjectDN);
final byte [] bytes = keyPair.getPublic().getEncoded();
final ByteArrayInputStream bIn = new ByteArrayInputStream(bytes);
final ASN1InputStream dIn = new ASN1InputStream(bIn);
final SubjectPublicKeyInfo keyInfo = new SubjectPublicKeyInfo((ASN1Sequence)dIn.readObject());
msgbuilder.setPublicKey(keyInfo);
GeneralName sender = new GeneralName(subjectDN);
msgbuilder.setAuthInfoSender(sender);
Control control = new RegTokenControl( "foo123" );
msgbuilder.addControl(control);
Provider prov = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME);
ContentSigner popsigner = new JcaContentSignerBuilder( "SHA256withRSA" ).setProvider(prov).build(keyPair.getPrivate());
msgbuilder.setProofOfPossessionSigningKeySigner(popsigner);
CertificateRequestMessage msg = msgbuilder.build();
GeneralName recipient = new GeneralName(issuerDN);
ProtectedPKIMessageBuilder pbuilder = new ProtectedPKIMessageBuilder(sender, recipient);
pbuilder.setMessageTime( new Date());
// senderNonce
pbuilder.setSenderNonce(senderNonce);
// TransactionId
pbuilder.setTransactionID(transactionId);
org.bouncycastle.asn1.crmf.CertReqMessages msgs = new org.bouncycastle.asn1.crmf.CertReqMessages(msg.toASN1Structure());
org.bouncycastle.asn1.cmp.PKIBody pkibody = new org.bouncycastle.asn1.cmp.PKIBody(org.bouncycastle.asn1.cmp.PKIBody.TYPE_INIT_REQ, msgs);
pbuilder.setBody(pkibody);
ContentSigner msgsigner = new JcaContentSignerBuilder( "SHA1withRSA" ).setProvider(prov).build(keyPair.getPrivate());
ProtectedPKIMessage message = pbuilder.build(msgsigner);

Mensaje con múltiples firmas

Código de muestra para un mensaje NestedMessageContent protegido por firma:

String subjectDN = "CN=bogusSubjectNested" ;
final byte [] nonce = "sendernonce" .getBytes();
final byte [] transid = "trandis" .getBytes();
PKIMessage crmfMsg = createCrmfReq();
//Signing crmfMsg
KeyPair eeKeys = getAdminKeys();
Certificate adminCert = getAdminCertificate();
ByteArrayInputStream bIn = new ByteArrayInputStream(adminCert.getEncoded());
ASN1InputStream dIn = new ASN1InputStream(bIn);
ASN1Sequence extraAdminCertSeq = (ASN1Sequence)dIn.readObject();
X509CertificateStructure extraCert = new X509CertificateStructure(ASN1Sequence.getInstance(extraAdminCertSeq));
crmfMsg.addExtraCert(extraCert);
Firma final Signature sig = Signature.getInstance(PKCSObjectIdentifiers.sha256WithRSAEncryption.getId(), BouncyCastleProvider.PROVIDER_NAME);
sig.initSign(eekeys.getPrivate());
sig.update(crmfMsg.getProtectedBytes());
byte [] eeSignature = sig.sign();
crmfMsg.setProtection( new DERBitString(eeSignature));
PKIHeader myPKIHeader = new PKIHeader( new DERInteger( 2 ), new GeneralName( new X509Name(subjectDN)), new GeneralName( new X509Name(((X509Certificate)cacert).getSubjectDN().getName())));
myPKIHeader.setMessageTime( new DERGeneralizedTime( new Date()));
// senderNonce
myPKIHeader.setSenderNonce( new DEROctetString(nonce));
// TransactionId
myPKIHeader.setTransactionID( new DEROctetString(transid));
PKIBody myPKIBody = new PKIBody(crmfMsg, 20 ); // NestedMessageContent
PKIMessage myPKIMessage = new PKIMessage(myPKIHeader, myPKIBody);
//Signing myPKIMessage
KeyPair raKeys = getRAKeys();
Firma final Signature sig = Signature.getInstance(PKCSObjectIdentifiers.sha256WithRSAEncryption.getId(), BouncyCastleProvider.PROVIDER_NAME);
sig.initSign(rakeys.getPrivate());
sig.update(myPKIMessage.getProtectedBytes());
byte [] eeSignature = sig.sign();
myPKIMessage.setProtection( new DERBitString(eeSignature));
final ByteArrayOutputStream bao = new ByteArrayOutputStream();
final DEROutputStream out = new DEROutputStream(bao);
out.writeObject(myPKIMessage);
final byte [] ba = bao.toByteArray();
// Send request and receive response
final byte [] resp = sendCmpHttp(ba, 200 );