繁体   English   中英

C#中外部计算的hash的PKCS#7签名

[英]PKCS#7 signature of externally calculated hash in C#

当前 state

我正在开发基于 Web 的应用程序,该应用程序用于管理 PDF forms 并允许用户填写表格、处理批准并签署 PDF。

应用程序使用 Adobe LiveCycle 计算文档摘要并运行外部应用程序(呼叫签名者应用程序)对 hash 进行签名。然后 hash 被发送回 LiveCycle,嵌入到 PDF 文档中。

签名者应用程序接收预先计算的消息摘要并生成 PKCS#7 签名。 Windows 证书库用于查找签名证书和私钥。 我们必须支持使用存储私钥的 USB 个电子令牌。

目前我们在 Java 中编写了功能齐全的签名者应用程序。它使用 BouncyCastle 库和 SunMSCAPI 加密提供程序来访问 Windows 证书存储。 以下是负责签名的代码片段。

protected byte[] signCMS(byte[] hash, PrivateKey key, X509Certificate[] cert) throws CertStoreException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, CMSException, OperatorCreationException, CertificateException {
        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
        ASN1EncodableVector signedAttrs = new ASN1EncodableVector();
        signedAttrs.add(new Attribute(CMSAttributes.messageDigest, new DERSet(new DEROctetString(hash))));
        ContentSigner sha256Signer = new JcaContentSignerBuilder("SHA256withRSA").setProvider("SunMSCAPI").build(key);
        gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(new BouncyCastleProvider()).build()).setSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator(new AttributeTable(signedAttrs))).build(sha256Signer, cert[0]));
        gen.addCertificates(generatedCertStore(cert));
        return gen.generate(new CMSAbsentContent()).toASN1Structure().getEncoded();
}

以上代码使用 SunMSCAPI 加密提供程序,完全支持使用 USB 个电子令牌,无需导出私钥。

需要 state

客户不同意Java在客户端的使用。 我正在处理签名者应用程序的C#变体。

问题

我不知道如何从外部计算的消息摘要生成 PKCS#7 签名。 我总是看起来消息摘要被散列了两次。 Acrobat Reader 然后报告文档在签名后被修改。

我尝试将 BouncyCastle 用于 .NET,并且在将 BouncyCastle 库用于 .NET 时能够处理工作签名,但它需要从 Windows 证书存储区导出私钥。 此解决方案不支持使用 USB 电子令牌。

当前非工作 C# 变体

public static byte[] Sign(byte[] hash, X509Certificate2 cert2)
        {
            List<byte> encodedMessageDigestList = new List<byte>(hash.Length + 2);
            encodedMessageDigestList.Add(4);
            encodedMessageDigestList.Add(checked((byte)(hash.Length)));
            encodedMessageDigestList.AddRange(hash);
            byte[] encodedMessageDigest = encodedMessageDigestList.ToArray();

            Pkcs9MessageDigest md = new Pkcs9MessageDigest();
            Pkcs9AttributeObject pAttribute = new Pkcs9AttributeObject("1.2.840.113549.1.9.4", encodedMessageDigest);
            md.CopyFrom(pAttribute);

            SignedCms cms = new(new ContentInfo(md.Oid, md.RawData));

            CmsSigner cmsSigner = new();
            cmsSigner.Certificate = cert2;
            cmsSigner.IncludeOption = X509IncludeOption.WholeChain;

            cms.ComputeSignature(cmsSigner, false);

            return cms.Encode();
}

我们可以将预先计算的 Pkcs9MessageDigest(摘要 hash 已计算)提供到 CmsSigner 的 SignedAttribues 集合中。 这将覆盖自动生成一个的默认行为。

https://learn.microsoft.com/en-us/do.net/api/system.security.cryptography.pkcs.pkcs9messagedigest?view=do.net-plat-ext-7.0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM