programatically reading java keystore file jceks using openssl - java

I am trying to do the AES encryption/decryption in java
I generated the secretkey using KeyGenerator. I stored the key using java keystore.
Key myKey = KeyGenerator.getInstance("AES").generateKey();
KeyStore.ProtectionParameter protParam =
new KeyStore.PasswordProtection("secretpass".toCharArray());
//For writing the secret Key
KeyStore.SecretKeyEntry skEntry =
new KeyStore.SecretKeyEntry((SecretKey)myKey);
FileOutputStream fout = new FileOutputStream("test.ks");
KeyStore ksout = KeyStore.getInstance("JCEKS");
ksout.load(null,"changeit".toCharArray());
ksout.setEntry("secretalias", skEntry, protParam);
I wanted to get this secretkey from this file using openssl programatically. Is it possible? If so, please give me some suggestions on how do I proceed.
Thank you in advance.

This is not possible as the default keystore (jks) is a proprietary format used by Java.
To exchange the key you would need something portable like PKCS#11 (which is a supported KeyStore format at least in Java 8).

Related

How to store & get own screct key in Java 8 PKCS12 keystore

I am trying to store my own secret key in PKCS12 keystore. I tried by using below code:
char[] passArray = "password".toCharArray();// this is key store pass
String key = "test123"; // this is my own secret key
// Loading a Keystore
KeyStore p12KeyStore = KeyStore.getInstance("PKCS12");
p12KeyStore.load(new FileInputStream("testKeyStore.p12"), passArray);
Storing my own secret key like as shown below:
byte [] byteKey = key.getBytes();
SecretKeySpec keySpec = new SecretKeySpec(byteKey, "DSA");
KeyStore.SecretKeyEntry secret = new KeyStore.SecretKeyEntry(keySpec);
KeyStore.ProtectionParameter password = new KeyStore.PasswordProtection(passArray);
p12KeyStore.setEntry("secret-key", secret, password);
but i am not sure whether storing the my own secret key as per best practice or not. and also when trying to get my own key from keystore as it is not getting like as my original secret key.
Key eKey = p12KeyStore.getKey("secret-key", passArray);
Can anyone please help me on this to store & get my own secret in PKCS12 keystore?
Are you sure the code you have above worked? Because DSA is a asymmetric algorithm, not a symmetric algorithm. If you are sure it is a secret key, it has to be AES or DES or DESede (Triple DES). Your above code should have failed.
And answers to your questions:
Just like databases stores data, keys (secret keys and key pairs) and certificates are meant to be stored in a keystore, that's where they should residing in your application. You should be referring/retrieving them from the keystore.
And from what you said in one of the statements, that the key is different from what you had originally when you stored and then retrieved, judging by this, I think the key you have is a Triple DES or a DES key. DES/TripleDES uses parity bits, and the parity bits are corrected by the Java API SecretKeySpec. This causes the key to look different from the original, but it is actually the same. You can read more about the parity bits here.
And as a best practice you shouldn't be storing the secret keys in a PKCS12 Keystore. The internet standard defines that the PKCS12 keystore should contain only one KeyPair entry associated with its certificate chain. Even though it can contain more than one entry, it is ideal to have only one entry, with the key password same as the keystore password. They can store secret keys too, but it is best if you store them in a JCEKS keystore format.

Unable to decrypt csv file using symmetric key java

I am provided two files encrypted_key.enc and encrypted_data.csv.enc. I need to use my private key to decrypt the encrypted_key.enc to get a symmetric key and then use that symmetric key to decrypt the encrypted_data.csv.enc file.
On the terminal, the following commands get the job done:
openssl rsautl -decrypt -ssl -inkey my_private_key -in encrypted_key.enc -out key
openssl aes-256-cbc -d -in encrypted_data.csv.enc -out secret.txt -pass file:key
My goal is to perform the java equivalent of the two commands. I was able to successfully decrypt the first file and retrieve the symmetric key.
Now I'm unable to use that symmetric key to decrypt the csv file. My issue arises in the decipher.init(Cipher.DECRYPT_MODE, keySpec); I receive the following stacktrace
Exception in thread "main" java.security.InvalidKeyException: Illegal key size or default parameters
I'm unclear on what exactly I'm missing from the decryption process. I've tried changing the cipher provider but that didn't help. Other posts have posted solutions using an IVParameterSpec but my decryption case doesn't seem to need it or I'm confused on where to put it.
File file = new File("my_private_key");
PrivateKey pk = getPrivateKey(file);
// Decrypt secret key
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, pk);
File skFile = new File("encrypted_key.enc");
FileInputStream fileInputStream = new FileInputStream(skFile);
byte[] decodedBytes = IOUtils.toByteArray(fileInputStream);
byte[] original = cipher.doFinal(decodedBytes);
String decodedOriginal = new String(Base64.encodeBase64(original));
System.out.println(decodedOriginal);
// Use the secret key for decrypting file
File csvFile =
new File(
"encrypted_data.csv.enc");
FileInputStream csvIS = new FileInputStream(csvFile);
Cipher decipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(original, "AES");
decipher.init(Cipher.DECRYPT_MODE, keySpec);
byte[] csvOriginal = decipher.doFinal(IOUtils.toByteArray(csvIS));
String csvContents = new String(csvOriginal);
System.out.println(csvContents);
Before Java 1.8 (I think, somewhere around there) you are limited by the Java Unlimited Strength Policy for key sizes above 128-bits. This is the most likely cause of the exception you are getting.
Unfortunately this won't fix your code. openssl with the pass flag uses an insecure KDF named EVP_BytesToKey(). Java doesn't natively support this KDF. You don't want to use it anyway since it is insecure. Update the upstream code to use a better KDF like PBKDF2. There is native support for this in Java.
Further, you're using CBC mode in openssl and ECB mode in Java. And you aren't specifying an IV in openssl. I get the impression you didn't write the Java code yourself. You might benefit from taking the time to learn and research what is actually happening in your code and in the commands you are executing and you might be better equipped to solve the problem.

