SunPKCS11 - does anyone used it or *really* know how it works?
Hi guys,
I need to develop an app to access security devices (tokens, smartcards) and I know that Sun included on Tiger this SunPCKS11 provider to access those devices through PKCS#11 interface.
Well, I've read the "JavaTM PKCS#11 Reference Guide" and understood how it works and how to configure it, but I couldn't realize what is actually needed to gain access to some cryptographic hardware (libraries, .DLLs, .SOs, policy files, etc) using this provider.
In short, anyone who already used or knows something else about SunPKCS11 provider could give some light?
Thanks,
Henrique Viecili
[628 byte] By [
viecilia] at [2007-10-1 20:11:39]

I磛e coded the sample test class below using SunPKCS11 and BouncyCastle (CMS) to access the e-Token (Aladdin) and sign some data, but I got org.bouncycastle.cms.CMSException: key inappropriate for signature. when I was trying to sign data.
How can I get the appropriate key for signing?
public class AssinadorPKCS11 {
public static final String ETOKEN_CONFIG = "config/eToken.properties";
private static String _msgSolicitaPIN = "Por favor informe seu PIN (N鷐ero de Identifica玢o Pessoal)" +
" para acessar seus certificados no Token";
private static String _titSolicitaPIN = "Login - eToken";
private static String _msgSelecionaAlias = "Selecione uma identidade abaixo";
private static String _titSelecionaAlias = "Identidades";
protected Provider provider;
protected KeyStore keyStore;
protected String alias;
/** Creates a new instance of AssinadorPKCS11 */
public AssinadorPKCS11() throws PKCS11Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
provider = new sun.security.pkcs11.SunPKCS11(ETOKEN_CONFIG);
Security.addProvider(provider);
login();
}
public byte[] sign(byte[] dados) throws PKCS11Exception {
byte[] saida = new byte[0];
setAlias();
try {
Certificate cert = keyStore.getCertificate(alias);
PrivateKey key = (PrivateKey) keyStore.getKey(alias, null);
Certificate[] chain = keyStore.getCertificateChain(alias);
CertStore certStore = CertStore.getInstance("Collection",new CollectionCertStoreParameters(Arrays.asList(chain)));
CMSSignedDataGenerator sdatagen = new CMSSignedDataGenerator();
sdatagen.addSigner(key, (X509Certificate) cert, CMSSignedDataGenerator.DIGEST_SHA1);
sdatagen.addCertificatesAndCRLs(certStore);
CMSProcessable content = new CMSProcessableByteArray(dados);
CMSSignedData sdata = sdatagen.generate(content, true, "BC"); // <<< exception thrown here !!!
saida = sdata.getEncoded();
} catch (Exception e) {
e.printStackTrace();
throw new PKCS11Exception("Erro assinando dados",e);
}
return saida;
}
protected void setAlias() throws PKCS11Exception {
try {
Enumeration<String> aliases = keyStore.aliases();
String[] selection = Collections.list(aliases).toArray(new String[0]);
if (selection != null) {
if (selection.length > 1) {
JOptionPane pane = new JOptionPane();
pane.setSelectionValues(selection);
pane.setOptionType(JOptionPane.OK_OPTION);
do {
alias = pane.showInputDialog(null,_msgSelecionaAlias,_titSelecionaAlias,JOptionPane.QUESTION_MESSAGE);
} while (alias == null);
} else {
alias = selection[0];
}
} else {
throw new PKCS11Exception("N鉶 existem alias dispon韛eis no reposit髍io");
}
} catch (Exception e) {
e.printStackTrace();
throw new PKCS11Exception("N鉶 foi poss韛el obter alias",e);
}
}
private void login() throws PKCS11Exception {
char[] pin = getPIN();
try {
keyStore = KeyStore.getInstance("PKCS11");
keyStore.load(null, pin);
} catch (Exception e) {
e.printStackTrace();
throw new PKCS11Exception("N鉶 foi poss韛el logar",e);
}
}
private char[] getPIN() {
char[] saida = {' '};
// modo grafico
JOptionPane pane = new JOptionPane();
pane.setOptionType(JOptionPane.OK_OPTION);
String pin;
do {
pin = pane.showInputDialog(null,_msgSolicitaPIN,_titSolicitaPIN,JOptionPane.QUESTION_MESSAGE);
} while (pin == null);
saida = pin.toCharArray();
return saida;
}
}
Solved in this topic: http://forum.java.sun.com/thread.jspa?threadID=506442&start=10&tstart=0
Solution: Change the BouncyCastle ("BC") provider name by PKCS11 ("SunPKCS11-eToken") provider name!
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
>> CMSSignedData sdata = sdatagen.generate(content, true, "SunPKCS11-opensc");
> No exception! So in your case it would be
> "SunPKCS11-eToken"
>
> Saida ?bom! :-)
Wow, that is it! worked!! Thank you very much joachimbj!
joachimbj, MUITO OBRIGADO MESMO!
Desde agosto eu estava parado nesse problema (tinha at?deixado de lado), que gra鏰s a tua perspic醕ia agora foi solucionado!!
Parab閚s e muito obrigado novamente!
ps.: Saida ?otimo :)
a-ha, u-hu... brasileiro ?foda!!! a-ha, u-hu...
Hi there,
I had also a problem using SunPKCS11 and BouncyCastle to sign an email and its attachments. The exception that occurred was:
org.bouncycastle.mail.smime.SMIMEException: key inappropriate for signature.
at org.bouncycastle.mail.smime.SMIMESignedGenerator.make(SMIMESignedGenerator.java:170)
at org.bouncycastle.mail.smime.SMIMESignedGenerator.generate(SMIMESignedGenerator.java:288)
While debugging I found out the underlying exception had the message:
java.security.InvalidKeyException: Private key must be instance of RSAPrivate(Crt)Key or have PKCS#8 encoding
After a lot of trial and error and reading, I read in an article (http://www.developer.com/java/other/article.php/10936_3587361_2):
"Some PKCS#11 native implementations require the provider to be unregistered after you've finished signing. Otherwise, an active session with the smart card can remain open and can cause all further signing attempts to fail."
So I added a single line of code to unregister my provider in between signing the attachments:
Security.removeProvider(myProvider.getName());
et voila, it worked!
Hope this might help you as it helped me, grtz