2016-09-30 124 views
1

我想知道是否可以使用pkcs11interop创建3DES密钥并指定用于创建的密钥值,否则创建密钥并输出生成的密钥核心价值。基本上我需要将密钥导出到其他设备。使用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.我想创建一个键与此类似,其在Hex在这里表示:1616161616161616 1010101010101010

+0

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

回答

1

秘密密钥可以与Session::CreateObject()方法导入。您将需要指定正确的对象属性,如PKCS#11规范中所定义。

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

请仔细阅读至少“第10章 - 对象”“第12.15.3 - DES3密钥对象”的PKCS#11 v2.20 specification,然后发布您的代码可能仍然无法解决您的问题。

下面的代码示例工作对我来说就像一个魅力与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(); 
       } 
      } 
     } 
    } 
} 
+0

运行此相同的确切代码不适用于我。我正在测试的HSM是Safenet HSM。将看它是否与某些配置有关,然后导致运行此代码我在导出时遇到cannotberead异常,导入时遇到了CKR_TEMPLATE_INCONSISTENT。谢谢。 – Andre

+0

@在这种情况下的任何消息? – jariq

+0

事实证明,它是我们所拥有的HSM的一个限制,而不是一个限制,它更像是一个安全功能。出于安全原因,您无法提取关键值!事实上,他们有一个不同的产品,允许这一点。我现在选择了一种解决方法,使用generateRandom生成DES密钥,然后将其存储为数据对象,以便使用AES密钥加密安全性。 – Andre