首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何重用现有私钥,使用智能卡和PKCS#11生成数字签名

如何重用现有私钥,使用智能卡和PKCS#11生成数字签名
EN

Stack Overflow用户
提问于 2016-10-25 11:54:03
回答 2查看 1.1K关注 0票数 2

我想使用pkcs11标准创建一个数字签名。假设我已经有一个存储在智能卡上的公钥和私钥对。这个键是通过使用下一个代码生成的:

代码语言:javascript
复制
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);

现在我可以用这些密钥来签名一些数据。例如:

代码语言:javascript
复制
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()方法中使用它。为此,我编写了下一段代码:

代码语言:javascript
复制
// 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

有人能告诉我我做错了什么以及如何解决这个问题吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-10-25 22:10:58

如果要为现有密钥获取ObjectHandle,则需要通过其属性(如label等)查找,查找密钥。密钥派生是完全不同的加密操作。

下面的代码示例搜索由问题中的代码生成的键:

代码语言:javascript
复制
// Prepare attribute template that defines search criteria for public key
List<ObjectAttribute> publicKeyAttributes = new List<ObjectAttribute>();
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_PUBLIC_KEY));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_RSA));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, PKCS11Settings.ApplicationName));

// Find all objects that match provided attributes
List<ObjectHandle> foundPublicKeys = session.FindAllObjects(publicKeyAttributes);
if (foundPublicKeys == null || foundPublicKeys.Count != 1)
    throw new Exception("Unable to find public key");

// Prepare attribute template that defines search criteria for private key
List<ObjectAttribute> privateKeyAttributes = new List<ObjectAttribute>();
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_RSA));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, PKCS11Settings.ApplicationName));

// Find all objects that match provided attributes
List<ObjectHandle> foundPrivateKeys = session.FindAllObjects(publicKeyAttributes);
if (foundPrivateKeys == null || foundPrivateKeys.Count != 1)
    throw new Exception("Unable to find private key");

// Use found object handles
ObjectHandle publicKeyHandle = foundPublicKeys[0];
ObjectHandle privateKeyHandle = foundPrivateKeys[0];
票数 4
EN

Stack Overflow用户

发布于 2016-10-25 22:19:13

首先,我想我会引用pkcs-11v2-20.pdf几次,所以如果还没有拷贝的话就抓住它(它还附带了一些有用的例子)。

第二,我不是C#程序员,所以下面的任何东西都只是伪代码。

让我们首先解决CKR_MECHANISM_INVALID问题:根据标准,CKM.CKM_RSA_PKCS不能用于C_DeriveKey (Chp )。12,表34)

现在的问题是:您的智能卡上已经有了一对密钥(并根据需要打开会话并登录),您必须使用C_FindObjectsInit、C_FindObjects和C_FindObjectsFinal (pg )搜索所需的内容。136及以下,也给出了一些例子),其中您为C_FindObjectsInit提供了一个属性模板,说明您正在寻找哪种类型的密钥。

代码语言:javascript
复制
// look for key allowing signing and decrypting
var searchCriteria = new List<ObjectAttribute>();
searchCriteria.Add(new ObjectAttribute(CKA.CKA_DECRYPT, true));
searchCriteria.Add(new ObjectAttribute(CKA.CKA_SIGN, true));

// initialize the search. The number is actually the number of search attributes.
session.FindObjectsInit(searchCriteria, 2);
...
session.FindObjects(out privateKeyHandle, ...);
... 
session.FindObjectsFinal();

// we found the requested private key, now sign the message
session.Sign(..., privateKeyHandle,...);

您在上一段中尝试过的密钥派生用于智能卡和应用程序需要通过非对称加密技术派生一个或两个共享密钥(例如,安全消息传递)的场景。

希望能帮上忙。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40239260

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档