【问题标题】:Create 3DES key with pkcs11Interop and output key value, or proivde key value for creation使用 pkcs11Interop 创建 3DES 密钥并输出密钥值,或提供用于创建的密钥值
【发布时间】:2016-09-30 16:11:28
【问题描述】:

我想知道是否可以使用 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 1010101010101010

【问题讨论】:

  • 我在我的答案中添加了一个工作代码示例。如果它不适用于您的库/设备,那么我相信您需要联系库/设备供应商。 BTW DES3 密钥总是 24 字节长。如果您只有 16 个字节,那么我相信您应该创建 DES2 密钥。

标签: c# pkcs#11 pkcs11interop


【解决方案1】:

可以使用Session::CreateObject() 方法导入密钥。您需要按照 PKCS#11 规范中的定义指定正确的对象属性。

可以使用Session::GetAttributeValue() 方法导出明文形式的密钥。关键对象需要指定正确的属性才能读取其纯值。

请至少阅读PKCS#11 v2.20 specification“第 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();
                }
            }
        }
    }
}

【讨论】:

  • 运行相同的代码对我不起作用。我正在测试的 HSM 是 Safenet HSM。将查看它是否与某些配置有关,然后导致运行此代码我在导出时得到无法读取的异常,在导入时得到 CKR_TEMPLATE_INCONSISTENT。谢谢。
  • @Andre 在这种情况下有什么消息吗?
  • 好吧,事实证明这是我们所拥有的 HSM 的限制,而不是限制,它更多的是一种安全功能。出于安全原因,您不能提取键值!事实上,他们有不同的产品可以做到这一点。我现在选择了一种解决方法,使用 generateRandom 生成 DES 密钥,然后将其存储为数据对象,以使用 AES 密钥进行安全加密。
  • 嗨,jariq,我正在使用最新的 github 版本的 pkcs11interop 库。上面的代码没有在那里编译。您是否可以使用最新的存储库提供更新后的等效代码
  • 我遇到了同样的问题。 CKR_TEMPLATE_INCONSISTEN。有谁知道如何将密钥导入 HSM?
【解决方案2】:

您可能需要设置以下属性:

(CKA.CKA_SENSITIVE, false)
(CKA.CKA_PRIVATE, false)

根据我的经验,var testval = test[0].GetValueAsString(); 通常会给出不可读的值,因此我建议您使用 Get 作为字节数组,然后自己转换为十六进制字符串。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-10
    • 1970-01-01
    • 2016-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-01
    相关资源
    最近更新 更多