我想使用 pkcs11 标准创建数字签名。假设我已经有一个公钥和私钥对存储在我的智能卡上。此密钥是通过使用下一个代码生成的:
byte[] ckaId = session.GenerateRandom(20);
// Prepare attribute template of new public key
var publicKeyAttributes = new List<ObjectAttribute>();
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, false));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, PKCS11Settings.ApplicationName));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ENCRYPT, true));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_VERIFY, true));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_VERIFY_RECOVER, true));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_WRAP, true));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_MODULUS_BITS, 1024));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PUBLIC_EXPONENT, new byte[] { 0x01, 0x00, 0x01 }));
// Prepare attribute template of new private key
var privateKeyAttributes = new List<ObjectAttribute>();
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, true));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, PKCS11Settings.ApplicationName));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SENSITIVE, true));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_DECRYPT, true));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SIGN, true));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SIGN_RECOVER, true));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_UNWRAP, true));
// Specify key generation mechanism
Mechanism mechanism = new Mechanism(CKM.CKM_RSA_PKCS_KEY_PAIR_GEN);
// Generate key pair
session.GenerateKeyPair(mechanism, publicKeyAttributes, privateKeyAttributes, out publicKeyHandle, out privateKeyHandle);
现在我可以使用这些密钥来签署一些数据。例如:
var mechanism = new Mechanism(CKM.CKM_RSA_PKCS);
byte[] byteContent = (ConvertUtils.Utf8StringToBytes("Hello World!!!"));
byte[] signature = session.Sign(mechanism, derivedKey, byteContent);
当您想要创建密钥然后在 C_sign 方法中使用它时,此代码非常有效
但是如何访问已经存在的密钥来执行类似的操作呢?据我了解,我应该使用 C_Derrive() 方法从现有的私钥派生一个私钥,而不是在 C_Sign() 方法中使用它。为此,我编写了下一个代码:
// Prepare attribute template of new key
List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_ENCRYPT, true));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_DECRYPT, true));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_DERIVE, true));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_EXTRACTABLE, true));
// Specify key generation mechanism
Mechanism mechanism = new Mechanism(CKM.CKM_RSA_PKCS);
// Generate key
ObjectHandle baseKey = session.GenerateKey(mechanism, objectAttributes);
byte[] dt = session.GenerateRandom(24);
// Specify mechanism parameters
var mechanismParams = new CkKeyDerivationStringData(dt);
// Specify derivation mechanism with parameters
Mechanism mech = new Mechanism(CKM.CKM_RSA_PKCS, mechanismParams);
// Derive key
ObjectHandle derivedKey = session.DeriveKey(mech, baseKey, null);
byte[] byteContent = (ConvertUtils.Utf8StringToBytes("Hello World!"));
byte[] signature = session.Sign(mech, derivedKey, byteContent);
但是当我运行这段代码时,它会抛出下一个错误:
方法 C_GenerateKey 返回 CKR_MECHANISM_INVALID
谁能告诉我我做错了什么以及如何解决这个问题?