Generate x509certificate certpath in JAVA - java

I successfully make X.509 certificate from certificate request.
However, I need to insert CERT Path informatin in the X.509 certificate.
I know that I have to use CertPathBuilder method but I don't know how to use it.
could you give me an code example that suitable for the following code?
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Enumeration;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.pkcs.Attribute;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.X509Extension;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.jce.PKCS10CertificationRequest;
import org.bouncycastle.openssl.PEMReader;
import org.bouncycastle.openssl.PEMWriter;
import org.bouncycastle.x509.X509V3CertificateGenerator;
import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;
import chapter6.X509V1CreateExample;
//example of a basic CA
public class PKCS10CertCreateExample
{
public static X509Certificate[] buildChain() throws Exception
{
PEMReader pRd = new PEMReader(
new InputStreamReader(
new FileInputStream("pkcs10.req")));
PKCS10CertificationRequest request = (PKCS10CertificationRequest)pRd.readObject();
//create a root certificate
KeyPair rootPair=chapter6.Utils.generateRSAKeyPair();
X509Certificate rootCert = X509V1CreateExample.generateV1Certificate(rootPair);
//validate the certification request
if(!request.verify("BC"))
{
System.out.println("request failed to verify!");
System.exit(1);
}
//create the certificate using the information in the request
X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
certGen.setIssuerDN(rootCert.getSubjectX500Principal());
certGen.setNotBefore(new Date(System.currentTimeMillis()));
certGen.setNotAfter(new Date(System.currentTimeMillis()+50000));
certGen.setSubjectDN(request.getCertificationRequestInfo().getSubject());
certGen.setPublicKey(request.getPublicKey("BC"));
certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(rootCert));
certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(request.getPublicKey("BC")));
certGen.addExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false));
//certGen.addExtension(X509Extensions.KeyUsage, true, new BasicConstraints(false));
certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment));
certGen.addExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(KeyPurposeId.id_kp_serverAuth));
//extract the extension request attribute
ASN1Set attributes = request.getCertificationRequestInfo().getAttributes();
for(int i=0;i!=attributes.size();i++)
{
Attribute attr = Attribute.getInstance(attributes.getObjectAt(i));
//process extension request
if(attr.getAttrType().equals(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest))
{
X509Extensions extensions = X509Extensions.getInstance(attr.getAttrValues().getObjectAt(0));
Enumeration<?> e = extensions.oids();
while(e.hasMoreElements())
{
DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
X509Extension ext = extensions.getExtension(oid);
certGen.addExtension(oid, ext.isCritical(), ext.getValue().getOctets());
}
}
}
X509Certificate issuedCert = certGen.generateX509Certificate(rootPair.getPrivate());
return new X509Certificate[]{issuedCert, rootCert};
}
public static void pemEncodeToFile(String filename, Object obj, char[] password) throws Exception{
PEMWriter pw = new PEMWriter(new FileWriter(filename));
if (password != null && password.length > 0) {
pw.writeObject(obj, "DESEDE", password, new SecureRandom());
} else {
pw.writeObject(obj);
}
pw.flush();
pw.close();
}
public static void main(String[] args) throws Exception
{
X509Certificate[] chain = buildChain();
PEMWriter pemWrt = new PEMWriter(new OutputStreamWriter(System.out));
pemWrt.writeObject(chain[0]);
pemEncodeToFile("pkcs10.pem", chain[0], null);
pemWrt.close();
}
}

The below code may help you
CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
X509CertSelector certSelector = new X509CertSelector();
certSelector.setCertificate((X509Certificate) myKeyStore.getCertificate("mykey"));
PKIXBuilderParameters cpp = new PKIXBuilderParameters(trustAnchors, certSelector);
cpp.addCertStore(cs);
cpp.setRevocationEnabled(true);
cpp.setMaxPathLength(6);
cpp.setDate(new Date());
CertPathBuilderResult a = cpb.build(cpp);
CertPath certPath = a.getCertPath();

