.NET Framework 4.8签名后如何向UnsignedAttribute添加内容
.NET Framework 4.8中签名后修改UnsignedAttributes的问题及解决方案尝试
版本差异
- .NET Framework 4.8 里,
System.Security.Cryptography.Pkcs.SignerInfo.UnsignedAttributes属性仅返回数据副本,修改无法同步到根SignedCms对象,导致签名生成后无法修改未签名属性。 - .NET 8 中
SignerInfo类新增AddUnsignedAttribute(AsnEncodedData unsignedAttribute)方法,支持签名后向UnsignedAttributes添加数据。
关键需求
签名后操作UnsignedAttributes是添加时间戳授权中心(TSA)时间戳响应的核心步骤。
已尝试的方案及问题
- 已知有通过NuGet包结合P/Invoke操作
UnsignedAttributes的可行方案,但无法找到有效实现方式。 - 使用BouncyCastle解码已生成的签名为
CmsSignedData并修改UnsignedAttributes:虽成功添加属性(经ASN.1解码验证),但会导致签名失效。 - 尝试通过反射覆盖私有属性:因部分属性无setter而失败(注:时间戳响应本身是有效的)。
最小复现代码
以下代码尝试向空白PDF的UnsignedAttributes添加signingTime的OID及NULL值,运行前需将"THUMBPRINT"替换为微软证书存储区中带私钥且无额外安全限制的证书指纹:
using System; using System.IO; using System.Security.Cryptography.Pkcs; using System.Security.Cryptography.X509Certificates; class Program { static void Main() { // 读取空白PDF文件 byte[] pdfContent = File.ReadAllBytes("blank.pdf"); // 从证书存储区获取指定证书 using X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); store.Open(OpenFlags.ReadOnly); X509Certificate2 targetCert = store.Certificates.Find( X509FindType.FindByThumbprint, "THUMBPRINT", false)[0]; store.Close(); // 初始化签名对象并计算签名 ContentInfo contentInfo = new ContentInfo(pdfContent); SignedCms signedCms = new SignedCms(contentInfo, false); CmsSigner signer = new CmsSigner(targetCert); signedCms.ComputeSignature(signer); // 尝试添加signingTime属性(.NET Framework 4.8中此修改不会同步到SignedCms) Oid signingTimeOid = new Oid("1.2.840.113549.1.9.5"); AsnEncodedData signingTimeAttribute = new AsnEncodedData(signingTimeOid, new byte[] { 5, 0 }); // NULL值 signedCms.SignerInfos[0].UnsignedAttributes.Add(signingTimeAttribute); // 导出签名后的数据 byte[] signedData = signedCms.Encode(); File.WriteAllBytes("signed_with_attr.pdf", signedData); } }
内容的提问来源于stack exchange,提问作者Dimiikou
相关产品推荐
相关产品推荐

