如何使用pkcs11包装ECDSA密钥签署CSR

时间:2019-04-17 13:31:54

标签: java cryptography pkcs#11

我想在pkcs11 usb令牌中生成ECDSA密钥对。之后,想要使用私钥对CSR进行签名,但是要面对“无效签名”异常。

Mechanism keyPairGenerationMechanism = Mechanism.get(PKCS11Constants.CKM_EC_KEY_PAIR_GEN);
 ECDSAPrivateKey ecdsaPrivateKeyTemplate = new ECDSAPrivateKey();
ecdsaPrivateKeyTemplate.getLabel().setCharArrayValue(keyAlias.toCharArray());
   ecdsaPrivateKeyTemplate.getId().setByteArrayValue(keyAlias.getBytes());
   ecdsaPrivateKeyTemplate.getSign().setBooleanValue(Boolean.TRUE);
   ecdsaPrivateKeyTemplate.getDecrypt().setBooleanValue(Boolean.TRUE);
   ecdsaPrivateKeyTemplate.getToken().setBooleanValue(Boolean.TRUE);
   ecdsaPrivateKeyTemplate.getPrivate().setBooleanValue(Boolean.TRUE);
   ecdsaPrivateKeyTemplate.getSensitive().setBooleanValue(Boolean.TRUE);
  ecdsaPrivateKeyTemplate.getExtractable().setBooleanValue(Boolean.FALSE);
   ecdsaPrivateKeyTemplate.getKeyType().setLongValue(PKCS11Constants.CKK_EC); ECDSAPublicKey ecdsaPublicKeyTemplate = new ECDSAPublicKey();    ecdsaPublicKeyTemplate.getLabel().setCharArrayValue(keyAlias.toCharArray());
    ecdsaPublicKeyTemplate.getId().setByteArrayValue(keyAlias.getBytes());
    ecdsaPublicKeyTemplate.getEncrypt().setBooleanValue(Boolean.TRUE);
   ecdsaPublicKeyTemplate.getPrivate().setBooleanValue(Boolean.FALSE);
    ecdsaPublicKeyTemplate.getVerify().setBooleanValue(Boolean.TRUE);
   ecdsaPublicKeyTemplate.getToken().setBooleanValue(Boolean.TRUE);

 ecdsaPublicKeyTemplate.getKeyType().setLongValue(PKCS11Constants.CKK_EC);
    ecdsaPublicKeyTemplate.getModifiable().setBooleanValue(Boolean.TRUE);

    ASN1ObjectIdentifier curveId = getCurveId((getEcdsaParamsOID(256)));
X962Parameters x962 = new X962Parameters(curveId);
   byte[] paramsBytes = x962.getEncoded();
    ecdsaPublicKeyTemplate.getEcdsaParams().setByteArrayValue(paramsBytes);
    KeyPair generatedKeyPair = m_objSession.generateKeyPair(keyPairGenerationMechanism,ecdsaPublicKeyTemplate, ecdsaPrivateKeyTemplate);


   ECDSAPublicKey publicKey = (ECDSAPublicKey) generatedKeyPair.getPublicKey();

    ECDSAPrivateKey privateKey = (ECDSAPrivateKey) generatedKeyPair.getPrivateKey();
 byte[] pubPoint = publicKey.getEcPoint().getByteArrayValue();
    DEROctetString os = (DEROctetString) DEROctetString.fromByteArray(pubPoint);
    AlgorithmIdentifier keyAlgID = new AlgorithmIdentifier(
            X9ObjectIdentifiers.id_ecPublicKey, curveId);
    SubjectPublicKeyInfo pkInfo = new SubjectPublicKeyInfo(keyAlgID, os.getOctets());

从注释中签名代码:

ECDSAPrivateKey signatureKey = this.getECDSAPrivateKey(a_strKeyId,m_objSession);

MessageDigest digestEngine = MessageDigest.getInstance("SHA-256");
digestEngine.update(bUnsignedData);
byte[] digest = digestEngine.digest();

Mechanism signatureMechanism = Mechanism.get(PKCS11Constants.CKM_ECDSA);
m_objSession.signInit(signatureMechanism, signatureKey);

DigestInfo digestInfoEngine = new DigestInfo(a_objAlgorithmIdentifier, digest);
byte[] digestInfo = digestInfoEngine.getEncoded();

byte[] signatureValue = m_objSession.sign(digestInfo);

1 个答案:

答案 0 :(得分:1)

对于ECDSA,您不需要DigestInfo,摘要值(以字节为单位)将直接签名。 RSA可能需要DigestInfo