CSR reply is normally signed by intermediate CA, hence the cert chain is incomplete missing root CA. Suppose you have all the root CA certs in the collection trustCerts, and the cert array certChain from CSR reply.
To build complete cert chain, firstly, add all the root CA certs to trustAnchors.
Set<TrustAnchor> trustAnchors = new HashSet<>();
trustAnchors.addAll(trustCerts.stream.map(cert -> new TrustAnchors(cert, null)).toList());
Then configure CertSelector with the targeting end certificate.
X509CertSelector selector = new X509CertSelector();
selector.setCertificate(certChain[0]);
Create build parameters. Disable revocation check if not using it.
PKIXBuilderParameters parameters = new PKIXBuilderParameters(trustAnchors, selector);
parameters.setRevocationEnabled(false);
Add intermediate CA certs into build parameters. Since certChain contains both intermediate CA and end certificate, just add it to parameter.
CertStore intermediate = CertStore.getInstance("Collection", new CollectionCertStoreParameters(Arrays.asList(certChain)));
parameters.addCertStore(intermediate);
Instantiate builder instance and build path
CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
PKIXCertPathBuilderResult cpbResult = (PKIXCertPathBuilderResult) cpb.build(parameters);
CertPath cp = cpbResult.getCertPath();
List<X509Certificate> completeCertChain = (List<X509Certificate>) cp.getCertificates();

Related

Bouncy castle with spring boot

I am trying to use Https over http, I generated the CA certificate with bouncy castle and generated from the .cer file the jks file, spring boot started successfully with the properties provided with an embedded tomcat.
The problem is that I'm getting always insecure ssl certificate from the browser (for example from chrome : This CA Root certificate is not trusted because it is not in the Trusted Root Certification Authorities store.) while I add the trust store programatically with another config class.
Here is my code:
import org.apache.commons.codec.binary.Base64; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.cmp.CertRepMessage; import org.bouncycastle.asn1.cmp.PKIBody; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.cert.CertException; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.X509v3CertificateBuilder; import org.bouncycastle.cert.cmp.CMPException; import org.bouncycastle.cert.cmp.ProtectedPKIMessage; import org.bouncycastle.cert.cmp.ProtectedPKIMessageBuilder; import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.ContentVerifierProvider; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.math.BigInteger; import java.security.*; import java.security.cert.X509Certificate; import java.util.Date;
public class generateService {
private static final String BC = BouncyCastleProvider.PROVIDER_NAME;
private static X509CertificateHolder makeV3Certificate(KeyPair subKP, String _subDN, KeyPair issKP, String _issDN)
throws GeneralSecurityException, IOException, OperatorCreationException, CertException
{
PublicKey subPub = subKP.getPublic();
PrivateKey issPriv = issKP.getPrivate();
PublicKey issPub = issKP.getPublic();
X509v3CertificateBuilder v1CertGen = new JcaX509v3CertificateBuilder(
new X500Name(_issDN),
BigInteger.valueOf(System.currentTimeMillis()),
new Date(System.currentTimeMillis()),
new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100)),
new X500Name(_subDN),
subPub);
ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSA").setProvider(BC).build(issPriv);
X509CertificateHolder certHolder = v1CertGen.build(signer);
ContentVerifierProvider verifier = new JcaContentVerifierProviderBuilder().setProvider(BC).build(issPub);
return certHolder;
}
public X509Certificate test(KeyPair kp) throws OperatorCreationException, GeneralSecurityException, CertException, IOException, CMPException {
Provider bcProvider = new BouncyCastleProvider();
Security.addProvider(bcProvider);
X509CertificateHolder cert = makeV3Certificate(kp, "CN=CA", kp, "CN=CA");
GeneralName sender = new GeneralName(new X500Name("CN=CA"));
GeneralName recipient = new GeneralName(new X500Name("CN=CA"));
ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSAEncryption").setProvider(BC).build(kp.getPrivate());
ProtectedPKIMessage message = new ProtectedPKIMessageBuilder(sender, recipient)
.setBody(new PKIBody(PKIBody.TYPE_INIT_REP, CertRepMessage.getInstance(new DERSequence(new DERSequence()))))
.addCMPCertificate(cert)
.build(signer);
X509Certificate jcaCert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(message.getCertificates()[0]);
return jcaCert;
}
public void generateJKS() throws GeneralSecurityException, IOException, OperatorCreationException, CMPException, CertException {
Provider bcProvider = new BouncyCastleProvider();
Security.addProvider(bcProvider);
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
X509Certificate certificate = test(keyPair);
final FileOutputStream os = new FileOutputStream("E:\\cert4.cer");
os.write("-----BEGIN CERTIFICATE-----\n".getBytes("US-ASCII"));
os.write(Base64.encodeBase64(certificate.getEncoded(), true));
os.write("-----END CERTIFICATE-----\n".getBytes("US-ASCII"));
os.close();
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(null,null);
X509Certificate[] certChain = new X509Certificate[1];
certChain[0] = certificate;
keyStore.setKeyEntry("myaliaskey", (Key)keyPair.getPrivate(), "secret".toCharArray(), certChain);
OutputStream outputStream = new FileOutputStream("E:\\keystoreRSA4.jks");
keyStore.store(outputStream, "secret".toCharArray());
outputStream.flush();
outputStream.close();
}
public static void main(String[] args) throws Exception {
new generateService().generateJKS();
} }
Application.properties:
server.port = 8443 server.http.port = 8080 server.ssl.key-store = E:\\keystoreRSA4.jks server.ssl.key-password = secret server.ssl.keyAlias = myaliaskey
/***************************************************************************/
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
#Configuration public class SSLConfig {
#PostConstruct
private void configureSSL() {
System.setProperty("https.protocols", "TLSv1.2");
System.setProperty("javax.net.ssl.trustStore", "E:\\keystoreRSA4.jks");
System.setProperty("javax.net.ssl.keyStore", "E:\\keystoreRSA4.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "secret");
} }
import org.apache.catalina.Context; import org.apache.catalina.connector.Connector; import org.apache.tomcat.util.descriptor.web.SecurityCollection; import org.apache.tomcat.util.descriptor.web.SecurityConstraint; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
#Configuration public class TomcatConfig {
#Value("${server.http.port}")
private int httpPort;
#Value("${server.port}")
private int httpsPort;
#Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
#Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(initiateHttpConnector());
return tomcat;
}
public Connector initiateHttpConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("https");
connector.setPort(httpPort);
connector.setSecure(true);
connector.setRedirectPort(httpsPort);
return connector;
} }
Any help will be appreciated and thank you in advance.
how i can figure it to let the browser accept it as trust certificate?
Fortunately, you can't. There's a discussion about the topic in this question:
If we simply said "HTTPS is now possible with self-signed certificates", your browser could not distinguish whether a site you are trying to visit has a self-signed cert because it is supposed to, or because you are being attacked. Thus, it would decrease security.
You have to add an exception to your browser to accept your certificate. Normally during development. For production use, you have to buy a certificate from a trusted vendor like Verisign.
To add an exception to your browser, please see this other question.
Cheers!

