We have created a new site for our web where we let the users to sign a pdf document using an applet we have designed. The issue is that this applet works fine only in Windows OS and we would like to extend it to linux OS.
When we run the applet in linux we get this error message:
[opensc-pkcs11] reader-pcsc.c:896:pcsc_detect_readers: SCardListReaders failed: 0x8010002e [opensc-pkcs11] reader-pcsc.c:1015:pcsc_detect_readers: returning with: No readers found [opensc-pkcs11] reader-pcsc.c:896:pcsc_detect_readers: SCardListReaders failed: 0x8010002e [opensc-pkcs11] reader-pcsc.c:1015:pcsc_detect_readers: returning with: No readers found java.security.NoSuchProviderException: no such provider: SunMSCAPI at sun.security.jca.GetInstance.getService(Unknown Source) at sun.security.jca.GetInstance.getInstance(Unknown Source)
I think the problem comes when we try to read the certificated stored in the Windows OS with this call in our code:
KeyStore keystore = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
keystore.load(null, null);
return keystore;
This is te function we use to obtain the list of certificates.
public KeyStore obtenerCertificados() throws Exception {
String osNombre = System.getProperty("os.name");
String osArquitectura = System.getProperty("os.arch");
String providerConfig = null;
String configuracionPKCS11 = null;
// LINUX
if(osNombre.contains(new StringBuffer("Linux")))
providerConfig = "name = OpenSC\nlibrary = /usr/lib/opensc-pkcs11.so\n";
// WINDOWS
else if(osNombre.contains(new StringBuffer("Windows")))
if(!osArquitectura.toLowerCase().contains("x86")){
System.out.println("Estamos en toLowerCase().contains x86");
providerConfig = "name = NSS"+"\n"+
"nssLibraryDirectory = "+"C:/Archivos de programa/Mozilla Firefox"+"\n"+
"nssSecmodDirectory = "+"C:/Users/SM/AppData/Local/Mozilla/Firefox/Profiles/plmk3eh9.default"+"\n"+
"nssDbMode = readOnly" + "\n" +
"nssModule = keystore" + "\n" +
"\r";
}
else{
System.out.println("Estamos en NO toLowerCase().contains x86");
providerConfig = "name = NSS"+"\n"+
"nssLibraryDirectory = "+"C:/Program Files (x86)/Mozilla Firefox"+"\n"+
"nssLibrary = "+"C:/Program Files (x86)/Mozilla Firefox/softokn3.dll"+"\n"+
"nssSecmodDirectory = "+"C:/Users/SM/AppData/Roaming/Mozilla/Firefox/Profiles/plmk3eh9.default"+"\n"+
"nssDbMode = readOnly" + "\n" +
"nssModule = keystore" + "\n" +
"\r";
}
// MAC OS
else {providerConfig = "name = OpenSC\nlibrary = /Library/OpenSC/lib/opensc-pkcs11.so\n";}
ByteArrayInputStream localByteArrayInputStream = new ByteArrayInputStream(providerConfig.getBytes());
SunPKCS11 _pk11provider = null;
try {
_pk11provider = new SunPKCS11(localByteArrayInputStream);
Security.addProvider(_pk11provider);
// _pk11provider.login(new Subject(), new DialogCallbackHandler());
}catch(Throwable e){
System.out.println(e.getMessage());
}
KeyStore keystore = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
keystore.load(null, null);
return keystore;
}
Any ideas about how to extend this use to linux and MAC???
Thanks a lot for your help!!
You can not use SunMSCAPI
provider in Linux or MAC OS X, this provider is Windows specific which deals with Windows keystore. If you want to use a Smart Card or Firefox keystore in Linux or MAC OS X through SunPKCS11
provider you must get an instance of java.security.KeyStore
passing SunPKCS11
as provider, like you are doing with SunMSCAPI
i.e:
ByteArrayInputStream confStream = ...// your configuration
SunPKCS11 pkcs11 = new SunPKCS11(confStream);
Security.addProvider(pkcs11);
KeyStore ks = KeyStore.getInstance("PKCS11", pkcs11);
ks.load(null, "your_pin".toCharArray());
With this code you load on the Keystore ks
the keys from your configured PKCS11.
There is another way to do it if you want that your PKCS11 pin will be introduced by a third party later. To do so you can initialize your keystore with a java.security.KeyStore.CallbackHandlerProtection
parameter like follows:
ByteArrayInputStream confStream = ...// your configuration
SunPKCS11 pkcs11 = new SunPKCS11(confStream);
Security.addProvider(pkcs11);
KeyStore.CallbackHandlerProtection cbhp = new KeyStore.CallbackHandlerProtection(new PinInputHandler(msg));
KeyStore.Builder builder = KeyStore.Builder.newInstance("PKCS11", pkcs11, cbhp);
builder.getKeyStore();
Note that PinInputHandler
in this second sample must implements: javax.security.auth.callback.CallbackHandler
.
Additionally in your code seems that you never loads the PKCS11 keys through SunPKCS11
provider (even in Windows case) because you are not instantiating a keystore with SunPKCS11
you are only adding it as a provider with Security.addProvider
method and always you are instantiating only a keystore with SunMSCAPI
, however probably in Windows you are getting some of your Smart cards keys because if you install Windows drivers for you smart card you can get their keys through Windows keystore.
Hope this helps,
User contributions licensed under CC BY-SA 3.0