Как создать цифровую подпись в формате CAdES с помощью Pkcs11Interop на C# без данных или документа для подписи

Я новичок в криптографическом программировании. Я хочу создать только цифровую подпись на C# в формате CAdES с использованием библиотеки Pkcs11Interop, не имея данных, документа или сообщения для подписи, я хочу, чтобы строка подписи использовалась только в любом файле json или xml, созданном из моего приложения. Я использовал библиотеку Pkcs11Interop, потому что у меня есть смарт-токен "Cryptoki" с неуправляемой библиотекой dll PKCS#11, который я должен использовать для создания подписи. Вот мой пример кода, основанный на образцах с открытым исходным кодом Pkcs11Interop.

using System;
using System.Collections.Generic;
using Net.Pkcs11Interop.Common;
using Net.Pkcs11Interop.HighLevelAPI;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Pkcs11InteropFactories factories = new Pkcs11InteropFactories();

            using (IPkcs11Library pkcs11Library = factories.Pkcs11LibraryFactory.LoadPkcs11Library(factories, @"C:\eps2003csp11.dll", AppType.MultiThreaded))
            {
                ILibraryInfo libraryInfo = pkcs11Library.GetInfo();

                foreach (ISlot slot in pkcs11Library.GetSlotList(SlotsType.WithOrWithoutTokenPresent))
                {
                    ISlotInfo slotInfo = slot.GetSlotInfo();

                    if (slotInfo.SlotFlags.TokenPresent)
                    {
                        using (ISession session = slot.OpenSession(SessionType.ReadWrite))
                        {
                            session.Login(CKU.CKU_USER, @"000000");

                            IObjectHandle publicKey = null;
                            IObjectHandle privateKey = null;
                            GenerateKeyPair(session, out publicKey, out privateKey);

                            IMechanism mechanism = session.Factories.MechanismFactory.Create(CKM.CKM_CMS_SIG);

                            byte[] sourceData = ConvertUtils.Utf8StringToBytes(null);

                            byte[] signature = session.Sign(mechanism, privateKey, sourceData);

                            string vStringSignature = ConvertUtils.BytesToBase64String(signature);
                            Console.WriteLine("Signature:  " + vStringSignature);
                                                        
                            session.DestroyObject(privateKey);
                            session.DestroyObject(publicKey);
                            session.Logout();
                        }
                    }
                }
            }
            
        }
        static void GenerateKeyPair(ISession session, out IObjectHandle publicKeyHandle, out IObjectHandle privateKeyHandle)
        {
            // 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, "Digital Business ERP"));
            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, 1024));
            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, "Digital Business ERP"));
            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);
        }
    }
}

Если я поставлю "null" или пустые двойные кавычки в следующую переменную sourceData

byte[] sourceData = ConvertUtils.Utf8StringToBytes(null);

или же

byte[] sourceData = ConvertUtils.Utf8StringToBytes("");

Я получаю ошибку при создании такой подписи

byte[] signature = session.Sign(mechanism, privateKey, sourceData);

или же

byte[] signature = session.Sign(mechanism, privateKey, null);

Только когда я помещаю образцы данных, такие как "Hello World", строка подписи создается успешно, но она содержит строку данных, которая в этом примере является "Hello World".

Я хочу сгенерировать строку подписи без каких-либо данных. Также в моем коде я не знаю, как установить формат подписи в CAdES.

1 ответ

Тарек

Я также борюсь с той же проблемой, пытаясь создать подпись cades-bes для документа json и прикрепить ее к исходному документу json в качестве свойства.

Это часть правил египетских налоговых органов по отправке подписанных счетов с использованием их API.

Я пробовал классы CMS. Net core, и удалось создать подпись документа, но Api отклоняет мой документ, и я получаю ответ 400 «Плохой запрос».

Если вы справились в своем эдуворе, пожалуйста, добавьте решение здесь.

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