Extract multiple X.509 certificates from PEM-formatted file in Java

I have a method which extracts a X.509 certificate from a given PEM-formatted file, using the bouncycastle library.
Imports:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.openssl.PEMParser;
Method:
/**
* Reads an X509 certificate from a PEM file.
*
* #param certificateFile The PEM file.
* #return the X509 certificate, or null.
* #throws IOException if reading the file fails
* #throws CertificateException if parsing the certificate fails
*/
public static X509Certificate readCertificatePEMFile(File certificateFile) throws IOException, CertificateException {
if (certificateFile.exists() && certificateFile.canRead()) {
try (InputStream inStream = new FileInputStream(certificateFile)) {
try (PEMParser pemParser = new PEMParser(new InputStreamReader(inStream))) {
Object object = pemParser.readObject();
if (object != null && object instanceof X509CertificateHolder) {
return new JcaX509CertificateConverter().getCertificate( (X509CertificateHolder)object );
}
}
}
}
return null;
}
This works well for "normal" certificate files, e.g. a server certificate.
If I have a CA chain certificate file, containing multiple certificates, how could I achieve extracting all certificates from this file (the method shown only extracts the first certificate in the file).
Try this code, it handles multiple certificates and Private key entry im PEM file
Security.addProvider(new BouncyCastleProvider());
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
while((object = pemParser.readObject())!=null)
{
if(object instanceof X509CertificateHolder)
{
X509Certificate x509Cert = (X509Certificate) new JcaX509CertificateConverter().getCertificate((X509CertificateHolder) object);
}
else if(object instanceof PEMEncryptedKeyPair)
{
if(password==null) throw new IllegalArgumentException("Password required for parsing RSA Private key");
PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password.toCharArray());
converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv));
}
else if(object instanceof PEMKeyPair)
{
converter.getKeyPair((PEMKeyPair) object);
}
}

Certifying Pdf document with iText

