Какие атрибуты объекта необходимы для создания пар ключей из YubiKey с помощью PKCS11?

Мое приложение хочет подписывать документы с помощью YubiKey с PIV ( PKCS11 ). Мне удалось войти в свой YubiKey, но когда я пытаюсь создать пары ключей, возникает эта ошибка.

«Метод C_GenerateKeyPair вернул CKR_ATTRIBUTE_VALUE_INVALID »

Это код, который у меня есть прямо сейчас (C# .NET)

      byte[] ckaId = session.GenerateRandom(20);

// Prepare attribute template of new public key
List<IObjectAttribute> publicKeyAttributes = new List<IObjectAttribute>();
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_PUBLIC_KEY));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_PRIVATE, false));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_LABEL, @"TestApp"));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ID, ckaId));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ENCRYPT, true));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_VERIFY, true));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_WRAP, true));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_MODIFIABLE, false));

// Prepare attribute template of new private key
List<IObjectAttribute> privateKeyAttributes = new List<IObjectAttribute>();
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_PRIVATE, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_LABEL, @"TestApp"));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ID, ckaId));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_SENSITIVE, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_DECRYPT, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_SIGN, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_UNWRAP, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_MODIFIABLE, false));

// Specify key generation mechanism
IMechanism mechanism = session.Factories.MechanismFactory.Create(CKM.CKM_RSA_PKCS_KEY_PAIR_GEN);

// Generate key pair
IObjectHandle publicKeyHandle = null;
IObjectHandle privateKeyHandle = null;
session.GenerateKeyPair(mechanism, publicKeyAttributes, privateKeyAttributes, out publicKeyHandle, out privateKeyHandle);

1 ответ

Чтобы избавиться от всех ошибок, необходимо внести несколько изменений. Чтобы помочь всем, у кого в будущем появляются похожие расплывчатые сообщения об ошибках, мне больше всего помогли настройки YKCS11_DBGпеременная окружения, чтобы сообщения об ошибках из библиотеки libykcs11 распечатывались в stderr (документы Yubico здесь не обновлены во всех разделах, но они упоминают переменную и некоторые другие важные вещи здесь https://developers.yubico.com/yubico-piv-tool / YKCS11 /)

Что касается изменений по порядку:

  1. CKA_IDдолжен быть одинаковым как для шаблона закрытого, так и для открытого ключа, но имеет конечный набор допустимых значений (охватываемых страницей документации Yubico и в исходном коде), поэтому вы не можете просто использовать 20 случайных байтов.
  2. CKA_MODIFIABLEне является допустимым атрибутом для шаблонов открытого или закрытого ключа (хотя в документации Yubico он показан как поддерживаемый атрибут)
  3. CKA_MODULUS_BITSдолжен быть установлен на 2048 или 1024 для открытого ключа в в режиме RSA.источнике

В итоге у меня сработало что-то вроде этого:

      // Prepare attribute template of new public key
List<IObjectAttribute> publicKeyAttributes = new List<IObjectAttribute>();
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_PUBLIC_KEY));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_PRIVATE, false));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_LABEL, @"TestApp"));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ID, 2)); // 2 == Digital Signature cert
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ENCRYPT, true));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_VERIFY, true));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_WRAP, true));
//publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_MODIFIABLE, false)); -- not allowed
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_MODULUS_BITS, 2048)); // required to be 1024 or 2048 for RSA

// Prepare attribute template of new private key
List<IObjectAttribute> privateKeyAttributes = new List<IObjectAttribute>();
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_PRIVATE, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_LABEL, @"TestApp"));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ID, 2)); // 2 == Digital Signature cert
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_SENSITIVE, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_DECRYPT, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_SIGN, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_UNWRAP, true));
//privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_MODIFIABLE, false)); -- not allowed

Кроме того, поскольку похоже, что вы примерно следуете образцу pkcs11interop, обратите внимание, что если вы вызовете session.DestroyObject на ключевых ручках сертификат удаляется

Другие вопросы по тегам