Создайте ключ 3DES с помощью pkcs11Interop и значения ключа вывода или введите значение ключа proivde для создания
Мне было интересно, возможно ли с помощью 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, но все безуспешно. Что я заметил, так это то, что свойства notread для извлеченного атрибута установлены в true, хотя я установил извлекаемый атрибут при создании.
Помимо этого я также обдумывал передачу значения ключа при генерации ключа 3DES, однако меня поразило то, что в документации сказано, что значение ключа, используемое с CKA.CKA_VALUE, должно быть байтовым массивом длиной 24. В моем случае ключ, который Мне нужно создать длину 16, а не 24. Я хочу создать ключ, подобный этому, который представлен здесь в шестнадцатеричном виде: 1616161616161616 1010101010101010
2 ответа
Секретный ключ может быть импортирован с Session::CreateObject()
метод. Вам нужно будет указать правильные атрибуты объекта, как определено в спецификации PKCS#11.
Обычную форму секретного ключа можно экспортировать с Session::GetAttributeValue()
метод. Для ключевого объекта должны быть указаны правильные атрибуты, чтобы вы могли прочитать его обычное значение.
Прочитайте, по крайней мере, "Глава 10 - Объекты" и "Глава 12.15.3 - Объекты секретных ключей DES3" спецификации PKCS#11 v2.20, а затем опубликуйте свой код, если вы все еще не можете решить свою проблему.
Следующий пример кода работает для меня как брелок с 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 as Byte, а затем преобразовать его в шестнадцатеричную строку самостоятельно.