Как установить / создать ключевое значение для секретного ключа AES в Network Luna HSM?

При попытке создать секретный ключ; Мне сказали, что невозможно создать свои собственные ключевые значения, и они должны быть сгенерированы / развернуты в HSM. Если это не так, я приложил обе попытки / методы на случай, если что-то упустил. Любая помощь будет принята с благодарностью!

Среда: Network Luna K6 5.1

Библиотека: PKCS11Interop.Net

Попытка 1. Использование "Создать объект"

Ошибка: CKR_TEMPLATE_INCONSISTENT

string keyLabel = "CustomSecretKey"
byte[] Value = HexStringToByteArray(value);

privateKey = new List<ObjectAttribute>
                                {
                                   //PKCS11V2.20 Common Attributes Defined @ 12.12.2
                                   new ObjectAttribute(CKA.CKA_LABEL, keyLabel),
                                   new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY),
                                   new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_AES),
                                   new ObjectAttribute(CKA.CKA_TOKEN, true),
                                   new ObjectAttribute(CKA.CKA_ENCRYPT, true),
                                   new ObjectAttribute(CKA.CKA_PRIVATE, true), 
                                   new ObjectAttribute(CKA.CKA_DECRYPT, true), 
                                   new ObjectAttribute(CKA.CKA_VALUE_LEN, 32),
                                   new ObjectAttribute(CKA.CKA_VALUE, Value)    

                               };

session.CreateObject(privateKey);

Очевидно, это не поддерживается?

Попытка 2. Использование ключа распаковки

Ошибка: CKR_WRAPPED_KEY_INVALID

using (Pkcs11 pkcs11 = new Pkcs11(HSM.Instance.vendorDLLPath, AppType.MultiThreaded))
            {
                List<Slot> slots = pkcs11.GetSlotList(SlotsType.WithTokenPresent); //Checks to see what slots have token on them.
                Slot slot = slots[HSM.Instance.activeSlot];
                using (Session session = slot.OpenSession(SessionType.ReadWrite)) // Open RW session
                {
                    session.Login(CKU.CKU_USER, HSM.Instance.loginPass); // Login as normal user   
                    try
                    {
                        byte[] Value = HexStringToByteArray(value);

                        if (!string.IsNullOrEmpty(keyLabel))
                        {

                            List<ObjectAttribute> wrapKey = new List<ObjectAttribute>
                            {
                            new ObjectAttribute(CKA.CKA_LABEL, "TempWrapKey"),
                            new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY),
                            new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_AES),
                            new ObjectAttribute(CKA.CKA_TOKEN, true),
                            new ObjectAttribute(CKA.CKA_PRIVATE, true),
                            new ObjectAttribute(CKA.CKA_ENCRYPT, true),
                            new ObjectAttribute(CKA.CKA_DECRYPT, true),
                            new ObjectAttribute(CKA.CKA_SENSITIVE, true),
                            new ObjectAttribute(CKA.CKA_VERIFY, true),
                            new ObjectAttribute(CKA.CKA_SIGN, true),
                            new ObjectAttribute(CKA.CKA_WRAP, true),
                            new ObjectAttribute(CKA.CKA_UNWRAP, true),
                            new ObjectAttribute(CKA.CKA_DERIVE, false),
                            new ObjectAttribute(CKA.CKA_EXTRACTABLE, false),
                            new ObjectAttribute(CKA.CKA_VALUE_LEN, 32)

                            };
                            ObjectHandle WrappingKey = session.GenerateKey(new Mechanism(CKM.CKM_AES_KEY_GEN), wrapKey);

                            byte[] keyValueBytes = session.Encrypt(new Mechanism(CKM.CKM_AES_ECB), WrappingKey, Value);

                            List<ObjectAttribute> privateKeyAttributes = new List<ObjectAttribute>
                            {

                                new ObjectAttribute(CKA.CKA_LABEL, keyLabel),
                                new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY),
                                new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_AES),
                                new ObjectAttribute(CKA.CKA_TOKEN, true),
                                new ObjectAttribute(CKA.CKA_PRIVATE, true),
                                new ObjectAttribute(CKA.CKA_ENCRYPT, true),
                                new ObjectAttribute(CKA.CKA_DECRYPT, true),
                                new ObjectAttribute(CKA.CKA_SENSITIVE, true),
                                new ObjectAttribute(CKA.CKA_VERIFY, true),
                                new ObjectAttribute(CKA.CKA_SIGN, true),
                                new ObjectAttribute(CKA.CKA_WRAP, true),
                                new ObjectAttribute(CKA.CKA_UNWRAP, true),
                                new ObjectAttribute(CKA.CKA_DERIVE, false),
                                new ObjectAttribute(CKA.CKA_EXTRACTABLE, false),
                                new ObjectAttribute(CKA.CKA_VALUE_LEN, 32)

                            };


                            session.UnwrapKey(new Mechanism(CKM.CKM_AES_ECB), WrappingKey, keyValueBytes, privateKeyAttributes);
                            session.DestroyObject(WrappingKey);
                            response.ErrorText = "Key Created?";

