Allora:
questa classe serve per creare un certificato pkcs12 partendo dal certificato della CA:
X509CertificateGenerator.java
public class X509CertificateGenerator {
private X509Certificate caCert;
private RSAPrivateCrtKeyParameters caPrivateKey;
public X509CertificateGenerator()
throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, InvalidKeyException, NoSuchProviderException, SignatureException {
String caFile = "my-ca.p12";
String caPassword = "password";
String caAlias = "super-CA"; // io ho messo queto alias
KeyStore caKs = KeyStore.getInstance("PKCS12");
caKs.load(new FileInputStream(new File(caFile)), caPassword.toCharArray());
// carica la chiave dal keystore
Key key = caKs.getKey(caAlias, caPassword.toCharArray());
if (key == null) {
throw new RuntimeException("Got null key from keystore!");
}
RSAPrivateCrtKey privKey = (RSAPrivateCrtKey) key;
caPrivateKey = new RSAPrivateCrtKeyParameters(privKey.getModulus(), privKey.getPublicExponent(), privKey.getPrivateExponent(),
privKey.getPrimeP(), privKey.getPrimeQ(), privKey.getPrimeExponentP(), privKey.getPrimeExponentQ(), privKey.getCrtCoefficient());
// poi prendo il certificato
caCert = (X509Certificate) caKs.getCertificate(caAlias);
if (caCert == null) {
throw new RuntimeException("Got null cert from keystore!");
}
caCert.verify(caCert.getPublicKey());
}
public boolean createCertificate(String dn, String reparto, int validityDays, String exportFile, String exportPassword) throws
IOException, InvalidKeyException, SecurityException, SignatureException, NoSuchAlgorithmException, DataLengthException, CryptoException, KeyStoreException, NoSuchProviderException, CertificateException, InvalidKeySpecException {
SecureRandom sr = new SecureRandom();
PublicKey pubKey;
PrivateKey privKey;
// genero le chiavi
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024, sr);
KeyPair keypair = keyGen.generateKeyPair();
privKey = keypair.getPrivate();
pubKey = keypair.getPublic();
Calendar expiry = Calendar.getInstance();
expiry.add(Calendar.DAY_OF_YEAR, validityDays);
////////////////////////////////////////
/// Qui vanno i dati del certificato ///
////////////////////////////////////////
X509Name x509Name = new X509Name("CN="+dn+", OU=ASL-Medico, O="+reparto+", L=perugia, ST=italia, C=it");
V3TBSCertificateGenerator certGen = new V3TBSCertificateGenerator();
certGen.setSerialNumber(new DERInteger(BigInteger.valueOf(System.currentTimeMillis())));
certGen.setIssuer(PrincipalUtil.getSubjectX509Principal(caCert));
certGen.setSubject(x509Name);
DERObjectIdentifier sigOID = X509Util.getAlgorithmOID("SHA1WithRSAEncryption");
AlgorithmIdentifier sigAlgId = new AlgorithmIdentifier(sigOID, new DERNull());
certGen.setSignature(sigAlgId);
certGen.setSubjectPublicKeyInfo(new SubjectPublicKeyInfo((ASN1Sequence) new ASN1InputStream(new ByteArrayInputStream(pubKey.getEncoded())).readObject()));
certGen.setStartDate(new Time(new Date(System.currentTimeMillis())));
certGen.setEndDate(new Time(expiry.getTime()));
// attenzione: SHA1+RSA!
SHA1Digest digester = new SHA1Digest();
AsymmetricBlockCipher rsa = new PKCS1Encoding(new RSAEngine());
TBSCertificateStructure tbsCert = certGen.generateTBSCertificate();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
DEROutputStream dOut = new DEROutputStream(bOut);
dOut.writeObject(tbsCert);
// firmiamo
byte[] signature;
// tramite JCE
PrivateKey caPrivKey = KeyFactory.getInstance("RSA").generatePrivate(new RSAPrivateCrtKeySpec(caPrivateKey.getModulus(), caPrivateKey.getPublicExponent(),
caPrivateKey.getExponent(), caPrivateKey.getP(), caPrivateKey.getQ(),
caPrivateKey.getDP(), caPrivateKey.getDQ(), caPrivateKey.getQInv()));
Signature sig = Signature.getInstance(sigOID.getId());
sig.initSign(caPrivKey, sr);
sig.update(bOut.toByteArray());
signature = sig.sign();
// qui creiamo il certificato
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(tbsCert);
v.add(sigAlgId);
v.add(new DERBitString(signature));
X509CertificateObject clientCert = new X509CertificateObject(new X509CertificateStructure(new DERSequence(v)));
clientCert.verify(caCert.getPublicKey());
// esportiamo come PKCS12
PKCS12BagAttributeCarrier bagCert = clientCert;
bagCert.setBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName,new DERBMPString("Certificate for IPSec WLAN access"));
bagCert.setBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_localKeyId,new SubjectKeyIdentifierStructure(pubKey));
KeyStore store = KeyStore.getInstance("PKCS12");
store.load(null, null);
X509Certificate[] chain = new X509Certificate[2];
// prima il client, poi la CA
chain[0] = clientCert;
chain[1] = caCert;
store.setKeyEntry("", privKey, exportPassword.toCharArray(), chain);
FileOutputStream fOut = new FileOutputStream(exportFile);
store.store(fOut, exportPassword.toCharArray());
return true;
}
}
Spero sia chiaro... gli "import" sono tantissimi. Cmq ho usato le librerie di bouncycastle.
Mentre per inserire le chiavi in un keystore patendo da un file PKCS12 ho fatto così:
kStoreCliente.java
public class kStoreCliente {
private String caAlias;
private String caPassword;
private String caFile;
private String aliasIn;
private String storeFile;
private String keyStorePass;
public kStoreCliente(String pass, String fileClienteCert) {
caPassword = pass; //canestro
caFile = fileClienteCert; //caFile = "my-ca.p12";
aliasIn = "cliente";
storeFile = "my-store.keystore";
keyStorePass = "storepass";
caAlias = ""; // l'ho lasciato vuoto per comodità
}
public void creaKStore() {
try {
//Load del file my-ca.p12
KeyStore caKs = KeyStore.getInstance("PKCS12");
caKs.load(new FileInputStream(new File(caFile)), caPassword.toCharArray());
//Test sull'esistenza del keystore
if (new File(storeFile).exists()) {
//Se il keystore esiste effettuo il load
System.out.println("Ho trovato keystore - file: " + storeFile);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream in = new FileInputStream(storeFile);
ks.load(in, keyStorePass.toCharArray());
in.close();
try {
// Estraggo il certificato relativo all'alias CA (aliasIN - vedi dopo)
java.security.cert.Certificate cert = ks.getCertificate(aliasIn);
if (cert != null) {
System.out.println("Trovato certificato di " + aliasIn + " nel keystore - file: " + storeFile);
PublicKey publicKey = cert.getPublicKey();
} else {
System.out.println("Non ho trovato certificato di " + aliasIn + " nel keystore - file: " + storeFile);
}
} //catch (UnrecoverableKeyException e) { System.out.println(e.toString());}
//catch (NoSuchAlgorithmException e) { System.out.println(e.toString()); }
catch (KeyStoreException e) {
System.out.println(e.toString());
} catch (Exception e) {
System.out.println(e.toString());
}
} else {
//Se il keystore non esiste creo un nuovo keystore
System.out.println("Non ho trovato keystore - file: " + storeFile);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
try {
// Get private key
Key key = caKs.getKey(caAlias, caPassword.toCharArray());
if (key instanceof PrivateKey) {
// Get certificate of public key
java.security.cert.Certificate cert = caKs.getCertificate(caAlias);
// Get public key
PublicKey publicKey = cert.getPublicKey();
// Return a key pair
KeyPair keys = new KeyPair(publicKey, (PrivateKey) key);
//inserisco il certificato di my-ca dal file .p12 nel keystore appena creato
//con alias CA
ks.setCertificateEntry(aliasIn, cert);
}
} catch (UnrecoverableKeyException e) {
System.out.println(e.toString());
} catch (NoSuchAlgorithmException e) {
System.out.println(e.toString());
} catch (KeyStoreException e) {
System.out.println(e.toString());
} catch (Exception e) {
System.out.println(e.toString());
}
FileOutputStream out = new FileOutputStream(storeFile);
//Salvo il keystore su file con password
ks.store(out, keyStorePass.toCharArray());
out.close();
System.out.println("Creato keystore - file: " + storeFile);
JOptionPane.showMessageDialog(null, "KeyStore creato con successo", "Successo", JOptionPane.INFORMATION_MESSAGE);
}
} catch (Exception e) {
System.out.println(e.toString());
}
return;
}
}
Spero che queste semplici classi possano essere utili. Per me lo sono state.
PS: è codice grezzo non ci sono grossi controlli. Ma funziona.