I need to convert a JKS (password protected) in to a .PEM containing the KeyPairs (or selected alias) for other services to use.
So far, I have written this:
#Transactional
public ResponseEntity<String> getPublicKeyFromJKS(long jksid) {
try {
//1. Lift the entity
JKSFile jksFile = jksFileRepo.getOne(jksid);
//2. Get the Object from S3
S3Object object = getS3ObjectService.getS3Object(jksFile.getS3ObjectKey());
System.out.println(object.getObjectContent().getHttpRequest());
InputStream in = object.getObjectContent();
//3. Make KeyStore...
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(in, rsaConfig.getKeystorePassword().toCharArray());
//4. Get keys to PEM formatted file.
PrivateKey privateKey = (PrivateKey) keyStore.getKey("access", rsaConfig.getKeystorePassword().toCharArray());
Certificate certificate = keyStore.getCertificate("access");
PublicKey publicKey = certificate.getPublicKey();
KeyPair keyPair = new KeyPair(publicKey, privateKey);
System.out.println(keyPair.getPrivate().toString());
System.out.println(keyPair.getPublic().toString());
I am pulling the requested JKS from my amazon S3 bucket and reading the Private and Public key without issue...but I would now like to be able to put them in to a PEM formatted keystore (for use by another service).
Thanks for any suggestions! I want this programatically...not using the java command line keytool.
Related
void createKeyStore(String alias) throws Exception {
if(keyStoreType == null || keyStoreType.isEmpty()){
keyStoreType = KeyStore.getDefaultType();
}
keyStore = KeyStore.getInstance(keyStoreType);
KeyPair kp = generateRSAKeyPair();
Certificate[] certChain = new Certificate[1];
certChain[0] = generateCertificate(kp);
//load
char[] pwdArray = keyStorePassword.toCharArray();
keyStore.load(null, pwdArray);
keyStore.setKeyEntry(alias, kp.getPrivate(), keyStorePassword.toCharArray(), certChain);
// Save the keyStore
FileOutputStream fos = new FileOutputStream(keyStoreName,true);
keyStore.store(fos, pwdArray);
fos.close();
}
Using this function for create and write multiple alias in keystore
In the first request it create keystore file and store the alias with private key and certificate but in the second request with alias it not storing any data in same keystore file.
I am working on a Java project. I have created certificate using my function but now I have only one certificate . I am expecting to store multiple alias in the same file but it happen only with first request but not with second request.
I would like to save a X509Certificate and its private key into the Android KeyStore, I tought I should 'merge' the X509Certificate (containing the public key) and its private key. The private key is used to create a CSR and then a server party sign the certificate and return to the application, can I merge the cert and the private key into one unique cert? Also I'm using spongycastle (aka bouncycastle's android wrapper).
I have no idea about Android KeyStore, but maybe you can try something like:
PrivateKey privateKey = ... //this is what you already have
X509Certificate certificate = ... //this is what you already have
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
Certificate[] certChain = new Certificate[1];
certChain[0] = certificate;
char[] myKeyPassword = "myKeyPassword".toCharArray();
keyStore.setKeyEntry("mykeyalias", (Key)privateKey, myKeyPassword, certChain);
See https://docs.oracle.com/javase/9/docs/api/java/security/KeyStore.html#setKeyEntry-java.lang.String-java.security.Key-char:A-java.security.cert.Certificate:A- for more information about KeyStore.setKeyEntry
Is there any way to return a file to client with .p12 extension (base64 encoded string, that is later decoded on the client side and saved with .p12 extension) without storing it to PKCS12 keystore? I have code for creating root certificate, client certificate and setting keyentry to PKCS12 keystore bellow, but I don't want to have .p12 file on the file system, just to generate it and return it to client. Thanks!
Simplified code of creating root certificate:
public static void createRootCertificate(PublicKey pubKey, PrivateKey privKey) {
certGen.setSerialNumber(...);
certGen.setIssuerDN(...);
certGen.setNotBefore(...);
certGen.setNotAfter(...);
certGen.setSubjectDN(...);
certGen.setPublicKey(pubKey);
certGen.setSignatureAlgorithm("SHA1WithRSA");
// add extensions, key identifier, etc.
X509Certificate cert = certGen.generateX509Certificate(privKey);
cert.checkValidity(new Date());
cert.verify(pubKey);
}
The root certificate and its private key is saved to the trusted store after creating.
Than, in the service for generating client certificates, I read root certificate from trusted store and generate client ones:
public static Certificate createClientCertificate(PublicKey pubKey) {
PrivateKey rootPrivateKey = ... //read key from trusted store
X509Certificate rootCertificate = ... //read certificate from trusted store
certGen.setSerialNumber(...);
certGen.setIssuerDN(...); // rootCertificate.getIssuerDN ...
certGen.setNotBefore(...);
certGen.setNotAfter(...);
certGen.setSubjectDN(...);
certGen.setPublicKey(pubKey);
certGen.setSignatureAlgorithm("SHA1WithRSA");
// add extensions, issuer key, etc.
X509Certificate cert = certGen.generateX509Certificate(rootPrivateKey);
cert.checkValidity(new Date());
cert.verify(rootCertificate.getPublicKey(););
return cert;
}
Main class look like this:
public static void main(String[] args) {
// assume I have all needed keys generated
createRootCertificate(rootPubKey, rootPrivKey);
X509Certificate clientCertificate = createClientCertificate(client1PubKey);
KeyStore store = KeyStore.getInstance("PKCS12", "BC");
store.load(null, null);
store.setKeyEntry("Client1_Key", client1PrivKey, passwd, new Certificate[]{clientCertificate});
FileOutputStream fOut = new FileOutputStream("client1.p12");
store.store(fOut, passwd);
}
After the code above, I'm reading client1.p12 and I'm creating Base64 encoded response of that file. When I decode response on my client and save with .p12 extension everything works, I can import it to browser. Can this be done without storing it to file?
I have tried with:
store.setKeyEntry("Client1_Key", client1PrivKey, passwd, new Certificate[]{clientCertificate});
and after that:
Key key = store.getKey("Client1_Key", passwd);
but when encode key variable, send to client and than decode it and save with .p12 extension, browser say invalid or corrupted file.
Thanks in advance!
Simply use a ByteArrayOutputStream instead of FileOutputStream to store the p12:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
store.store(baos, passwd);
byte[] p12Bytes = baos.toByteArray();
String p12Base64 = new String(Base64.encode(p12Bytes));
I am trying to encrypt a text file using a .pfx certificate file using :
public void EncryptUsingPublicKey(File in, File out, File publicKeyFile) throws IOException, GeneralSecurityException {
byte[] encodedKey = new byte[(int)publicKeyFile.length()];
new FileInputStream(publicKeyFile).read(encodedKey);
// create public key
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedKey);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pk = kf.generatePublic(publicKeySpec);
FileInputStream is = new FileInputStream(in);
Cipher pkCipher = Cipher.getInstance("RSA");
pkCipher.init(Cipher.ENCRYPT_MODE, pk);
CipherOutputStream os = new CipherOutputStream(new FileOutputStream(out), pkCipher);
copy(is, os);
os.close();
}
I have two problems:
Where should I store the .pfx file on the device?
Is this function correct?
I don't think that your code will work. PFX files are internally AFAIR PKCS#12 files with can contain multiple certificates and keys. The X509EncodedKeySpec you are using requires to have exactly one certificate in a .CER file (DER/binary format).
Therefore you have the following two options:
Extract the certificate from the PFX file as CER file (e.g. with the GUI tool portecle) or
Try to read the PFX file as a PKCS#12 KeyStore at it is presented here: PKCS12 Java Keystore from CA and User certificate in java
In the end you can include the PFX/CER file as resource into your andoid app: Load file from resource
I have the following code to export certificates and keys from a keystore, that I created with keytool in Windows:
final KeyStore keystore = KeyUtil.loadKeystore("keystore.jks", "pass");
UserInfo userinfo = new UserInfo(WSusername, WSpassword);
X509Certificate clientcert = KeyUtil.getCertificate(CLIENT_KEY_ALIAS, keystore);
X509Certificate servercert = KeyUtil.getCertificate(SERVER_KEY_ALIAS, keystore);
PrivateKey clientprivate = KeyUtil.getPrivateKey(CLIENT_KEY_ALIAS, CLIENT_KEY_PASSWORD, keystore);
Yet it fails at the last line with "unable to retrieve private key for signing"
It can retrieve the clientcert, but when it tries clientprivate, it fails.
My problem was that when I generated the keystore with keytool, it did not create the PrivateKey as a key entry. To fix this, I imported the .p12 keystore as the private key, which worked. My original code above then worked.