I can sign my pdf and verify it by adding my smith.crt to be trusted in adobe reader (i get the green check mark) , my problem is certifying my pdf, i can not get the blue ribbon in the top left corner of my pdf, is it because i use the self-signed certificate?
I get the message:
The validity of the document certification is UNKNOWN. The author
could not be verified.
Can you please help me out, how can I get that blue ribbon?
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
import com.itextpdf.text.pdf.security.MakeSignature;
public class SO {
public static String ORIGINAL = "src/test.pdf";
public static String SIGNED1 = "src/signedtest.pdf";
public void createPdf(String filename) throws IOException, DocumentException {
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream(filename));
document.open();
document.add(new Paragraph("Test!"));
document.close();
}
public void signPdf(String src, String dest)
throws IOException, DocumentException, GeneralSecurityException {
String path = "src/keyS";
String keystore_password = "SOSOSO";
String key_password = "SOSOSO";
String alias = "SO";
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(path), keystore_password.toCharArray());
PrivateKey pk = (PrivateKey) ks.getKey(alias, key_password.toCharArray());
Certificate[] chain = ks.getCertificateChain(alias);
// reader / stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);
// appearance
PdfSignatureAppearance appearance = stamper
.getSignatureAppearance();
appearance.setReason("Test");
appearance.setLocation("Test st.");
appearance.setVisibleSignature(new Rectangle(350, 750, 500, 800), 1, "first");
appearance.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED);
// digital signature
ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC");
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, es, chain, null, null, null, 0, CryptoStandard.CMS);
}
public static void main(String[] args)
throws IOException, DocumentException, GeneralSecurityException {
Security.addProvider(new BouncyCastleProvider());
SO potpis = new SO();
potpis.createPdf(ORIGINAL);
potpis.signPdf(ORIGINAL, SIGNED1);
}
}
Verification requires a CA (Certification Authority). When you copy the document to a new site (customer's computer), it will perform verification by going through the trusted CA store. There, it cannot find you and verification fails.
You may try and register yourself as a Trusted CA, but it is for the only purpose to test your code in a development environment.
To have the real thing, you must use a Trusted CA that is already registered at the new site (customer's computer). Generally, on the Internet at large this means you need a REAL CA (VeriSign or similar).
More about installing a Trusted CA on your computer: How to install a Trusted Root CA Certificates
Again, this latter option will give you the blue ribbon on your site (development machine) but not on any other site (customer's computer).

Error while creating x.509 certificate

I would like to create x.509 certificate,
so I copy the following codes from Wrox, Beggining Cryptography with Java, chapter 6.
import java.io.OutputStreamWriter;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Enumeration;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.pkcs.Attribute;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.X509Extension;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.jce.PKCS10CertificationRequest;
import org.bouncycastle.openssl.PEMWriter;
import org.bouncycastle.x509.X509V3CertificateGenerator;
import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;
import chapter6.PKCS10ExtensionExample;
import chapter6.X509V1CreateExample;
//example of a basic CA
public class PKCS10CertCreateExample
{
public static X509Certificate[] buildChain() throws Exception
{
//create the certification request
KeyPair pair = chapter7.Utils.generateRSAKeyPair();
PKCS10CertificationRequest request = PKCS10ExtensionExample.generateRequest(pair);
//create a root certificate
KeyPair rootPair=chapter7.Utils.generateRSAKeyPair();
X509Certificate rootCert = X509V1CreateExample.generateV1Certificate(rootPair);
//validate the certification request
if(!request.verify("BC"))
{
System.out.println("request failed to verify!");
System.exit(1);
}
//create the certificate using the information in the request
X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
certGen.setIssuerDN(rootCert.getSubjectX500Principal());
certGen.setNotBefore(new Date(System.currentTimeMillis()));
certGen.setNotAfter(new Date(System.currentTimeMillis()+50000));
certGen.setSubjectDN(request.getCertificationRequestInfo().getSubject());
certGen.setPublicKey(request.getPublicKey("BC"));
certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(rootCert));
certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(request.getPublicKey("BC")));
certGen.addExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false));
certGen.addExtension(X509Extensions.KeyUsage, true, new BasicConstraints(false));
certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment));
certGen.addExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(KeyPurposeId.id_kp_serverAuth));
//extract the extension request attribute
ASN1Set attributes = request.getCertificationRequestInfo().getAttributes();
for(int i=0;i!=attributes.size();i++)
{
Attribute attr = Attribute.getInstance(attributes.getObjectAt(i));
//process extension request
if(attr.getAttrType().equals(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest))
{
X509Extensions extensions = X509Extensions.getInstance(attr.getAttrValues().getObjectAt(0));
Enumeration<?> e = extensions.oids();
while(e.hasMoreElements())
{
DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
X509Extension ext = extensions.getExtension(oid);
certGen.addExtension(oid, ext.isCritical(), ext.getValue().getOctets());
}
}
}
X509Certificate issuedCert = certGen.generateX509Certificate(rootPair.getPrivate());
return new X509Certificate[]{issuedCert, rootCert};
}
public static void main(String[] args) throws Exception
{
X509Certificate[] chain = buildChain();
PEMWriter pemWrt = new PEMWriter(new OutputStreamWriter(System.out));
pemWrt.writeObject(chain[0]);
pemWrt.writeObject(chain[1]);
pemWrt.close();
}
}
However, the codes shows errors as follows
Exception in thread "main" java.lang.IllegalArgumentException: extension 2.5.29.15 already added
at org.bouncycastle.asn1.x509.X509ExtensionsGenerator.addExtension(Unknown Source)
at org.bouncycastle.asn1.x509.X509ExtensionsGenerator.addExtension(Unknown Source)
at org.bouncycastle.x509.X509V3CertificateGenerator.addExtension(Unknown Source)
at PKCS10CertCreateExample.buildChain(PKCS10CertCreateExample.java:68)
at PKCS10CertCreateExample.main(PKCS10CertCreateExample.java:100)
please, help me..
Googling extension 2.5.29.15 will tell you that refers to KeyUsage
Googling the source code for X509V3CertificateGenerator shows that addExtension() calls X509ExtensionsGenerator.addExtension() which throws an exception if the extension provided has already been added.
The source code you provide above does just that, and the exception is thrown:
certGen.addExtension(X509Extensions.KeyUsage, true, new BasicConstraints(false));
certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment));
This is a bug in the code. You need to remove one of them. I would guess the first.

