如何使用 iText 在 Web 环境中通过智能卡签署 PDF?

2023-12-04

阅读以下参考文献:

  • iText 数字签名白皮书, and C# 示例。 (具体来说第4章)对于那些有兴趣的人,另一个精彩而简洁的总结PDF 签名过程。
  • CAPICOM 文档.
  • 此处和 iText 邮件列表档案上的在线示例/问题,例如here and here.

哈希代码:

BouncyCastle.X509Certificate[] chain = Utils.GetSignerCertChain();
reader = Utils.GetReader();
MemoryStream stream = new MemoryStream();
using (var stamper = PdfStamper.CreateSignature(reader, stream, '\0'))
{
    PdfSignatureAppearance sap = stamper.SignatureAppearance;
    sap.SetVisibleSignature(
        new Rectangle(36, 740, 144, 770),
        reader.NumberOfPages,
        "SignatureField"
    );
    sap.Certificate = chain[0];
    sap.SignDate = DateTime.Now;
    sap.Reason = "testing web context signatures";

    PdfSignature pdfSignature = new PdfSignature(
        PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED
    );
    pdfSignature.Date = new PdfDate(sap.SignDate);
    pdfSignature.Reason = sap.Reason;
    sap.CryptoDictionary = pdfSignature;

    Dictionary<PdfName, int> exclusionSizes = new Dictionary<PdfName, int>();
    exclusionSizes.Add(PdfName.CONTENTS, SIG_BUFFER * 2 + 2);
    sap.PreClose(exclusionSizes);

    Stream sapStream = sap.GetRangeStream();
    byte[] hash = DigestAlgorithms.Digest(
        sapStream,
        DigestAlgorithms.SHA256
    );

// is this needed?
    PdfPKCS7 sgn = new PdfPKCS7(
        null, chain, DigestAlgorithms.SHA256, true
    );
    byte[] preSigned = sgn.getAuthenticatedAttributeBytes(
        hash, sap.SignDate, null, null, CryptoStandard.CMS
    );

    var hashedValue = Convert.ToBase64String(preSigned);
}

只是一个简单的测试 - 在初始页面请求时创建一个虚拟 Pdf 文档,计算哈希值,并放入 Base64 编码的隐藏输入字段中。 (这hashedValue above)

然后在客户端使用 CAPICOM 来 POST 表单并获取用户签名的响应:

PdfSignatureAppearance sap = (PdfSignatureAppearance)TempData[TEMPDATA_SAP];
PdfPKCS7 sgn = (PdfPKCS7)TempData[TEMPDATA_PKCS7];
stream = (MemoryStream)TempData[TEMPDATA_STREAM];
byte[] hash = (byte[])TempData[TEMPDATA_HASH];

byte[] originalText = (Encoding.Unicode.GetBytes(hashValue));
// Oid algorithm verified on client side
ContentInfo content = new ContentInfo(new Oid("RSA"), originalText);

SignedCms cms = new SignedCms(content, true);
cms.Decode(Convert.FromBase64String(signedValue));
// CheckSignature does not throw exception
cms.CheckSignature(true);
var encodedSignature = cms.Encode();

/* tried this too, but no effect on result
sgn.SetExternalDigest(
    Convert.FromBase64String(signedValue),
    null,
    "RSA"
);
byte[] encodedSignature = sgn.GetEncodedPKCS7(
    hash, sap.SignDate, null, null, null, CryptoStandard.CMS
);
*/
byte[] paddedSignature = new byte[SIG_BUFFER];
Array.Copy(encodedSignature, 0, paddedSignature, 0, encodedSignature.Length);
var pdfDictionary = new PdfDictionary();
pdfDictionary.Put(
    PdfName.CONTENTS,
    new PdfString(paddedSignature).SetHexWriting(true)
);
sap.Close(pdfDictionary);

所以现在我不确定我是否搞乱了哈希部分、签名部分或两者。在上面的签名代码片段和客户端代码(未显示)中,我调用的是我认为的签名验证代码,但这也可能是错误的,因为这对我来说是第一次。获得臭名昭著的“文件自签署以来已被更改或损坏“打开 PDF 时签名消息无效。

客户端代码(不是我编写的)可以在这里找到。源有一个变量命名错误,已更正。作为参考,CAPICOM 文档显示签名响应采用 PKCS#7 格式.

编辑2015-03-12:

经过 @mkl 的一些很好的指导和更多的研究后,看来 CAPICOM 是切实可行地在这种情况下无法使用。尽管没有明确记录,(还有什么新内容?)根据here and here, CAPICOM 需要一个 utf16 字符串 (Encoding.Unicode在 .NET 中)作为创建数字签名的输入。从那里开始,它要么填充要么截断(取决于前一句中的哪个来源正确)如果长度为奇数,则接收到任何数据。 IE。签名创建将总是失败 if the Stream由返回PdfSignatureAppearance.GetRangeStream()长度为奇数。也许我应该创建一个我很幸运选项:如果范围流长度是偶数,则进行签名,并抛出一个InvalidOperationException如果奇数。 (悲伤的幽默尝试)