Журналы попытки 2:

12:02:28 03696-5152:STRTOpenSession {Slot=1 Flgs=6 }
12:02:28 03696-5152:FINIOpenSession CKR_OK(1609ms) {Sesn=1 }

12:02:28 03696-5152:STRTLogin {Sesn=1 User=1 PIN="********" }
12:02:28 03696-5152:FINILogin CKR_OK(1734ms) {}

12:02:28 03696-5152:STRTGenerateKey {Sesn=1 Mech=(CKM_AES_KEY_GEN,"") AttrList={CKA_CLASS="04000000" CKA_KEY_TYPE="1f000000" CKA_TOKEN="01" CKA_ENCRYPT="01" CKA_LABEL="TempWrapKey" CKA_CLASS="04000000" CKA_KEY_TYPE="1f000000" CKA_TOKEN="01" CKA_ENCRYPT="01" CKA_PRIVATE="01" CKA_DECRYPT="01" CKA_VALUE_LEN="20000000" CKA_WRAP="01" CKA_UNWRAP="01" CKA_SENSITIVE="01" CKA_SIGN="01" CKA_DERIVE="00" CKA_EXTRACTABLE="00" } }
12:02:29 03696-5152:FINIGenerateKey CKR_OK(1750ms) {Obj=2000001 }

12:02:29 03696-5152:STRTEncrypt_Init {Sesn=1 Mech=(CKM_AES_ECB,"") Obj=2000001 }
12:02:29 03696-5152:FINIEncrypt_Init CKR_OK(1750ms) {}

12:02:29 03696-5152:STRTEncrypt {Sesn=1 "23724cf301e85a53fc3f5aea6384c16e" pusEncryptedDataLen=0xf91ddca0 *pusEncryptedDataLen=0 }
12:02:29 03696-5152:FINIEncrypt CKR_OK(1750ms) {"" pusEncryptedDataLen=0xf91ddca0 *pusEncryptedDataLen=16 }

12:02:29 03696-5152:STRTEncrypt {Sesn=1 "23724cf301e85a53fc3f5aea6384c16e" pusEncryptedDataLen=0xf91ddca0 *pusEncryptedDataLen=16 }
12:02:29 03696-5152:FINIEncrypt CKR_OK(1750ms) {"2e151cc889470864b5fb5a24146fecb2" pusEncryptedDataLen=0xf91ddca0 *pusEncryptedDataLen=16 }

12:02:29 03696-5152:STRTUnwrapKey {Sesn=1 Mech=(CKM_AES_ECB,"") Obj=2000001 "2e151cc889470864b5fb5a24146fecb2" AttrList={CKA_LABEL="Key2372" CKA_CLASS="04000000" CKA_KEY_TYPE="1f000000" CKA_TOKEN="01" CKA_PRIVATE="01" CKA_ENCRYPT="01" CKA_DECRYPT="01" CKA_SENSITIVE="01" CKA_VERIFY="01" CKA_SIGN="01" CKA_WRAP="01" CKA_UNWRAP="01" CKA_DERIVE="00" CKA_EXTRACTABLE="00" CKA_VALUE_LEN="20000000" } }
12:02:29 03696-5152:FINIUnwrapKey ***CKR_WRAPPED_KEY_INVALID***(1750ms) {Obj=0 }

12:02:29 03696-5152:STRTCloseSession {Sesn=1 }
12:02:29 03696-5152:FINICloseSession CKR_OK(1765ms) {}

