我在pkcs11密钥库中生成一个RSA密钥对,它存储到智能卡中,我正在生成pkcs10请求。当我下载等效证书时,如何将其存储到智能卡中(因为密钥已存储到智能卡中,因此没有私钥),因为我无法访问pkcs11密钥库中的私钥。
String wdtokenpath = "path to dll file";
String pkcs11ConfigSettings = "name = SmartCard\n" + "library =" + wdtokenpath;
byte[] pkcs11ConfigBytes = pkcs11ConfigSettings.getBytes();
ByteArrayInputStream confStream = new ByteArrayInputStream(pkcs11ConfigBytes);
Provider pkcs11Provider = null;
Class sunPkcs11Class = Class.forName("sun.security.pkcs11.SunPKCS11");
Constructor pkcs11Constr = sunPkcs11Class.getConstructor(
java.io.InputStream.class);
pkcs11Provider = (Provider) pkcs11Constr.newInstance(confStream);
CallbackHandler call = new TextCallbackHandler();
Subject token = new Subject();
AuthProvider aprov = (AuthProvider) pkcs11Provider;
aprov.login(token, call);
System.out.println("Login successfully");
KeyPairGenerator keyGen1 = KeyPairGenerator.getInstance("RSA", aprov);
keyGen1.initialize(2048);
KeyPair pair1 = keyGen1.generateKeyPair();
PublicKey publicKey1 = pair1.getPublic();
String sigAlg = "SHA1withRSA";
PKCS10 pkcs10 = new PKCS10(publicKey1);
Signature signature = Signature.getInstance("SHA1withRSA", pkcs11Provider);
signature.initSign(pair1.getPrivate());
答案 0 :(得分:1)
这取决于您拥有的智能卡类型,或者您拥有的PKCS#11设备类型。实施可能会有所不同。
当您使用SunPKCS11
时,您可以这样做:
public boolean uploadCertificate(X509Certificate cert, String label, String id) {
CK_ATTRIBUTE[] certificate = new CK_ATTRIBUTE[9];
certificate[0] = new CK_ATTRIBUTE(PKCS11Constants.CKA_CLASS, PKCS11Constants.CKO_CERTIFICATE);
certificate[1] = new CK_ATTRIBUTE(PKCS11Constants.CKA_TOKEN, true);
certificate[2] = new CK_ATTRIBUTE(PKCS11Constants.CKA_PRIVATE, false);
certificate[3] = new CK_ATTRIBUTE(PKCS11Constants.CKA_LABEL, label.toCharArray());
certificate[4] = new CK_ATTRIBUTE(PKCS11Constants.CKA_SUBJECT, cert.getSubjectX500Principal().getEncoded());
certificate[5] = new CK_ATTRIBUTE(PKCS11Constants.CKA_ID, HexUtils.hexStringToByteArray(id));
certificate[6] = new CK_ATTRIBUTE(PKCS11Constants.CKA_ISSUER, cert.getIssuerX500Principal().getEncoded());
certificate[7] = new CK_ATTRIBUTE(PKCS11Constants.CKA_SERIAL_NUMBER, cert.getSerialNumber().toByteArray());
try {
certificate[8] = new CK_ATTRIBUTE(PKCS11Constants.CKA_VALUE, cert.getEncoded());
p11.C_CreateObject(hSession, certificate);
} catch (Exception e) {
logger.log(Level.SEVERE, "Upload Certificate Exception", e);
return false;
}
return true;
}
或使用IAIK PKCS#11 Wrapper:
// create certificate object template
X509PublicKeyCertificate pkcs11X509PublicKeyCertificate = new X509PublicKeyCertificate();
pkcs11X509PublicKeyCertificate.getToken().setBooleanValue(Boolean.TRUE);
pkcs11X509PublicKeyCertificate.getPrivate().setBooleanValue(Boolean.FALSE);
pkcs11X509PublicKeyCertificate.getLabel().setCharArrayValue("test".toCharArray());
pkcs11X509PublicKeyCertificate.getSubject().setByteArrayValue(cert.getSubjectX500Principal().getEncoded());
pkcs11X509PublicKeyCertificate.getId().setByteArrayValue(objectId);
pkcs11X509PublicKeyCertificate.getIssuer().setByteArrayValue(cert.getIssuerX500Principal().getEncoded());
// serial number should be an DER encoded ASN.1 integer
/*
INTEGER asn1Integer = new INTEGER(userCertificate.getSerialNumber());
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
DerCoder.encodeTo(asn1Integer, buffer);
pkcs11X509PublicKeyCertificate.getSerialNumber().setByteArrayValue(buffer.toByteArray());
*/
// Netscape deviates from the standard here, for use with Netscape rather use
pkcs11X509PublicKeyCertificate.getSerialNumber().setByteArrayValue(cert.getSerialNumber().toByteArray());
pkcs11X509PublicKeyCertificate.getValue().setByteArrayValue(cert.getEncoded());
session.createObject(pkcs11X509PublicKeyCertificate);
证书对象的ID应与生成密钥的ID相同。