Reputation: 763
I have a SafeNet eToken 5100 USB Token with PDF Digital Signing Certificate on it. I configured a windows and mac system to use it and I succeeded in manually signing PDF files with its certificate on both machines. Thus the certificate works as intended.
I shipped the token to my web host company and they placed it on my Linux (CentOS) server. I installed SafeNet Authentication Client on the server.
Now I'm attempting to use iText to apply the signature. I'm following code sample 4.2 from this excellent book: http://itextpdf.com/book/digitalsignatures. My code is:
String config = "name = eToken5100_20130805\n" +
"library = /usr/lib64/libeTPkcs11.so\n" +
"slot = 0"; // create a dynamic conf file
ByteArrayInputStream bais = new ByteArrayInputStream(config.getBytes());
Provider providerPKCS11 = new SunPKCS11(bais);
Security.addProvider(providerPKCS11);
System.out.println(providerPKCS11.getName());
BouncyCastleProvider providerBC = new BouncyCastleProvider();
Security.addProvider(providerBC);
KeyStore ks = KeyStore.getInstance("PKCS11", providerPKCS11);
ks.load(null, K.PASS_TOKEN);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey)ks.getKey(alias, K.PASS_TOKEN);
Certificate[] chain = ks.getCertificateChain(alias);
OcspClient ocspClient = new OcspClientBouncyCastle();
TSAClient tsaClient = null;
for (int i = 0; i < chain.length; i++) {
X509Certificate cert = (X509Certificate)chain[i];
String tsaUrl = CertificateUtil.getTSAURL(cert);
if (tsaUrl != null) {
tsaClient = new TSAClientBouncyCastle(tsaUrl);
break;
}
}
List<CrlClient> crlList = new ArrayList<CrlClient>();
crlList.add(new CrlClientOnline(chain));
sign(userFile, userFile_signed, chain, pk, DigestAlgorithms.SHA256, providerPKCS11.getName(),
CryptoStandard.CMS, "Test", "Ghent", crlList, ocspClient, tsaClient, 0);
when I run this code, it generates the following runtime error:
stack trace: java.security.KeyStoreException: PKCS11 not found
Caused by: java.security.NoSuchAlgorithmException: no such algorithm:
PKCS11 for provider SunPKCS11-eToken5100_20130805
This link indicates that the wrong keystore type might generate this error. I checked my ~glassfish/java/jdk7u25/jdk1.7.0_25/jre/lib/security/java.security
file and it uses a keystore of jks
. However, changing it to PKCS11
causes my GlassFish server not to restart. So I kept it as jks
.
QUESTION 1: Could this cause the problem? If so, how to resolve?
QUESTION 2: I just made up the name eToken5100_20130805
in the java code above... but does this name need to match some other name somewhere? (the Java code above is the only place I entered this name).
QUESTION 3: I know the library is correct, but how do I determine the slot number? I have manually entered slots 0 through 6 (just guessing) and they each produced the same error shown above. Further, if I enter slot numbers 7 through 10, a PKCS11Exception CKR_SLOT_ID_INVALID is thrown each time.
I don't know much about this topic, but I tried to determine the slot number various ways:
(A) I'm not sure if the following syntax is correct:
# keytool -v -list -keystore NONE -storetype PKCS11 -providername SunPKCS11-eToken5100_20130805 -J-Djava.security.debug=sunpkcs11,pkcs11
but it returns this output:
keytool error: java.security.NoSuchProviderException: no such provider: SunPKCS11-eToken5100_20130805
java.security.NoSuchProviderException: no such provider: SunPKCS11-eToken5100_20130805
at sun.security.jca.GetInstance.getService(GetInstance.java:83)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:206)
at java.security.Security.getImpl(Security.java:698)
at java.security.KeyStore.getInstance(KeyStore.java:661)
at sun.security.tools.KeyTool.doCommands(KeyTool.java:765)
at sun.security.tools.KeyTool.run(KeyTool.java:340)
at sun.security.tools.KeyTool.main(KeyTool.java:333)
(B) I also tried to use modutil to find the slot number:
# modutil -list -dbdir $HOME/.mozilla/firefox/*.default
but I'm not sure what it means when it returns the following:
winscard_clnt.c:420:SCardEstablishContextTH() Your pcscd is too old and does not support CMD_VERSION
winscard_clnt.c:420:SCardEstablishContextTH() Your pcscd is too old and does not support CMD_VERSION
Listing of PKCS #11 Modules
-----------------------------------------------------------
1. NSS Internal PKCS #11 Module
slots: 2 slots attached
status: loaded
slot: NSS Internal Cryptographic Services
token: NSS Generic Crypto Services
slot: NSS User Private Key and Certificate Services
token: NSS Certificate DB
2. eToken
library name: libeTPkcs11.so
slots: 6 slots attached
status: loaded
slot:
token:
slot:
token:
slot:
token:
slot:
token:
slot:
token:
slot:
token:
(C) Lastly, I tried to run
# pkcs11-tool --module /usr/lib64/libeTPkcs11.so --list-slots
but this requires to first install openSC to obtain the pkcs11-tool. When I attempt to install using: # yum install opensc.x86_64
, it gives the following error:
Transaction Check Error:
file /usr/lib64/libpcsclite.so.1.0.0 from install of pcsc-lite-libs-1.5.2-13.el6_4.x86_64
conflicts with file from package libpcsclite1-1.4.0-9.el6.x86_64`
and I can't figure out how to overcome this error.
I could use some help navigating these unfamiliar errors, to understand what the problem is, then how to resolve it. Does it appear the slot number is indeed incorrect (can slot numbers be large, like, 31310? So far I'm assuming they're single digit...), or something else?
---------- UPDATE ----------
My linux machine had a package installed for libpcsclite1
that caused the error described above. I uninstalled SafeNet Auth Client (SAC), removed this package, installed pcsc-lite (using yum), and re-installed the standard SAC. I also installed opensc using yum so I can use pkcs11-tool. I can now see the slot using:
# pkcs11-tool --module /usr/lib64/libeToken.so -L
Available slots:
Slot 0 (0x0): AKS xxxx 00 00
token label: my label
token manuf: SafeNet, Inc.
token model: eToken
token flags: rng, login required, PIN initialized, token initialized, other flags=0x200
serial num : xxxxxxx
Slot 1 (0x1):
(empty)
Slot 2 (0x2):
(empty)
Slot 3 (0x3):
(empty)
Slot 4 (0x4):
(empty)
Slot 5 (0x5):
(empty)
Now I can run everything without generating runtime errors. However, the resulting PDF file displays "At least one signature is invalid". [update: my mistake, I was looking at the wrong file. The signed PDF file shows a valid signature.]
Upvotes: 1
Views: 2438
Reputation: 77606
The keystore used by your JVM is irrelevant in your case. Your keys are stored on your eToken. It's that keystore that you are trying to load when you use these lines:
KeyStore ks = KeyStore.getInstance("PKCS11", providerPKCS11);
ks.load(null, K.PASS_TOKEN);
Hence your question 1 is irrelevant. By the way: when I create the instance of the KeyStore
, I don't pass the provider. What happens if you remove providerPKCS11
? It should find the provider as you're adding it to the Security
instance.
In your config file, you chose the name eToken5100_20130805
and that's fine. You can use any name you want. This answers your question 2.
As for your question 3, there's an example on how to find the slot you need in section 4.1.2 if the book you refer to (and if which I'm the author), but if you need a more simple example, please read the answers to this question on StackOverflow: java keytool with opensc pkcs#11 provider only works with debug option enabled
Note that you have established that the provider works. Your config file is read correctly, otherwise you wouldn't see the name you chose in the exception (SunPKCS11-eToken5100_20130805). The problem is that you can't load the keystore. I've found this post about this problem. I'm not sure if it helps.
In any case: your attempt (A) can never work because keytool
is unaware of the config file and thus unaware of the name you chose. Your attempt (C) fails because of a conflict between tools on Linux. I don't know the modutil
tool you mention in (B), but if I see the output, I would assume that the library to access the token is loaded correctly, and that there are 6 USB slots in the server, but that there is no USB token in any of these slots. Maybe it's as simple as that: maybe your USB token isn't inserted in an USB slot of your server, or maybe it is inserted, but it isn't seen because of a hardware driver problem.
I would check with the hosting company first.
Upvotes: 1
Reputation: 12118
SlotID (in your case specified by slot
variable) is unsigned long integer and it is up to the PKCS#11 library creator to choose what exact value will be used so it may be very hard to just guess the correct value. I am no java expert but by looking at the documentation of Sun PKCS#11 Provider I would say you should rather use slotListIndex
variable which specifies the position in the list of available slots/tokens returned by PKCS#11 library.
Upvotes: 0