Должен ли я сгенерировать еще один ключ и использовать его для распаковки?


person G .    schedule 30.08.2018    source источник
comment
Не могли бы вы показать типы и значения переменных keyLabel и Value?   -  person Maarten Bodewes    schedule 31.08.2018
comment
Во второй попытке вы сначала создаете ключ, а затем разворачиваете его. Если не ошибаюсь, ключ будет создан автоматически; нет необходимости заранее указывать / создавать ключевой объект. Обратите внимание, что во второй попытке у вас будет много повторяющихся полей в шаблоне. Это не показывает точности, необходимой для борьбы с криптовалютой.   -  person Maarten Bodewes    schedule 31.08.2018
comment
Извините за путаницу, я добавил типы и значения для keyLabel и Value. Значение создается пользователем как шестнадцатеричное значение. Случайно опубликованы тестовые атрибуты и попытка создания ключевого объекта, те, которые находятся наверху, теперь обновлены и соответствуют приведенным ниже операторам журнала, еще раз извините. Дубликаты вызывают другую ошибку и согласуются с недостаточной точностью, чтобы справиться с согласованным шаблоном :) Что касается метода создания ключа, я подумал сначала создать объект, а функция развертывания перезаписать ключ без значений с ключом развернутого значения. Это не работает.   -  person G .    schedule 31.08.2018
comment
В вашей попытке 2 вы устали шифровать ключ, используя режим CBC с IV, прежде чем распаковывать его?   -  person always_a_rookie    schedule 02.09.2018
comment
Использование режима CBC с IV перед разворачиванием помогло. Спасибо @always_a_rookie_to_learn! Я уверен, что мне придется позже изменить атрибуты, чтобы проверить значение ключа, но я замечаю, что, когда я использую одно и то же значение ключа для двух новых ключей, они, похоже, не соответствуют зашифрованному и дешифрованному тексту, по крайней мере, на Сетевой HSM. Есть мысли о том, почему это должно быть?   -  person G .    schedule 04.09.2018
comment
@Г. Пробовали ли вы шифрование одним ключом и дешифрование другим ключом, используя те же параметры шифрования в операции дешифрования, что и операция шифрования?   -  person always_a_rookie    schedule 05.09.2018
comment
@always_a_rookie_to_learn Да, я получаю CKR_DATA_INVALID при расшифровке с использованием другого ключа. Но используя тот же ключ, я могу успешно зашифровать и расшифровать. Я новичок в SO / crypto (возможно, что-то тупое), но вот механизмы: session.Encrypt (новый механизм (CKM.CKM_AES_CBC_PAD, Iv), privateKeyHandles [0], rawData); session.Decrypt (новый механизм (CKM.CKM_AES_CBC_PAD, Iv), privateKeyHandles [0], rawData); Значения IV такие же, как те, которые использовались для создания ключа. RawData - это массив байтов. PrivateHandle [0] - это просто возвращаемый ключ, соответствующий метке и классу.   -  person G .    schedule 06.09.2018
comment
Хотя могут быть полезны разные системы; шифрование одним ключом и дешифрование другим ключом (вместе со значениями ключей / соответствием шифрования / дешифрования в целом) отлично работает в нашем программном обеспечении SafeNet HSM ...   -  person G .    schedule 06.09.2018
comment
@Г. В методе дешифрования вы передаете rawData для дешифрования. Вы должны передать зашифрованное значение (возвращаемое значение метода encrypt).   -  person always_a_rookie    schedule 07.09.2018
comment
@always Однако процесс шифрования и дешифрования - это отдельные методы. Поэтому, когда я вызываю метод дешифрования, он извлекает текстовое поле с зашифрованным значением (преобразуется в байты). Я могу опубликовать код от них, если это поможет, но это логин, найти ключ на метке и классе и запустить эту строку шифрования / дешифрования. Вызовет ли механизм этих методов какие-либо проблемы с механизмом, который я использую для разворачивания?   -  person G .    schedule 07.09.2018


Ответы (2)


По-видимому, после разговора с Gemalto и нескольких комментариев, это не может быть сделано на семействе сетевых HSM без защиты серверов. Процесс отлично работает для HSM защищенных серверов (теперь у них есть защищенный сервер Network HSM). После обновления процесса распаковки для использования режима CBC с IV я смог создать ключи, но не с указанными значениями ключей.

