问题
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