Java Access Token PKCS11 Not found Provider - java

Hello I'm trying to access the keystore from my smartcard in Java. And I'm using the following code..
I'm using the Pkcs11 implementation of OpenSc http://www.opensc-project.org/opensc
File windows.cnf =
name=dnie
library=C:\WINDOWS\system32\opensc-pkcs11.dll
Java Code =
String configName = "windows.cnf"
String PIN = "####";
Provider p = new sun.security.pkcs11.SunPKCS11(configName);
Security.addProvider(p);
KeyStore keyStore = KeyStore.getInstance("PKCS11", "SunPKCS11-dnie"); =)(=
char[] pin = PIN.toCharArray();
keyStore.load(null, pin);
When the execution goes by the line with =)(= throws me the following exception
java.security.KeyStoreException: PKCS11 not found
at java.security.KeyStore.getInstance(KeyStore.java:635)
at ObtenerDatos.LeerDatos(ObtenerDatos.java:52)
at ObtenerDatos.obtenerNombre(ObtenerDatos.java:19)
at main.main(main.java:27)
Caused by: java.security.NoSuchAlgorithmException: no such algorithm: PKCS11 for provider SunPKCS11-dnie
at sun.security.jca.GetInstance.getService(GetInstance.java:70)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:190)
at java.security.Security.getImpl(Security.java:662)
at java.security.KeyStore.getInstance(KeyStore.java:632)
I think the problem is "SunPKCS11-dnie", but I don't know to put there. I had tried with a lot of combinations...
Anyone can help me...

I was also getting the error as below:
Caused by: java.security.NoSuchAlgorithmException: no such algorithm: PKCS11 for provider SunPKCS11
I am running the application from a jar through bat file.
I bat file I replaced the code : java - jar sign.jar
with code: java -Djava.security.debug=sunpkcs11,pkcs11 -jar SigningUtility.jar
And it solved the issue.

I am not sure the problem is the name. It looks correct. ColinD's suggestion to pass the Provider instance should rule it out as a problem.
I am guessing that the problem is with the PKCS11 support. Like, you don't have a card in your reader, or the native code cannot access the reader. Have you tried using this driver in conjunction with some "known good" software, like Firefox or Thunderbird's security modules?

Why don't you just pass the Provider directly as the second argument to KeyStore.getInstance(String, Provider). In your code you'd just do:
KeyStore keyStore = KeyStore.getInstance("PKCS11", p);

Try the below code:
// Create instance of SunPKCS11 provider
String pkcs11Config = "name=eToken\nlibrary=C:\\Windows\\System32\\eps2003csp11.dll";
java.io.ByteArrayInputStream pkcs11ConfigStream = new java.io.ByteArrayInputStream(pkcs11Config.getBytes());
sun.security.pkcs11.SunPKCS11 providerPKCS11 = new sun.security.pkcs11.SunPKCS11(pkcs11ConfigStream);
java.security.Security.addProvider(providerPKCS11);
// Get provider KeyStore and login with PIN
String pin = "12345678";
java.security.KeyStore keyStore = java.security.KeyStore.getInstance("PKCS11", providerPKCS11);
keyStore.load(null, pin.toCharArray());
it is working fine for me.

Related

Programmatically compute "SHA-256-Digest-Manifest-Main-Attributes" in jar file?

Because of using HSM hardware we need to sign a jar file w/o actually using Jarsigner. It's all pretty obvious, to the exception of the SHA256 digest of the manifest's main attributes, the attribute "SHA-256-Digest-Manifest-Main-Attributes" in the .SF file.
The main attributes are defined in the manifest specification.
However, I can not seem to find the proper order and/or values to hash. I've been scanning the source code of Jarsigner, but neither can I not find the class reading the attributes.
Does somebody knows how this works ?
[UPDATE: PKCS11 Sun provider]
Using Java PKCS11 provider works, but it yields an empty keystore
name = OpenSC
description = SunPKCS11 w/ OpenSC Smart card Framework
library = /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so
slotListIndex = 0
Code sample
final InputStream inputStream = Signer.class.getClassLoader().getResourceAsStream("opensc-java.cfg");
final SunPKCS11 pkcs11 = new SunPKCS11(inputStream);
final KeyStore ks = KeyStore.getInstance("PKCS11", pkcs11);
ks.load(null, "*****".toCharArray());

Get certificate from keystore not based on alias name in java

I am getting certificates from the keystore based on alias name using the below code,
KeyStore keyStore = KeyStore.getInstance("Windows-MY");
Enumeration aliasesEnum = keyStore.aliases();
while(aliasesEnum.hasMoreElements())
{
aAliasName = (String)aliasesEnum.nextElement();
X509Certificate certificate = (X509Certificate)keyStore.getCertificate(aAliasName);
}
Is there any way to get aliases from the current token instead of getting from keystore?.
Thanks in advance.
It is not possible to get a particular certificate other than knowing the alias.
The best practice would be to have unique alias in your use case, so you will know which certificate you are getting.
If you are storing the Certificate through the KeyStore api, you can do a containsAlias(alias) to see if the alias already exists before you save.
Normally alias names are unique. This is a problem specific to MSCAPI keystore. There are several bug reports (some of them very old) regarding this issue:
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=2162058
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6483657
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8058544
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6672015
Follow the last link, it contains a workaround. You basically have to modify the alias names via reflection API into something unique (see code in link). Not exactly a clean solution, but unfortunately the only way.