person G .    schedule 21.09.2018

Обновление: в пример добавлена ​​функция GenerateKeyPair.

Мне удалось «загрузить» ключ AES в HSM с помощью следующего кода:

        // Create factories used by Pkcs11Interop library
        Pkcs11InteropFactories factories = new Pkcs11InteropFactories();

        // Load unmanaged PKCS#11 library
        using (IPkcs11Library pkcs11Library = factories.Pkcs11LibraryFactory.LoadPkcs11Library(factories, options.PKCS11LibraryPath, AppType.SingleThreaded))
        {
            // Find first slot with token present
            ISlot slot = pkcs11Library.GetSlotList(SlotsType.WithTokenPresent)[0];

            // Open RW session
            using (ISession session = slot.OpenSession(SessionType.ReadWrite))
            {
                // Login as normal user
                session.Login(CKU.CKU_USER, options.Pin);

                // Generate asymmetric key encryption key pair
                IObjectHandle asymKeyEncrpytionPublicKey = null;
                IObjectHandle asymKeyEncryptionPrivateKey = null;
                Helpers.GenerateKeyPair(session, out asymKeyEncrpytionPublicKey, out asymKeyEncryptionPrivateKey, "KEK");

                // Load aes key from file
                // Generate the key with the following command: "openssl rand -out aes256-forImport.key 32"
                byte[] sourceKey = File.ReadAllBytes(options.aesKeyPath);
                Console.WriteLine($"Loaded AES key: {BitConverter.ToString(sourceKey)}");

                // Specify wrapping mechanism
                IMechanism asymMechanism = session.Factories.MechanismFactory.Create(CKM.CKM_RSA_PKCS);

                // Encrypt key in file
                byte[] encryptedKey = session.Encrypt(asymMechanism, asymKeyEncrpytionPublicKey, sourceKey);

                // Define attributes for unwrapped key
                List<IObjectAttribute> objectAttributes = new List<IObjectAttribute>();
                objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
                objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_KEY_TYPE, CKK.CKK_AES));
                objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ENCRYPT, true));
                objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_DECRYPT, true));
                objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_EXTRACTABLE, options.markExtractable));
                objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true));
                objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_LABEL, $"Unwrapped at {DateTime.Now}"));

                // Symmetric unwrap key
                IObjectHandle symUnwrappedKey = session.UnwrapKey(asymMechanism, asymKeyEncryptionPrivateKey, encryptedKey, objectAttributes);
            }
        }

-----

        /// <summary>
        /// Generates asymetric key pair.
        /// </summary>
        /// <param name='session'>Read-write session with user logged in</param>
        /// <param name='publicKeyHandle'>Output parameter for public key object handle</param>
        /// <param name='privateKeyHandle'>Output parameter for private key object handle</param>
        public static void GenerateKeyPair(ISession session, out IObjectHandle publicKeyHandle, out IObjectHandle privateKeyHandle, string label = "")
        {
            // The CKA_ID attribute is intended as a means of distinguishing multiple key pairs held by the same subject
            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_TOKEN, true));
            publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_PRIVATE, false));
            publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_LABEL, $"{label} public"));
            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_VERIFY_RECOVER, true));
            publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_WRAP, true));
            publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_MODULUS_BITS, 2048));
            publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_PUBLIC_EXPONENT, new byte[] { 0x01, 0x00, 0x01 }));

            // Prepare attribute template of new private key
            List<IObjectAttribute> privateKeyAttributes = new List<IObjectAttribute>();
            ////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, $"{label} private"));
            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_SIGN_RECOVER, true));
            privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_UNWRAP, true));

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

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

person Rufus Buschart    schedule 05.09.2019
comment
не могли бы вы опубликовать реализацию Helpers.GenerateKeyPair (сессия, вне asymKeyEncrpytionPublicKey, вне asymKeyEncryptionPrivateKey, KEK); Пытаясь сделать то же самое, я получаю следующую ошибку для механизма: CKM_RSA_X9_31_KEY_PAIR_GEN C_GenerateKeyPair не удалось с ошибкой CKR_ATTRIBUTE_VALUE_INVALID: 0x00000013 - person Pravin; 23.04.2020