Create 3DES key with pkcs11Interop and output key value, or proivde key value for creation

天大地大妈咪最大 提交于 2019-12-24 09:13:06

问题


I was wondering whether it is possible using pkcs11interop to create a 3DES key and specify the key value for creation, or otherwise create a key and output the generated key value. Basically I need the secret key to be exported to another device.

I've tried using the CKA_VALUE attribute and passing the key as a byte[] array but with no success.

Is such thing possible please? Can someone assist me please?

EDIT:

Here is the code I have with no luck so far:

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;
}

So what I'm trying with this code is to create a 3DES key and then get it's value using the GetAttributeValue as instructed below. I've tried the GetValueAsByteArray and GetValueAsString but all without success. What I've noticed is that the the cannotread properties on the retrieved attribute is set to true even though I've set the extractable attribute on creation.

Apart from this I also contemplated passing the key value on generating the 3DES key however what puzzled me is the fact that documentation says that the key value used with the CKA.CKA_VALUE should be a byte array of length 24. In my case the key that I need to create is 16 length long and not 24. I want to create a key similar to this which is represented in hex over here: 1616161616161616 1010101010101010


回答1:


Secret key can be imported with Session::CreateObject() method. You will need to specify correct object attributes as defined in PKCS#11 specification.

Plain form of secret key can be exported with Session::GetAttributeValue() method. Key object will need to have correct attributes specified to allow you to read its plain value.

Please read at least "Chapter 10 - Objects" and "Chapter 12.15.3 - DES3 secret key objects" of PKCS#11 v2.20 specification and then post your code may you still be unable to solve your issue.

Following code sample works for me like a charm with 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();
                }
            }
        }
    }
}


来源:https://stackoverflow.com/questions/39795787/create-3des-key-with-pkcs11interop-and-output-key-value-or-proivde-key-value-fo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!