摘要:在PKCS11和OpenSC上使用JCA时,在提取证书时会请求PIN。
我有一个应用程序需要使用智能卡签名。智能卡由OpenSC支持,所以我使用Java内置的pkcs11包装提供程序来使用它。出于功能原因,我需要在不需要PIN的情况下获得卡中的证书。如果用户最终签名,那么当然需要PIN。
我明白了,我可以在命令行中完成,而无需提供PIN:
pkcs11-tool --module C:\WINDOWS\system32\opensc-pkcs11.dll -r -a 50-MDS_Signature -y cert -o p.cer
Using slot 1 with a present token (0x1)
到目前为止,一切顺利。
Oracle的文档清楚地说,“生成器将根据需要使用之前配置的回调处理程序提示输入密码”(http://docs.oracle.com/javase/6/docs/technotes/guides/security/p11guide.html#Login).然而,我的代码在调用KeyStore ks0=ksbuilder0时总是以子身份请求pin。getKeyStore()
即使只提取公共信息(如证书)。
下面是代码的摘录:
private static final String PKCS11_LIB = "C:\\WINDOWS\\system32\\opensc-pkcs11.dll";
private static final String NAME = "OpenSCpkcs11";
private static final String SLOT = "1";
private static final String PIN = "11111111";
private static final String ALIAS = "myCert";
[...]
private static CallbackHandler myCallbackHandler = new CallbackHandler() {
@Override
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for (Callback callback : callbacks) {
if (callback instanceof PasswordCallback) {
PasswordCallback passwordCallback = (PasswordCallback) callback;
System.out.println(passwordCallback.getPrompt() + PIN);
passwordCallback.setPassword(PIN.toCharArray());
}
}
}
};
[...]
String configString = "name = "
+ NAME.replace(' ', '_')
+ "\n"
+ "library = "
+ PKCS11_LIB
+ "\n slot = "
+ SLOT
+ " "
+ "\n attributes = compatibility \n"
+ "attributes(*,*,*)=\n{\nCKA_TOKEN=true\nCKA_LOCAL=true\n}";
ByteArrayInputStream configStream = new ByteArrayInputStream(
configString.getBytes());
SunPKCS11 pkcs11Provider0 = new SunPKCS11(configStream);
pkcs11Provider0.login(null, myCallbackHandler);
Security.addProvider(pkcs11Provider0);
KeyStore.CallbackHandlerProtection chp = new KeyStore.CallbackHandlerProtection(
myCallbackHandler);
KeyStore.Builder ksbuilder0 = KeyStore.Builder.newInstance(
"PKCS11", pkcs11Provider0, chp);
KeyStore ks0 = ksbuilder0.getKeyStore();
X509Certificate cert0 = (X509Certificate) ks0.getCertificate(ALIAS);
// System.out.println("Cert " + cert0.toString());
Principal p = cert0.getSubjectDN();
System.out.println("I am: " + cert0.getSubjectDN().getName());
结果是:
Contraseña de la tarjeta de claves PKCS11 [SunPKCS11-OpenSCpkcs11]: 11111111
2014-01-16 17:48:11.275 cannot lock memory, sensitive data may be paged to disk
I am: CN=pepe perez, SURNAME=pepe, L=qwerty
正如您所看到的,在获得证书之前会请求密码。通过调试,我可以看到在
KeyStore ks0=ksbuilder0行中请求了密码。getKeyStore()
任何想法?没有办法按我想要的配置吗?有什么进一步的想法或测试吗?
此外:您是否知道任何其他访问智能卡的方法,例如直接通过JAVA2OpenSC包装器或类似的方式?
谢谢,
最后,没有使用JCA的解决方案。最终的解决方案是直接攻击PKCS11驱动程序。我用过jacknji11(https://github.com/joelhockey/jacknji11)以及PKCS11规范(http://www.emc.com/emc-plus/rsa-labs/standards-initiatives/pkcs-11-cryptographic-token-interface-standard.htm).
我曾经做过的是
Provider prov = new sun.security.pkcs11.SunPKCS11("pkcs.cfg");
Security.addProvider(prov);
KeyStore cc = null;
try {
cc = KeyStore.getInstance("PKCS11");
cc.load(null, null);
cc.getCertificate("CITIZEN AUTHENTICATION CERTIFICATE")
} catch (Exception ex) {
ex.printStackTrace();
}
pkcs.cfg是指向“libpteidpkcs11.so”库的文件,您应该能够使其适应您的代码。我的上面写着:
name = SmartCard
library = /usr/local/lib/libpteidpkcs11.so
解决了的
我找到了从智能卡获取公共证书的方法。
String pkcs11Config = "name = SmartCard\nlibrary = /path/to/libraby.so";
ByteArrayInputStream confStream = new ByteArrayInputStream(pkcs11Config.getBytes());
Provider prov = new sun.security.pkcs11.SunPKCS11(confStream);
Security.addProvider(prov);
KeyStore cc = null;
String pin = "";
try {
cc = KeyStore.getInstance("PKCS11",prov);
KeyStore.PasswordProtection pp = new KeyStore.PasswordProtection(pin.toCharArray());
cc.load(null , pp.getPassword() );
Enumeration aliases = cc.aliases();
while (aliases.hasMoreElements()) {
Object alias = aliases.nextElement();
try {
X509Certificate cert0 = (X509Certificate) cc.getCertificate(alias.toString());
System.out.println("I am: " + cert0.getSubjectDN().getName());
} catch (Exception e) {
continue;
}
}
} catch (Exception e) {
e.printStackTrace();
}
KeyStore.load()应提供带空引脚的Paswordprotected对象。这允许我读取公共证书并从中提取数据。
我已经用3种不同类型的智能卡测试了这个功能,并且所有的智能卡都可以使用
我正试图从智能卡读取证书, 这是我从http://www.developer.com/java/other/article.php/3587361/Java-Applet-for-Signing-with-a-Smart-Card.htm我将在applet中执行这段代码,问题是每个用户都必须向我指出他们的本地pkcs11。。。dll,使用java samrtcard api是否可以避免加载此dll
我有一个Java应用程序,可以从智能卡读取证书,并使用它们登录用户。该应用还可以使用其他登录方法(用户名和密码)跟踪失败的登录尝试。 我想知道是否有可能在没有引脚的情况下从智能卡中读取用户信息?我想将失败的pin条目标记为失败的登录尝试,但是因为我需要pin从证书中读取别名,所以我无法知道哪个用户正在尝试登录。有没有读取这些信息没有引脚在Java? 我根据这个线程的建议尝试加载KeyStore对象
我正在编写一个Java程序,该程序使用USB证书(智能卡)进行加密和签名。我有一个共享库(Windows上为.dll,Linux上为.so),它为硬件实现PKCS11。 我正在搜索现有的解决方案,并找到以下指南http://docs.oracle.com/javase/7/docs/technotes/guides/security/p11guide.html指南建议使用sun。安全pkcs11.
因此,我正在尝试编写一个小applet,它使用library。智能卡与读卡器连接,现在我成功连接到智能卡并读取基本信息,如ATR和协议(T=1)。 我对此做了一些研究(例如:http://www.cardwerk.com/smartcards/smartcard_standard_ISO7816-4_5_basic_organizations.aspx#table9) 但我不知道我应该向卡上发送哪
我有一个面向服务的webapp,它使用IIS 8.5和通过智能卡的客户端证书身份验证。静态服务的前端通过AJAX调用多个服务。带有证书的智能卡受PIN保护。当使用Chrome、Firefox等浏览器时,PIN提示只会出现一次,似乎会被缓存以供后续使用。 但是,我们需要将webapp嵌入Windows 10。NET桌面应用程序。webapp可以工作,但是用户需要不断地输入他们的PIN,每个服务一次,
问题内容: 我尝试从KeyStore获取密钥。我通过Keytool创建了一个密钥库: keytool -genkeypair -dname“ cn = Mark Jones,ou = JavaSoft,o = Sun,c = US” -alias business2 -keypass abcdtest -keystore C:\ workspace \ XMLSample \ keystore \