Extract multiple X.509 certificates from PEM-formatted file in Java - 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);
}
}

Related

iText Verify Signature with checking CRL

I am setting up a verifier which makes it possible to check the validity of signature.
The signature I do is based on DSS level LT so revocation checking is built into the document.
The problem that I encounter now is at the level of the verifier that I developed in iText. It allows the verification of the validity of the signature but of the information of the revocation. IText according to my research allows to verify this information in the signature itself based on: pkcs7.getCrl().
However, the DSS signature incorporates the revocation information into the dictionaries.
Below is the code I use to verify the signature:
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfString;
import com.itextpdf.text.pdf.security.PdfPKCS7;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.Principal;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.Security;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class TestCheck {
public static String pdf_file = "CURRENT_SIGNATURE.pdf";
public static final boolean verifySignature(PdfReader pdfReader)
throws GeneralSecurityException, IOException {
boolean valid = false;
AcroFields acroFields = pdfReader.getAcroFields();
PdfDictionary sigDict = acroFields.getSignatureDictionary("Signature1");
System.out.println(sigDict);
PdfString contents = sigDict.getAsString(PdfName.CONTENTS);
List<String> signatureNames = acroFields.getSignatureNames();
if (!signatureNames.isEmpty()) {
for (String name : signatureNames) {
// if (acroFields.signatureCoversWholeDocument(name)) {
PdfPKCS7 pkcs7 = acroFields.verifySignature(name);
valid = pkcs7.verify();
String reason = pkcs7.getReason();
Calendar signedAt = pkcs7.getSignDate();
X509Certificate signingCertificate = pkcs7.getSigningCertificate();
Principal issuerDN = signingCertificate.getIssuerDN();
Principal subjectDN = signingCertificate.getSubjectDN();
System.out.println("valid = "+valid);
//System.out.println("date = "+signedAt.getTime());
////System.out.println("reason = "+reason);
//System.out.println("issuer = "+issuerDN);
//System.out.println("subject = "+subjectDN);
System.out.println("CRL : " + pkcs7.getCRLs());
break;
}
// }
}
return valid;
}
public static void main(String[] args) throws Exception {
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
InputStream is = new FileInputStream(new File(pdf_file));
PdfReader reader = new PdfReader(is);
boolean ok = verifySignature(reader);
System.out.println("Ver : "+ ok);
}
}
Initially I wanted to simply point to the LtvVerifier class provided both by iText 5 and iText 7. Testing with that class, though, it turned out to not be applicable to the current PAdES BASELINE profiles but instead has been designed for an older PAdES-LTV profile (see ETSI TS 102 778-4 section 4 "Profile for PAdES-LTV").
If I understand your question correctly, though, you already know how to evaluate CRLs and OCSP responses. Thus, it would suffice if you learned how to extract the revocation information from the DSS dictionaries.
Your example code apparently uses iText 5.x, so I used the current iText 5.5.14-SNAPSHOT. A bit older versions should be usable with the same code, too.
PdfReader pdfReader = new PdfReader(...);
PdfDictionary dss = pdfReader.getCatalog().getAsDict(PdfName.DSS);
if (dss == null)
System.out.println("No DSS in PDF");
else {
PdfArray crlarray = dss.getAsArray(PdfName.CRLS);
if (crlarray == null || crlarray.size() == 0)
System.out.println("No CRLs in DSS");
else {
System.out.println("CRLs:");
CertificateFactory cf = CertificateFactory.getInstance("X.509");
for (int i = 0; i < crlarray.size(); i++) {
PRStream stream = (PRStream) crlarray.getAsStream(i);
X509CRL crl = (X509CRL)cf.generateCRL(new ByteArrayInputStream(PdfReader.getStreamBytes(stream)));
System.out.printf(" '%s' update %s\n", crl.getIssuerX500Principal(), crl.getThisUpdate());
}
}
PdfArray ocsparray = dss.getAsArray(PdfName.OCSPS);
if (ocsparray == null || ocsparray.size() == 0)
System.out.println("\nNo OCSP responses in DSS");
else {
System.out.println("\nOCSP Responses:");
for (int i = 0; i < ocsparray.size(); i++) {
PRStream stream = (PRStream) ocsparray.getAsStream(i);
OCSPResp ocspResponse = new OCSPResp(PdfReader.getStreamBytes(stream));
if (ocspResponse.getStatus() == 0) {
try {
BasicOCSPResp basicOCSPResp = (BasicOCSPResp) ocspResponse.getResponseObject();
System.out.printf(" '%s' update %s\n", basicOCSPResp.getResponderId(), basicOCSPResp.getProducedAt());
} catch (OCSPException e) {
throw new GeneralSecurityException(e);
}
}
}
}
}
(VerifyLtv test testExtractRevocationInformationCURRENT_SIGNATURE)
Instead of printing information to System.out you can of course collect the CRLs and OCSP responses and process them as you used to.
Also, you can of course check both the revocation data you retrieve from the PdfPKCS7 object and the data from the DSS. Adobe Acrobat also uses both during verification.

