如何使用智能卡签署一个罐子

时间:2015-09-24 22:23:46

标签: java jar cryptography smartcard jarsigner

我在工作时使用PKCS11智能卡,并希望使用jarsigner使用我卡上的证书对jar文件进行签名。

我主要在Linux上工作。酷键可以看到卡片。

Oracle's documentation提到智能卡:

jarsigner -keystore NONE -storetype PKCS11 \
    -providerName SunPKCS11-SmartCard \
    -list

但显然没有该名称的实际提供者,而jarsigner的-list参数似乎不存在。

我终于让jarsigner看到了这张卡,但它报告说它不是一个有效的条目而且没有私钥:

jarsigner -keystore NONE -storetype PKCS11 \
  -providerClass sun.security.pkcs11.SunPKCS11 \
  -providerArg smartcard.config \
  -storepass notmyrealpass \
  myjarfile.jar 'Identity #0'

jarsigner: Certificate chain not found for: Identity #0.
  Identity #0 must reference a valid KeyStore key entry
  containing a private key and corresponding public key
  certificate chain.

smartcard.config是:

name=Kittens
library=/usr/lib/pkcs11/libcoolkeypk11.so

我得到了别名列表[来自哪个"身份#0"以编程方式通过在Java中加载卡:

String conf = "name=Kittens\nlibrary=/usr/lib/pkcs11/libcoolkeypk11.so";
InputStream s = new ByteArrayInputStream(conf.getBytes());
Provider p = new sun.security.pkcs11.SunPKCS11(s);
KeyStore keyStore = KeyStore.getInstance("PKCS11", p);
keyStore.load(null, "notmyrealpass".toCharArray());
Enumeration<String> aliases = keyStore.aliases();
// Aliases contains "Identity #0", "Identity #1", "Identity #2"

这些智能卡的重点在于私钥留在卡上,卡就是签名;有没有办法让jarsigner做我想做的事?

编辑:

经过一些更多的涂鸦之后,我注意到我似乎无法使用SHA1withDSA,只有SHA1withRSA:

Set<Provider.Service> services = p.getServices();
for(Provider.Service service : services) {
    System.out.println(service.getAlgorithm());
}

打印此列表:SHA512withRSA,SHA256withRSA,SHA1withRSA,MD5withRSA,RSA / ECB / PKCS1Padding,SHA384withRSA,MD2withRSA,RSA,PKCS11

但我注意到签名的罐子似乎都使用DSA;这可能是问题吗?

2 个答案:

答案 0 :(得分:2)

我将-sigalg添加到可用的algortihm [在这种情况下为SHA256withRSA],这有帮助。也:

jarsigner: This jar contains entries whose certificate chain is not validated

我偶然混合了几个不同JDK的二进制文件。

所以,我使用的最后一个命令行是:

jarsigner \
    -tsa http://timestamp.digicert.com \
    -keystore NONE \
    -storetype PKCS11 \
    -providerClass sun.security.pkcs11.SunPKCS11 \
    -providerArg card_linux.config \
    -storepass `cat ~/cardpass` \
    -sigalg SHA256withRSA \
    dist/sup2rtam.jar \
    'Identity #0'

其中〜/ cardpass是一个只包含notmyrealpass的文件,而card_linux.config是

name=CAC
library=/usr/lib/pkcs11/libcoolkeypk11.so

答案 1 :(得分:0)

与@Gary B类似,除了我正在使用OpenSC,这是我的命令:

jarsigner -tsa http://timestamp.digicert.com \
    -keystore NONE -storetype PKCS11 \
    -providerClass sun.security.pkcs11.SunPKCS11 \
    -providerArg /Library/Java/Extensions/pkcs11.cfg 
    -sigalg SHA256withRSA \
    testjni_signed.jar \
    'Certificate for Digital Signature'

我使用的卡是PIV(也适用于CAC)。 pkcs11.cfg是

name = OpenSC
library = /Library/OpenSC/lib/opensc-pkcs11.dylib
description = OpenSC PKCS#11 interface for SmartCard
#showInfo = true
slot = 0

在命令行中不包含卡片PIN会提示输入PIN码(也就是密钥库的密码短语)。

以上内容已经过CAC和Yubikey NEO(PIV配置),JDK-1.8.0_102和Github mouse07410 / OpenSC测试。