【问题标题】:How to create Digital Signature with CAdES format using Pkcs11Interop in C# without data or document to sign如何在 C# 中使用 Pkcs11Interop 创建具有 CAdES 格式的数字签名,无需数据或文档进行签名
【发布时间】:2020-11-04 14:42:14
【问题描述】:

我是加密编程的新手。 我只想使用 Pkcs11Interop 库创建具有 CAdES 格式的 C# 数字签名,而无需签名数据或文档或消息,我希望签名字符串仅用于从我的应用程序生成的任何 json 或 xml 文件。 我使用了 Pkcs11Interop 库,因为我有一个带有非托管 PKCS#11 dll 库的智能令牌“Cryptoki”,我必须使用它来制作签名。 这是我基于 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);
        }
    }
}

如果我在以下 sourceData 变量中加上“null”或空双引号

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。

【问题讨论】:

  • 听起来您想创建一个没有实际签名的模板。证书是 Xml,因此您想要添加一个 xml 标记,而不是在内部文本中放置任何内容。所以你不需要运行sign方法。只需将标签添加到 xml 文档中即可。
  • 是的,你没看错,我希望我的 HSM 令牌的签名模板稍后在需要时添加到 xml 标记或 json 元素中。
  • 您想要添加标签的 Xml 文档或字符串在哪里?我已经做过很多次了。在以下帖子中查看我的答案:stackoverflow.com/questions/46722997/…
  • 您在该链接中的答案仅适用于 Xml 文档,那么 json 文档呢?这就是为什么我希望将签名模板作为字符串添加到我想要的任何文件中。
  • 证书是 XML 格式,签名是 XML。从未见过 JSON 签名。

标签: c# cryptography pkcs#11 pkcs11interop cryptoki


【解决方案1】:

塔雷克

我也在努力解决同样的问题,试图在 json 文档上生成 cades-bes 签名并将其作为属性附加到原始 json 文档。

这是埃及税务机关使用其 API 提交已签名发票的规则的一部分。

我尝试了 CMS 类。 Net core,并设法生成了文档的签名,但 Api 拒绝了我的文档,我得到了 400 "Bad request" 的响应。

如果您在 eduvor 中管理过,请在此处添加解决方案。

【讨论】:

  • 这并不能真正回答问题。如果您有其他问题,可以点击 提问。要在此问题有新答案时收到通知,您可以follow this question。一旦你有足够的reputation,你也可以add a bounty 来引起对这个问题的更多关注。 - From Review
猜你喜欢
  • 2015-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-13
  • 2015-09-12
  • 1970-01-01
  • 2015-06-20
相关资源
最近更新 更多