使用Java+Bouncy Castle向智能卡存储自签名根证书时遭遇CKR_USER_NOT_LOGGED_IN异常的原因排查及代码正确性咨询
使用Java+Bouncy Castle向智能卡存储自签名根证书时遭遇CKR_USER_NOT_LOGGED_IN异常的原因排查及代码正确性咨询
我想要使用P-256 ECDSA(secp256r1)加密算法在智能卡上创建并存储自己的根证书。
目前我已经能通过其他工具(OpenSSL)访问卡上已有的证书,现在想用Java结合Bouncy Castle库来实现。以下操作已经可以正常工作:
- 打开密钥库(对应代码块[1]和[2])
- 列出智能卡上存储的证书(对应代码块[3])
- 在智能卡上生成密钥对(对应代码块[4])
- 创建自签名根证书(对应代码块[5])
但不幸的是,在代码块[7]的setKeyEntry方法执行时,抛出了如下异常:
KeyStoreException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_USER_NOT_LOGGED_IN
请问为什么会出现这个问题?
我使用的智能卡是Thales SafeNet ID Prime 940,不确定这段创建并保存证书到智能卡的代码是否整体正确,如果你发现任何问题,也请指出哪里有错误。
public void smartCard_Save_Certificate() { try { //-------------- [1] PKCS#11 configuration ------------------------ Security.addProvider(new BouncyCastleProvider()); String name = "SmartCard"; String library = "C:\\Program Files\\SafeNet\\Authentication\\SAC\\x64\\IDPrimePKCS1164.dll"; String slotListIndex = "0"; String PIN = "1234"; String pkcs11Config = "name=" + name + "\nlibrary=" + library + "\nslot=" + slotListIndex; ByteArrayInputStream pkcs11ConfigStream = new ByteArrayInputStream(pkcs11Config.getBytes()); Provider provider = new sun.security.pkcs11.SunPKCS11(pkcs11ConfigStream); Security.addProvider(provider); //--------------------- [2] Key store open ------------------------- KeyStore keyStore = KeyStore.getInstance("PKCS11", provider); keyStore.load(null, PIN.toCharArray()); //------------------ [3] listing certificates --------------------- Enumeration<String> aliases = keyStore.aliases(); while (aliases.hasMoreElements()) { String alias = aliases.nextElement(); System.out.println(alias); } //------------------------ [4] generate key pair (elliptic curves secp256r1) -------------------------- KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC", provider); keyGen.initialize(new ECGenParameterSpec("secp256r1")); KeyPair keyPair = keyGen.generateKeyPair(); //-------------------------- [5] creation my root certificate ----------------------------------------- X509v3CertificateBuilder rootCertificateBuilder = new JcaX509v3CertificateBuilder( new X500Name("CN=MyRootCertificate"), new BigInteger(64, new SecureRandom()), getCurrentDate(), getCurrentDatePlusDays(7), new X500Name("CN=MyRootCertificate"), keyPair.getPublic()); ContentSigner rootSelfSigner = new JcaContentSignerBuilder("SHA256withECDSA").setProvider(provider).build(keyPair.getPrivate()); X509Certificate rootCertificate = new JcaX509CertificateConverter()./*setProvider(provider).*/getCertificate(rootCertificateBuilder.build(rootSelfSigner)); //---------------------------- [6] printing a public key ---------------------------------------------- PublicKey publicKey = rootCertificate.getPublicKey(); System.out.println("PublicKey of \"rootCertificate\": " + convertByteTableToHex(publicKey.getEncoded())); //-------- [7] Saving the private key and my root certificate to a smart card ------------------------ Certificate[] certificatesChain = new Certificate[1]; certificatesChain[0] = rootCertificate; keyStore.setKeyEntry("MyRootCertificate", (Key)keyPair.getPrivate(), null, certificatesChain); keyStore.store(null); //-------------------------- [8] private Key Verification ----------------------------------- PrivateKey privateKey = (PrivateKey)keyStore.getKey("MyRootCertificate", null); boolean keyPairMatch = verifyKeyPair(privateKey, keyPair.getPublic(), "SHA256withRSA", provider); System.out.println("Key pair match: " + keyPairMatch); //-------------------------- [9] reading my certificate from the card ------------------------- Certificate x509CertificateSaved = keyStore.getCertificate("MyRootCertificate"); if (x509CertificateSaved != null) { PublicKey publicKeySaved = x509CertificateSaved.getPublicKey(); System.out.println("publicKeySaved: " + convertByteTableToHex(publicKeySaved.getEncoded())); //-------------------------- [10] Verifying the public key of the card certificate -------------- rootCertificate.verify(publicKeySaved, provider); } } catch (KeyStoreException ex) { Exceptions.printStackTrace(ex); } catch (IOException ex) { Exceptions.printStackTrace(ex); } catch (NoSuchAlgorithmException ex) { Exceptions.printStackTrace(ex); } catch (CertificateException ex) { Exceptions.printStackTrace(ex); } catch (InvalidAlgorithmParameterException ex) { Exceptions.printStackTrace(ex); } catch (OperatorCreationException ex) { Exceptions.printStackTrace(ex); } catch (InvalidKeyException ex) { Exceptions.printStackTrace(ex); } catch (SignatureException ex) { Exceptions.printStackTrace(ex); } catch (UnrecoverableKeyException ex) { Exceptions.printStackTrace(ex); } catch (ProviderException ex) { Exceptions.printStackTrace(ex); } } public String convertByteTableToHex(byte [] bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02X ", b)); } return sb.toString(); } public boolean verifyKeyPair(PrivateKey privateKey, PublicKey publicKey, String signatureAlgorithm, Provider provider) { try { Signature signature = Signature.getInstance(signatureAlgorithm, provider); try { signature.initSign(privateKey); String testData = "Test data"; try { signature.update(testData.getBytes(StandardCharsets.UTF_8)); byte[] digitalSignature = signature.sign(); signature.initVerify(publicKey); signature.update(testData.getBytes()); boolean keysMatch = signature.verify(digitalSignature); System.out.println("Key pair match: " + keysMatch); return keysMatch; } catch (SignatureException ex) { Exceptions.printStackTrace(ex); return false; } } catch (InvalidKeyException ex) { Exceptions.printStackTrace(ex); return false; } } catch (NoSuchAlgorithmException ex) { Exceptions.printStackTrace(ex); return false; } }
备注:内容来源于stack exchange,提问作者Marogo
相关产品推荐
相关产品推荐