For reference, here's the test project.

编辑2015-03-25:

为了关闭这个循环,这是 VS 2013 ASP.NET MVC 项目的链接。可能不是最好的方法,但它does提供一个完全有效的解决方案到问题。由于 CAPICOM 的奇怪且不灵活的签名实现,如上所述,我们知道可能的解决方案可能需要第二次传递,并且如果返回值是,则需要注入额外字节的方法PdfSignatureAppearance.GetRangeStream()(再次,Stream.Length) 是奇数。我本来打算通过填充 PDF 内容来尝试漫长而艰难的方法,但幸运的是,一位同事发现填充要容易得多PdfSignatureAppearance.Reason。需要第二遍才能使用 iText[Sharp] 执行某些操作并不是史无前例的 - 例如为文档页眉/页脚添加第 x 页(共 y 页).


Use of PdfPkcs7

服务器端代码在计算范围流摘要之后和将数据转发到网页之前包含此块:

PdfPKCS7 sgn = new PdfPKCS7(
    null, chain, DigestAlgorithms.SHA256, true
);
byte[] preSigned = sgn.getAuthenticatedAttributeBytes(
    hash, sap.SignDate, null, null, CryptoStandard.CMS
);

var hashedValue = Convert.ToBase64String(preSigned);

在当前的情况下,这是没有必要的。仅当您使用的外部签名 API 仅返回签名摘要时才需要它;在这种情况下PdfPKCS7实例构建 CMS/PKCS#7 签名容器。另一方面,您使用您知道的 API

CAPICOM 文档称签名响应采用 PKCS#7 格式。

因此,您不需要并且(更重要的是)不得使用 the PdfPKCS7实例。

Sign.js 签名什么

服务器端的内容hash变量已经是要签名的数据的哈希摘要值。因此,前端(即此处使用的sign.js)不得再次对其进行哈希处理以获取要放入签名中的消息摘要属性值。

但 IE 的 Sign.js 签名方法最终会执行

var signedData = new ActiveXObject("CAPICOM.SignedData");

// Set the data that we want to sign
signedData.Content = src;

SignedData.Content另一方面,被记录为

Content 读/写待签署的数据。

(msdn: "SignedData 对象")

所以来自后端的哈希被用作待签名数据而不是作为待签名数据的哈希值,您确实散列了两次,因此散列值错误。

因此,看起来您必须传输整个范围的流,这并不实际......

“但是曾经有使用 CAPICOM 签署样本的情况……”

事实上,一些旧的 iTextSharp(版本 4.x)签名示例使用了 CAPICOM。但该代码之所以有效,是因为它创建了 PDF 签名类型的签名adbe.pkcs7.sha1范围流的 SHA1 哈希确实是嵌入 PKCS#7 签名并由 PKCS#7 签名签名的数据.

