[英]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 集合中。 这将覆盖自动生成一个的默认行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.