You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 09:58:09