这不再是真正的选择,因为

  • 它需要使用 SHA1,这在严重的情况下是无效的,并且
  • 至少自 ISO 32000-1 (2008) 起就不再鼓励使用它,并将在 ISO 32000-2(正在开发中)中正式弃用。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 iText 在 Web 环境中通过智能卡签署 PDF? 的相关文章

  • C# ItextSharp Fontawesome 图标(货币)- PDF

    我在导入图标 fontawesome webfont ttf 并在 PDF 上显示它们时遇到问题 但我无法在 PDF 上显示它们 特别是货币图标 fa money 我能够从CultureInfo 类 如果除此之外我还错过了什么 chunkR
  • AxInterop 和 Interop 有什么区别?

    我已将 ocx 添加到 VS 的工具箱中 创建了两个 dll Interop NNN dll AxInterop NNN dll 每一个是什么 两者都需要吗 Interop xxx dll 和 AxInterop xxx dll 分别是引用
  • 作为 Windows 服务运行时的 PCSC.InvalidContextException

    我一直在使用 pcsc sharp 库开发一个小型智能卡扫描仪应用程序 该应用程序作为控制台应用程序运行时工作正常 代码如下 using System using System Collections Generic using Syste
  • 如何将 ISO7816 选择命令与 DESfire Ev1 卡一起使用?

    我有一张 DESfire Ev1 版本 1 3 卡 我正在尝试使用 ISO7816 apdu 样式选择一个文件 我有一份文件 需要帮助A0 A1 A2我可以使用本机或包装模式选择它 Native gt 5A A0 A1 A2 lt 00 W
  • Ajax 调用在 IE 中不起作用,除非您修改安全设置

    IE 有时很糟糕 直到 IE 10 IE 才提供对 XMLHttpRequest 对象的支持 相反 您必须使用 XActiveXObject 对象来运行 AJAX 调用 JQuery 默认启动该对象 并在三元函数中维护它 如果它存在 本质上
  • pdfptable的不可见边框

    我正在使用 iText 库在 Java 中生成 pdf 文件 我正在 pdfptable 中写入数据 如何使表格边框不可见 PdfPTable 的边框元素由添加到表中的 PdfPCell 定义 每个单元格都有自己的样式 格式 这是 API
  • 打开与 Java Card 和 Global Platform 的安全连接

    在模拟器上成功开发 Java Card 后 现在我正在处理一个真正的 Java Card 金雅拓 IDCore 3010 http www gemalto com dwnld 6589 IDCore3010 Product Datashee
  • 图像未按顺序添加到 pdf 文档 itextsharp 中(元素顺序错误)

    我现在正在使用 iTextSharp 5 4 5 几个星期 本周 我在文档中的元素顺序方面遇到了一些奇怪的事情 我正在制作一份包含主题和图像 图表 的 pdf 报告 该文档的格式如下 NR 主题 1 的主题标题 主题 1 的图表图像 来自
  • 使用自签名证书签署 PowerShell 脚本(并且不使用 makecert.exe)

    我正在尝试签署一份 ps1使用自签名证书 用例是我自己在私人开发站上编写的脚本 因此无需使用 或付费 真正的 CA 但是 无论我阅读多少关于证书生成和数字签名主题的指南 我似乎都无法使其正常工作 这是我到目前为止所取得的成就 Create
  • 重命名 PDF 文件中的指定目标

    我一直在 PDF 文件中使用命名目标来在文件中的特定位置打开 PDF 文件 负责生成 PDF 文档的团队使用工具从书签自动生成命名目的地 因此命名目的地往往具有诸如 9 Glossary 或 Additional Information 之
  • AxAcroPDF - Vista64 类未注册错误

    我们有一个用 C 编写的 WinForms 应用程序 它使用 AxAcroPDFLib AxAcroPDF 组件来加载和打印 PDF 文件 在 Windows XP 下一直运行没有任何问题 我已将开发环境移至 Vista 64 位 现在除非
  • 智能卡 CMS 解密

    我在用着充气城堡管理我的项目的加密功能 我设法使用CMS用于加密和解密 两个密钥都存储在我的文件系统中 a cert and a p12 这是我实际使用的两个函数 private static byte CmsEncrypt byte me
  • 无法将 iTextSharp 与 ASP.NET 5 Core 一起使用

    我正在尝试将 iTextSharp 与 ASP NET 5 Core 一起使用 但是 当我尝试使用 iTextSharp 5 5 5 构建 ASP NET 应用程序时 出现这些错误 Code using Microsoft AspNet M
  • 如何以编程方式从 Excel 中的 VBA 宏中删除数字签名?

    有没有办法以编程方式从 Excel 工作表的 VBA 宏中删除数字签名 即相当于进入 VBA 编辑器 转到 工具 菜单 gt 数字签名 并单击 删除 的代码 有趣的问题 出于安全原因 它故意不属于 Excel 对象模型的一部分 可以从证书存
  • 如何向页面添加 HTML 页眉和页脚?

    如何使用 itext 从 html 源添加标题到 pdf 目前 我们已经扩展了 PdfPageEventHelper 并重写了这些方法 工作正常 但当我到达 2 个以上页面时 它会抛出 RuntimeWorkerException Over
  • 与 OLE 服务器或 ActiveX 控件通信

    MS Access 2010 Win 7 常规形式我没有故意放置任何 ActiveX 或 OLE 东西 甚至不确定它们是什么 但无论如何 每当我在特定形式的代码中放入某些内容时 它都会说 您作为事件属性设置输入的表达式 XXXXX 产生了以
  • 无法将小程序(.cap 文件)下载到智能卡中:SW 6D 00(无效指令)

    我正在开发 JCOP3 SecID P60 CS 智能卡 我正在尝试使用下载 cap 文件pyAPDU工具购买 我得到 6D 00回答 无效指令 与 的结果相同gp 请问有人可以告诉我问题出在哪里吗 未给出您用于初始选择颁发者安全域 ISD
  • 如何防止在 ActiveX 方法调用期间重新进入 WPF 事件处理程序?

    我们从 WPF 和 STA 应用程序中调用 ActiveX 组件上的方法 此调用是通过以下方式后期绑定执行的 res ocx GetType InvokeMember methodName flags null ocx args 其中 oc
  • 编码用于验证 PIN 的 APDU 命令时出现问题

    我正在尝试使用发送验证 pin 命令javax smartcardioAPI 我的密码是 12345678 根据我在网上找到的一些示例 我尝试使用此 APDU 00 20 00 83 08 01 02 03 04 05 06 07 08 但
  • 在 Android 中使用 iText 将图像添加到特定位置

    我想使用 Android 中的 iText 将图像添加到 PDF 文件中的特定位置 这是一个可填写的表单 我添加了作为图像占位符的文本框 我想要做的就是像这样获取该文本框和图像 public class FormFill public st

随机推荐