We are using SunMSCAPI to retrieve the current user keystore as below..
keystore = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
We will need to build a JSSE keystore of type JKS/PKCS12 and pass it to an app..
Sort of beginning to understand how this works.. Any help would be appreciated.
Did you try something like
keystore.load(inputStreamFromOriginalFile, password);
KeyStore keystore2 = KeyStore.getInstance("JKS");
for (String name : toIterable(keystore.aliases())) {
Entry entry = keystore.getEntry(name, protParam);
keystore2.setEntry(name, entry, protParam);
}
keystore2,store(outputStream, password);
I mean a dump copy of all entries into a new keystore2.
Related
I have a Java keystore file using the storetype JCEKS. It contains SecretKeyEntry entries. I would like to be able to dump, from the command line, the actual secret keys stored in this file. I tried this:
keytool -list -keystore secretkeys.jks -storetype JCEKS
which returned
Keystore type: JCEKS
Keystore provider: SunJCE
Your keystore contains 1 entry
secret1, May 27, 2016, SecretKeyEntry
But that does not show me the key itself. How can I extract and look at, from the command line, the secret key?
This is not possible with keytool.
Converting the keystore to PKCS#12 and then using OpenSSL to view the key doesn't work either, because this is a symmetric key (SecretKeyEntry).
If you are stuck with the command line, you could write a small Java program that does it. Something like this:
String fileName = "secretkey.ks";
char[] password = "mypassword".toCharArray();
String alias = "secret1";
KeyStore ks = KeyStore.getInstance("JCEKS");
try (FileInputStream fis = new FileInputStream(fileName)) {
ks.load(fis, password);
SecretKey secretKey = (SecretKey) ks.getKey(alias, password);
System.out.println(new BigInteger(1, secretKey.getEncoded()).toString(16));
}
This prints out the secret key as a hex string (toString() with radix 16).
Or you could use the GUI program KeyStore Explorer.
I extracted a Key and its certification chain from a JKS, and now I'm trying to add this key to the Windows Keystore using Java.
To load my JKS I did the following:
String jksPath = "D:\\mykeystore.jks";
KeyStore keystore = KeyStore.getInstance("JKS");
FileInputStream fIn = new FileInputStream(jksPath);
keystore.load(fIn, "12345678".toCharArray());
Then I get the key and the certification chain:
Key key = keystore.getKey("res1", "12345678".toCharArray());
Certificate[] cchain = keystore.getCertificateChain("res1");
So far so good, then I try to add this key to my Windows Keystore:
KeyStore ks = KeyStore.getInstance("Windows-MY");
ks.load(null, null);
ks.setKeyEntry("myKey", key, "12345678".toCharArray(), cchain);
And BOOM:
Exception in thread "main" java.lang.ClassCastException: [Ljava.security.cert.Certificate; cannot be cast to [Ljava.security.cert.X509Certificate;
at sun.security.mscapi.KeyStore.engineSetKeyEntry(KeyStore.java:402)
at sun.security.mscapi.KeyStore$MY.engineSetKeyEntry(KeyStore.java:62)
at java.security.KeyStore.setKeyEntry(KeyStore.java:909)
Exception thrown due to the setKeyEntry call.
P.S: when I use the same syntaxe on a JKS type of Keystore no exception is thrown.
It seems there's a clumsy bit of java code in the implementation of sun.security.mscapi.KeyStore.engineSetKeyEntry(). It tries to convert an array of Certificates ("[Ljava.security.cert.Certificate", notice the prefix in the class name) to an array of X509Certificates (" [Ljava.security.cert.X509Certificate"), which is not something java ever allows you to do with a simple cast expression (e.g. see discussion of a similar mistake).
All I did in a similar situation is to pass the certificate array to the keyStore.setKeyEntry() method call as a X509Certificate array, rather than a simple Certificate array.
I am working with digital certificate and digital signature. We got pfx file from the vendor. We convert this pfx file to java key store and used it to create the digital signature using java program. Now the vendor has etoken hardware. They give me cer file in place pf pfx. I converted cer to jks java key store and used it in my program... My program told me that private key is not there. I have found that there is no private key with cer file. I have talked to vendor about this he told me private key can not be extracted from the etoken.. you must directly access the etoken through program to get the private key. Can anybody tell me how do i access etoken programetically. Is there any java api which is used to access etoken directly. Help me....
Private key can be extracted using PKCS11.
To extract Private key from eToken in java, you need to pass config file to sun.security.pkcs11.SunPKCS11 instance.
Config file must have following properties:
name=<Name of Etoken>
slot=<slot number for etoken>
library=<path of the pckcs11 library(dll) for that etoken>
Following is sample code to extract private key using eToken
PrivateKey privateKey = null;
char password[] = "1234".toCharArray();
Provider userProvider = new sun.security.pkcs11.SunPKCS11("D:\\config.cfg");
ks = KeyStore.getInstance("PKCS11", userProvider);
ks.load(null, password);
Enumeration e = ks.aliases();
String alias=null;
while (e.hasMoreElements())
{
alias = (String) e.nextElement();
privateKey = (PrivateKey) ks.getKey(alias, password);
}
I have a keystore.jks file with multiple certificate including public and private key.
now i want to know how to export all public key certificate into new file all-public-cert.crt file.
This "all-public-cert.crt" file contain only certificate (public key only) . should not contain any private key in this file.
after this i would like to ready this "all-public-cert.crt" file via java code and validate public and private key using challenge response.
kindly guide me or suggest me some reference document or url.
Note : i am able to use any tool like openssl or keytool.
Thanks & Regards,
Gaurav Paliwal
Normally a keystore i.e., your keystore.jks contains private keys and the corresponding X.509 certificates. But the X.509 certificates do NOT include a private key, as you falsely assumed:
I have a keystore.jks file with multiple certificate including public and private key
This "all-public-cert.crt" file contain only certificate (public key only) . should not contain any private key in this file.
This means that your X.509 certificates do only contain public key information, no private key information.
In order to fetch a certificate form your keystore (leaving the error handling aside):
String keystorePath = ....
InputStream is = new FileInputStream(new File(keystorePath));
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(is, "keystorePassword".toCharArray());
Enumeration e = ks.aliases();
Set<Certificate> certs = new HashSet<Certificate>();
while (e.hasMoreElements()) {
Certificate cert = ks.getCertificate((String) enumeration.nextElement());
certs.add(cert);
}
Now you have all certificates in your certs Set. But why do you need to put them all into the all-public-cert.crt.
1.) First you cannot put multiple certificates in one file, and hope that the one file can be used the "normal" way (e.g. double click to open it, import it into other applications, ..). The file will be garbage and can only be read from e.g., your application
2.) Therefore the file extension should not be .crt, it should be .myExportedCertificates or something like that.
I think you just want to store the certificates on the file system in order to use them afterwards. In this case simply use this code (error handling is your job):
String pathToStoreTheCerts = ...
File path = new File(pathToStoreTheCerts);
OutputStream os = null;
for (X509Certificate cert : certs) {
File certFile = new File(path, cert.getSubjectX500Principal().getName() + ".crt");
os = new FileOutputStream(certFile);
os.write(cert.getEncoded());
os.flush();
}
os.close();
As the title suggests, I have .p12 file required for google service account api access. In order to get the credential to connect to the api, there's a field .setServiceAccountPrivateKey(PrivateKey privateKey). So, what's the easiest way in which I can do this? I have a resources folder which is in my classpath so if I add the p12 file there, I can get the resource from getClass().getResource() as either an inputStream or a URL. I've tried the URL method but it doesn't work (I get a "URI is not hierarchical" error trying to create a File object from URL.toURI()).
You can load your .p12 file using the ClassLoader.getResourceAsStream(String) method, load it to a KeyStore and them get the key from the KeyStore.
KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(this.getClass().getClassLoader().getResourceAsStream("keyFile.p12"), p12Password.toCharArray());
PrivateKey key = (PrivateKey)keystore.getKey(keyAlias, p12Password.toCharArray());
ClassLoader.getResourceAsStream(String) loads resources from any location provided they're already on the classpath, there's no need to specify a path to the file.
keyAlias is the name of the entry in your p12 file that corresponds to the private key. PKCS12 files can contain multiple entries, so you need some way to indicate which entry you want to access. The alias is how this is achieved.
If you're not sure what the alias for your private key is, you can use the keytool utility from the command line to list the contents of your p12 file. This tool is included with all JRE and JDK installations.
keytool -list -keystore keyFile.p12 -storepass password -storetype PKCS12
Output
Keystore type: PKCS12
Keystore provider: SunJSSE
Your keystore contains 1 entry
yourKeyAlias, Sep 4, 2013, PrivateKeyEntry,
Certificate fingerprint (MD5): 48:A8:C4:12:8E:4A:8A:AD:58:81:26:90:E7:3D:C8:04
I think it's easier to call Google's SecurityUtils directly, e.g.:
PrivateKey privateKey = SecurityUtils.loadPrivateKeyFromKeyStore(SecurityUtils.getPkcs12KeyStore(), this.getClass().getResourceAsStream("keyFile.p12"), "notasecret", "privatekey", "notasecret")
It's one-line and you don't have to worry about aliasing.
If you get null from getKey() (eg. you are using BouncyCastle as a provider) you should find the last keyAlias element:
KeyStore keystore = KeyStore.getInstance("PKCS12", "BC");
keystore.load(this.getClass().getClassLoader().getResourceAsStream("keyFile.p12"), p12Password.toCharArray());
Enumeration aliases = keystore.aliases();
String keyAlias = "";
while (aliases.hasMoreElements()) {
keyAlias = (String) aliases.nextElement();
}
PrivateKey key = (PrivateKey)keystore.getKey(keyAlias, pass);
The above suggestions did not work for me. Then I tried the one at http://www.java2s.com/Code/Java/Security/RetrievingaKeyPairfromaKeyStore.htm and it worked. Copy pasting it below
import java.io.FileInputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
public class Main {
public static void main(String[] argv) throws Exception {
FileInputStream is = new FileInputStream("your.keystore");
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(is, "my-keystore-password".toCharArray());
String alias = "myalias";
Key key = keystore.getKey(alias, "password".toCharArray());
if (key instanceof PrivateKey) {
// Get certificate of public key
Certificate cert = keystore.getCertificate(alias);
// Get public key
PublicKey publicKey = cert.getPublicKey();
// Return a key pair
new KeyPair(publicKey, (PrivateKey) key);
}
}
}