How to access certificates and private key from etoken using java - java

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);
}

Related

How to add a private key to Windows Cert Store programmatically

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.

Not able to access Private key from PKCS12 file using java

I have created a pkcs12 file having a private key entry without any password.
I am able to access the p12 file using keytool utility without providing any password.
The same I am not able to to programmatically.
When I am trying like below
if( keyStore.isKeyEntry(KEYSTORE_ALIAS)) {
key = (PrivateKey) keyStore.getKey(KEYSTORE_ALIAS,new char[0]);
}
I am getting the below exception
Caused by: javax.crypto.BadPaddingException: Given final block not
properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.PKCS12PBECipherCore.implDoFinal(PKCS12PBECipherCore.java:355)
at com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndDESede.engineDoFinal(PKCS12PBECipherCore.java:387)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at sun.security.pkcs12.PKCS12KeyStore.engineGetKey(PKCS12KeyStore.java:266)
... 2 more
key = (PrivateKey) keyStore.getKey(KEYSTORE_ALIAS,new char[0]);
That's not the correct way to specify no key. Here you are specifying a zero-length key. It isn't the same thing. Try this:
key = (PrivateKey) keyStore.getKey(KEYSTORE_ALIAS, null);

Create a .jks file from a Certificate and private Key

I wanted to create a .jks file using a Certificate and a private Key from an etoken programmatically.
I could access the etoken using the password but could not read the Certificate or the private key.
In an earlier question I had asked whether the private Key could be extracted from the etoken for which I was told it was not possible.
So, my question is whether I could get the reference of the private key using PKCS11..
Thank you.
You can get the reference (object handle) of the PrivateKey using PKCS11. You can even get the public components of the PrivateKey. But you cannot extract the sensitive data that comprises the key.

programatically reading java keystore file jceks using openssl

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).

How to export multiple public certificate in one crt file

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();

Categories

Resources