使用pkcs11Interop创建3DES密钥并输出密钥值,或者为创建提供密钥值
本文关键字:密钥 创建 或者 输出 pkcs11Interop 3DES 使用 | 更新日期: 2023-09-27 18:09:55
我想知道是否可以使用pkcs11interop创建3DES密钥并指定用于创建的密钥值,或者以其他方式创建密钥并输出生成的密钥值。基本上,我需要将密钥导出到另一个设备。
我已经尝试使用CKA_VALUE属性并将密钥作为byte[]数组传递,但没有成功。
请问这样的事情可能吗?有人能帮我一下吗?
编辑:下面是我到目前为止没有找到的代码:
public ObjectHandle generate3DESKey(string keyLabel)
{
ObjectHandle key = null;
// Generate symetric key
// Prepare attribute template of new key
List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
objectAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
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_EXTRACTABLE, true));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, keyLabel));
// Specify key generation mechanism
Mechanism mechanism = new Mechanism(CKM.CKM_DES3_KEY_GEN);
// Generate key
key = _session.GenerateKey(mechanism, objectAttributes);
List<CKA> retrieveTemplate = new List<CKA>();
retrieveTemplate.Add(CKA.CKA_VALUE);
var test = _session.GetAttributeValue(key, retrieveTemplate);
var testval = test[0].GetValueAsString();
return key;
}
所以我用这段代码尝试的是创建一个3DES密钥,然后使用如下所示的GetAttributeValue获取它的值。我尝试过GetValueAsByteArray和GetValueAsString,但都没有成功。我注意到,即使我在创建时设置了可提取属性,检索属性上的cannotread属性也被设置为true。
除此之外,我还考虑在生成3DES密钥时传递密钥值,但令我困惑的是文档中说与CKA一起使用的密钥值。CKA_VALUE应该是一个长度为24的字节数组。在我的例子中,我需要创建的键长度是16,而不是24。我想创建一个类似的键用十六进制表示为:1616161616161616 10101010101010
私钥可以通过Session::CreateObject()
方式导入。您需要指定pkcs# 11规范中定义的正确对象属性。
可以使用Session::GetAttributeValue()
方法导出明文形式的密钥。Key对象需要指定正确的属性,以允许您读取其普通值。
请至少阅读pkcs# 11 v2.20规范的"第10章-对象"和"第12.15.3章- DES3秘密密钥对象",然后发布您的代码,如果您仍然无法解决您的问题。
下面的代码示例对我来说就像SoftHSM 2.1.0的魅力:
using Net.Pkcs11Interop.Common;
using Net.Pkcs11Interop.HighLevelAPI;
using System;
using System.Collections.Generic;
namespace ExportTest
{
class Program
{
static void Main(string[] args)
{
using (Pkcs11 pkcs11 = new Pkcs11(@"D:'SoftHSM2'lib'softhsm2.dll", false))
{
Slot slot = pkcs11.GetSlotList(true)[0];
using (Session session = slot.OpenSession(false))
{
session.Login(CKU.CKU_USER, "11111111");
// Generate exportable key
List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, "Generated key"));
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_TOKEN, true));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_ENCRYPT, true));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_DECRYPT, true));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_EXTRACTABLE, true));
ObjectHandle generatedKey = null;
using (Mechanism mechanism = new Mechanism(CKM.CKM_DES3_KEY_GEN))
generatedKey = session.GenerateKey(mechanism, objectAttributes);
// Export the key
byte[] plainKeyValue = null;
List<ObjectAttribute> readAttrs = session.GetAttributeValue(generatedKey, new List<CKA>() { CKA.CKA_VALUE });
if (readAttrs[0].CannotBeRead)
throw new Exception("Key cannot be exported");
else
plainKeyValue = readAttrs[0].GetValueAsByteArray();
// Import the key
objectAttributes = new List<ObjectAttribute>();
objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, "Imported key"));
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_TOKEN, true));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_ENCRYPT, true));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_DECRYPT, true));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_VALUE, plainKeyValue));
ObjectHandle importedKey = session.CreateObject(objectAttributes);
// Test encryption with generated key and decryption with imported key
using (Mechanism mechanism = new Mechanism(CKM.CKM_DES3_CBC, session.GenerateRandom(8)))
{
byte[] sourceData = ConvertUtils.Utf8StringToBytes("Our new password");
byte[] encryptedData = session.Encrypt(mechanism, generatedKey, sourceData);
byte[] decryptedData = session.Decrypt(mechanism, importedKey, encryptedData);
if (Convert.ToBase64String(sourceData) != Convert.ToBase64String(decryptedData))
throw new Exception("Encryption test failed");
}
session.Logout();
}
}
}
}
}
您可能需要设置以下属性:
(CKA.CKA_SENSITIVE, false)
(CKA.CKA_PRIVATE, false)
根据我的经验,var testval = test[0].GetValueAsString();
通常给出一个不可读的值,因此我建议您使用Get作为字节数组,然后自己转换为十六进制字符串。