How to decrypt a pkcs8 encrypted private key using bouncy castle?

i am trying to decrypt a pkcs8 encrypted private key using bouncy castle library. I parsed the file containing the private key using PEMParser provided by bouncy castle. I got PKCS8EncryptedPrivateKeyInfo object. I am unable to get the PrivateKeyInfo object from this.
I am getting the following exception while trying to decrypt.
org.bouncycastle.pkcs.PKCSException: unable to read encrypted data: 1.2.840.113549.1.5.13 not available: No such provider: 1.2.840.113549.1.5.13
here is the code which I used
PEMParser parser = new PEMParser(br);
PKCS8EncryptedPrivateKeyInfo pair = (PKCS8EncryptedPrivateKeyInfo)parser.readObject();
JceOpenSSLPKCS8DecryptorProviderBuilder jce = new JceOpenSSLPKCS8DecryptorProviderBuilder();
jce.setProvider("1.2.840.113549.1.5.13");
InputDecryptorProvider decProv = jce.build(password.toCharArray());
PrivateKeyInfo info = pair.decryptPrivateKeyInfo(decProv);
Have you tried with jce.setProvider("BC"); instead of jce.setProvider("1.2.840.113549.1.5.13");
Edit to add solution provided by #PeterDettman :
In addition to use jce.setProvider("BC"); also install the BC provider bouncycastle.org/wiki/display/JA1/Provider+Installation
Security.addProvider(new BouncyCastleProvider());
thats whats missing

How to convert JKS certs/keys to BouncyCastle certs/keys

In my java app I have a JKS keystore with a self-signed cert/key. I need to load them and convert them to BouncyCastle types.
I am using java.security.KeyStore to load the cert/key which gives me java.security.cert.Certificate and java.security.Key.
How do I then convert these to a format that BouncyCastle uses (org.bouncycastle.asn1.x509.Certificate etc.)
If I use Security.addProvider(new BouncyCastleProvider()); will that make the KeyStore return different types???
Or does BC have it's own KeyStore API (note: the keystore is in JKS/SUN format).
Thanks
I figured it out, here is some pseudo code.
To convert certs:
byte data[] = java.security.cert.Certificate.getEncoded();
org.bouncycastle.asn1.x509.Certificate.getInstance(data);
To convert keys:
byte data[] = java.securty.Key.getEncoded();
if (isRSA) {
RSAPrivateKey rsa = RSAPrivateKey.getInstance(data);
return new RSAPrivateCrtKeyParameters(rsa.getModulus(), rsa.getPublicExponent(),
rsa.getPrivateExponent(), rsa.getPrime1(), rsa.getPrime2(), rsa.getExponent1(),
rsa.getExponent2(), rsa.getCoefficient());
} else {
return PrivateKeyFactory.createKey(data);
}

Is there a way to extract secret key from NSS

I am using NSS as my keystore. I have generated a secret key which i use for encrypting/decrypting sensitive data (using AES) and all works fine.
For portability, is there a way in which this secret key can be extracted and inserted back to a different NSS DB?
I am using jre6 with SunPKCS11 provider. I am generating key as follows
KeyStore ks = //get NSS keystore
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128);
SecretKey skey = kg.generateKey();
ks.setEntry(SECREY_KEY, new KeyStore.SecretKeyEntry(skey),
new KeyStore.PasswordProtection(pw.toCharArray()));
Try the NSS toolkit, it has a utility to extract PKCS#12 keys from NSS keystores:
http://www.mozilla.org/projects/security/pki/nss/tools/

Categories

Resources