Error while decrypting HSM keys using nCipherKM

I am trying to decrypt Database password stored in a Securestorage file. I am using the nCipherKM HSM security provider and the Key Encryption Keys used for decryption is stored in a key store (folder). While I try to load the HSM Key Store by passing the keystore password , it fails to load the key store with the following Exception. Not sure what is the root cause of this error.
Code Snippet:
java.security.provider hsm_provider = (java.security.provider)Class.forName("com.ncipher.provider.km.nCipherKM").newInstance();
java.security.Security.addProvider(hsm_provider);
myKeyStore = KeyStore.getInstance(KeyStore.getDefaulttype,"nCipherKM");
myKeyStore .load(new FileInputStream(KeyStorePath),pwdOfKeyStore);
Exception:
java.io.IOException: A password was supplied but all keys are
module protected. at
com.ncipher.provider.km.KMKeyStore.engineLoad()
Note: Posting this answer to an old question in the hopes of helping others who encounter this same problem.
The root cause could be that the keystore was created with the option to protect the keys with the module. This doesn't mean that a passphrase is optional, it means it is prohibited.
To fix, use the code below
java.security.provider hsm_provider = (java.security.provider)Class.forName("com.ncipher.provider.km.nCipherKM").newInstance();
java.security.Security.addProvider(hsm_provider);
myKeyStore = KeyStore.getInstance(KeyStore.getDefaulttype,"nCipherKM");
myKeyStore .load(new FileInputStream(KeyStorePath),null);
Note: if you attempt to extract the private key from the keystore, you should pass in a null too, like the following:
PrivateKey privateKey = (PrivateKey)keystore.getKey(KEYSTORE_ALIAS, null);

How can I find the implementation and configuration file of PKCS#11

I'm trying to make a program that reads and displays certificate info from the token (Safenet)
but the problem that I face is :
Exception in thread "main" java.security.ProviderException: Error parsing configuration
so I think the problem is in the Configuration file.
How can I make the configration file and also the implementation file so it works correctly.
Thanks
you can able to resolve the error by correcting nss.cfg in %AS_HOME%\domains\nssdomain\config\
you can follow the instructions in the section "Configure Glassfish to Use the NSS Stores" on this page.
Either follow this link also.
In order to work with PKCS#11 in java you need to provide a config file where you at least specify library and name parameter. In this parameters you must specify the path to native library for the token and a arbitrary identifier. Additionally you can add more parameters but they are optional, you can take a look on java pkcs#11 reference guide. I give you a code sample to instantiate a PKCS#11:
// create configuration
String pkcs11nativeLibrary = "/path_to_native_library/library.so";
String pkcs11ConfigSettings = "name = mySmartCard\n" + "library = " + pkcs11nativeLibrary;
byte[] pkcs11ConfigBytes = pkcs11ConfigSettings.getBytes();
final ByteArrayInputStream confStream = new ByteArrayInputStream(pkcs11ConfigBytes);
// instantiate the provider with your config
SunPKCS11 pkcs11Provider = new SunPKCS11(confStream);
Security.addProvider(pkcs11Provider);
// get the keystore
Char[] pkcs11Password = "your_password".toCharArray();
KeyStore myPKCS11KS = KeyStore.getInstance("PKCS11", pkcs11Provider );
myPKCS11KS.load(null, pkcs11Password);
In the sample I put the pkcs11 password directly, however when you try to load a PKCS#11 from some client you have to get the password dinamically in order to do so you can change you key store instance for something like:
// YourCallbackHandler must implements javax.security.auth.callback.CallbackHandler
KeyStore.CallbackHandlerProtection cbhp = new KeyStore.CallbackHandlerProtection(new YourCallbackHandler());
KeyStore.Builder builder = KeyStore.Builder.newInstance("PKCS11", pkcs11Provider, cbhp);
KeyStore myPKCS11KS = builder.getKeyStore();
Hope this helps,

Using keystore with javax.crypto for file encryption/decryption

I was advised to look here: http://exampledepot.com/egs/javax.crypto/DesFile.html for the source code of encryption/decryption using import javax.crypto. I have generated my key via keytool and now I don't know how to pass my generated keys into that application for encryption and decryption.
My situation is, that I have a XML file stored online (it stores configuration details) and before I parse it with a XML parser I have to decrypt it. First of all I should of course encrypt it, before it goes online.
Question is: How to pass my generated keys into code visible in link in first row?
Thanks
How to load a KeyStore is documented in the JavaDoc of the KeyStore class:
import java.io.FileInputStream;
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
// get user password and file input stream
char[] password = getPassword();
try (FileInputStream fis = new FileInputStream("C:/mykeystore.jks")) {
ks.load(fis, password);
}
Once you have loaded the key store you can load the key:
Key myKey = ks.getKey("mykeyalias", password);
The key alias is the one you have specified using keytool.
Using the myKey you can initialize the Cipher instance or use for example a CipherOutputStream / CipherInputStream

Categories