Sign data using PKCS #7 in JAVA

I want to sign a text file (may be a .exe file or something else in the future)
using PKCS#7 and verify the signature using Java.
What do I need to know?
Where will I find an API (.jar and documentation)?
What are the steps I need to follow in order to sign data and verify the data?
Please provide me code snippet if possible.
I reckon you need the following 2 Bouncy Castle jars to generate the PKCS7 digital signature:
bcprov-jdk15on-147.jar (for JDK 1.5 - JDK 1.7)
bcmail-jdk15on-147.jar (for JDK 1.5 - JDK 1.7)
You can download the Bouncy Castle jars from here.
You need to setup your keystore with the public & private key pair.
You need only the private key to generate the digital signature & the public key to verify it.
Here's how you'd pkcs7 sign content (Exception handling omitted for brevity) :
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSTypedData;
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.util.Store;
import org.bouncycastle.util.encoders.Base64;
public final class PKCS7Signer {
private static final String PATH_TO_KEYSTORE = "/path/to/keyStore";
private static final String KEY_ALIAS_IN_KEYSTORE = "My_Private_Key";
private static final String KEYSTORE_PASSWORD = "MyPassword";
private static final String SIGNATUREALGO = "SHA1withRSA";
public PKCS7Signer() {
}
KeyStore loadKeyStore() throws Exception {
KeyStore keystore = KeyStore.getInstance("JKS");
InputStream is = new FileInputStream(PATH_TO_KEYSTORE);
keystore.load(is, KEYSTORE_PASSWORD.toCharArray());
return keystore;
}
CMSSignedDataGenerator setUpProvider(final KeyStore keystore) throws Exception {
Security.addProvider(new BouncyCastleProvider());
Certificate[] certchain = (Certificate[]) keystore.getCertificateChain(KEY_ALIAS_IN_KEYSTORE);
final List<Certificate> certlist = new ArrayList<Certificate>();
for (int i = 0, length = certchain == null ? 0 : certchain.length; i < length; i++) {
certlist.add(certchain[i]);
}
Store certstore = new JcaCertStore(certlist);
Certificate cert = keystore.getCertificate(KEY_ALIAS_IN_KEYSTORE);
ContentSigner signer = new JcaContentSignerBuilder(SIGNATUREALGO).setProvider("BC").
build((PrivateKey) (keystore.getKey(KEY_ALIAS_IN_KEYSTORE, KEYSTORE_PASSWORD.toCharArray())));
CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
generator.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").
build()).build(signer, (X509Certificate) cert));
generator.addCertificates(certstore);
return generator;
}
byte[] signPkcs7(final byte[] content, final CMSSignedDataGenerator generator) throws Exception {
CMSTypedData cmsdata = new CMSProcessableByteArray(content);
CMSSignedData signeddata = generator.generate(cmsdata, true);
return signeddata.getEncoded();
}
public static void main(String[] args) throws Exception {
PKCS7Signer signer = new PKCS7Signer();
KeyStore keyStore = signer.loadKeyStore();
CMSSignedDataGenerator signatureGenerator = signer.setUpProvider(keyStore);
String content = "some bytes to be signed";
byte[] signedBytes = signer.signPkcs7(content.getBytes("UTF-8"), signatureGenerator);
System.out.println("Signed Encoded Bytes: " + new String(Base64.encode(signedBytes)));
}
}
PKCS#7 is known as CMS now (Cryptographic Message Syntax), and you will need the Bouncy Castle PKIX libraries to create one. It has ample documentation and a well established mailing list.
I won't supply code snippet, it is against house rules. Try yourself first.

Categories

Resources