Unable to generate certificate request on android through bouncycastle library

I'm now on developing digital signature app on android.
however, I failed to make a apk file because eclipse show following message
[2013-01-27 20:43:25 - BlowfishCipher] Dx
UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.IllegalArgumentException: already added: Lorg/bouncycastle/mozilla/SignedPublicKeyAndChallenge;
[2013-01-27 20:43:25 - BlowfishCipher] Dx at com.android.dx.dex.file.ClassDefsSection.add(ClassDefsSection.java:123)
[2013-01-27 20:43:25 - BlowfishCipher] Dx at com.android.dx.dex.file.DexFile.add(DexFile.java:163)
I know that the error message indicates that duplicated jar files but I don't know how to
solve it since the duplicated jar (Lorg/bouncycastle/mozilla/SignedPublicKeyAndChallenge;) is the core file of the bouncy caslte library.
and follwing java code shows no syntax error but it cause java.lang.IllegalArgumentException: already added exception
package exam.blowfishcipher;
import java.io.FileWriter;
import java.io.OutputStreamWriter;
import java.security.KeyPair;
import java.security.SecureRandom;
import javax.security.auth.x500.X500Principal;
import org.bouncycastle.jce.PKCS10CertificationRequest;
import org.bouncycastle.openssl.PEMWriter;
import android.os.Environment;
import chapter6.PKCS10ExtensionExample;
public class PKCS10Generater
{
public static PKCS10CertificationRequest generateRequest(
KeyPair pair)
throws Exception
{
return new PKCS10CertificationRequest(
"SHA256withRSA",
new X500Principal("CN=Test CA Certificate"),
//new X500Principal("CN=end"),
pair.getPublic(),
null,
pair.getPrivate());
}
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 reqGen() throws Exception
{
//create the keys
/*
KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC");
//KeyPairGenerator kpGen = KeyPairGenerator.getInstance()
kpGen.initialize(512, chapter4.Utils.createFixedRandom());
KeyPair pair=kpGen.generateKeyPair();
*/
//PKCS10CertificationRequest request = generateRequest(pair);
KeyPair pair = chapter8.Utils.generateRSAKeyPair();
PKCS10CertificationRequest request = PKCS 10ExtensionExample.generateRequest(pair);
pemEncodeToFile(Environment.getExternalStorageDirectory()+"pkcs10.req", request, null);
PEMWriter pemWrt = new PEMWriter( new OutputStreamWriter(System.out));
pemWrt.writeObject(request);
pemWrt.close();
}
}
Android already includes BouncyCastle in the system, that is why you are getting the error when trying to add it again (on recent versions it is actually in com.android.org.bouncycastle or some such so you shouldn't get the error, in theory). You have to rename the package of BC if you want to include it in your project (with jarjar, etc.). One project that already does this for you is SpongyCastle. Try using that instead of the regular BC jar.
https://github.com/rtyley/spongycastle

Generate x509certificate certpath in 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();

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.

Java: Invalid keystore format, when generated through code

This has been asked a couple of times, but none provide coded test cases. Here I give an example of the problem:
programmatic generation of a Keystore (works)
creation of certificate within that store (works)
saving keystore to disk (works)
listing keystore with keytool (works)
loading the keystore programmatically (fails with IOException: InvalidKeystoreFormat)
What I dont get is that in both save and load, I use KeyStore.getInstance("JKS"), but its failing. Any suggestions welcome!
Runtime output:
Creating private keystore at 'private.keystore'.
Created keystore, now created signer cert
Created signer cert, saving cert
Reloading keystore:
Failed to load the keystore after creation: Invalid keystore format
Test case source:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import sun.security.x509.X500Name;
public class KeystoreCreator
{
private String fPrivateKeyStore;
private String fPrivateKeyStorePassword;
private String fPrivateKeyStoreKeyPassword;
private String fPublicKeyCipherPassword;
private String fPrivateKeyAlias;
/**
* #param args
* #throws Exception
*/
public static void main(String[] args) throws Exception
{
KeystoreCreator creator = new KeystoreCreator();
creator.setPrivateKeyStore("private.keystore");
creator.setPrivateKeyStorePassword("beer123");
creator.setPrivateKeyAlias("myalias");
creator.setPrivateKeyStoreKeyPassword("beer123");
creator.setPublicKeyCipherPassword("beer123");
creator.initKeyStores();
}
public KeystoreCreator()
{
}
public void setPrivateKeyStore(String name)
{
fPrivateKeyStore=name;
}
public void setPrivateKeyStorePassword(String pass)
{
fPrivateKeyStorePassword=pass;
}
public void setPrivateKeyStoreKeyPassword(String pass)
{
fPrivateKeyStoreKeyPassword=pass;
}
public void setPublicKeyCipherPassword(String pass)
{
fPublicKeyCipherPassword=pass;
}
public void setPrivateKeyAlias(String alias)
{
fPrivateKeyAlias=alias;
}
public void initKeyStores() throws Exception
{
OutputStream out = null;
File f=new File(fPrivateKeyStore);
if (f.exists())
{
f.delete();
if (f.exists())
{
throw new IOException("Want to remove the keystore but can't, still reported as present after removal");
}
}
try
{
System.out.println("Creating private keystore at '" + fPrivateKeyStore + "'.");
out = new FileOutputStream(fPrivateKeyStore);
KeyStore privateKeyStore = KeyStore.getInstance("JKS");
privateKeyStore.load(null, fPrivateKeyStorePassword.toCharArray());
System.out.println("Created keystore, now created signer cert");
X500Name x500name=getCA();
Certificate cert = createCertificate(fPrivateKeyAlias, fPrivateKeyStoreKeyPassword, x500name, privateKeyStore);
System.out.println("Created signer cert, saving cert");
privateKeyStore.store(out, fPublicKeyCipherPassword.toCharArray());
out.flush();
out.close();
//try to load it.
KeyStore reloadedKeyStore = KeyStore.getInstance("JKS");
try
{
InputStream reloadedIs=getClass().getClassLoader().getResourceAsStream(fPrivateKeyStore);
if (reloadedIs!=null)
{
System.out.println("Reloading keystore:");
reloadedKeyStore.load(reloadedIs, fPrivateKeyStorePassword.toCharArray());
}
}
catch (Exception e)
{
System.err.println("Failed to load the keystore after creation: "+e.getLocalizedMessage());
}
}
catch (Exception e)
{
System.err.println("Failed to save the keystore: "+e.getLocalizedMessage());
}
}
private X500Name getCA() throws IOException
{
return new sun.security.x509.X500Name("a","b", "c","d","e", "GB");
}
public Certificate createCertificate( String alias, String keyPassword,
sun.security.x509.X500Name x500Name, KeyStore keyStore ) throws NoSuchAlgorithmException,
InvalidKeyException, CertificateException, SignatureException, NoSuchProviderException,
KeyStoreException {
sun.security.x509.CertAndKeyGen keypair = new sun.security.x509.CertAndKeyGen( "RSA", "MD5WithRSA" );
keypair.generate( 1024 );
PrivateKey privKey = keypair.getPrivateKey();
X509Certificate[] chain = new X509Certificate[1];
chain[0] = keypair.getSelfCertificate( x500Name, 7000 * 24 * 60 * 60 );
keyStore.setKeyEntry( alias, privKey, keyPassword.toCharArray(), chain );
Certificate cert = keyStore.getCertificate( alias );
return cert;
}
}
You create the private key store in the current working directory, by writing to a file: new FileOutputStream(fPrivateKeyStore);
Later, you read from the class path by using getClass().getClassLoader().getResourceAsStream(fPrivateKeyStore);
I think you're reading the wrong files. And there is already another one with the name private.keystore from previous tests. To verify, you may want to print out the absolute file path of both files, e.g. new File(fPrivateKeyStore).getAbsolutePath() and compare it to getClass().getClassLoader().getResource(fPrivateKeyStore).toFileURL();
I may be missing something, but why not just re-load the private key store using FileInputStream?
InputStream reloadedIs = new FileInputStream(fPrivateKeyStore);
(I'm not certain this fixes the problem, I just noticed it while scanning your code)

Categories

Resources