itextsharp 使用签名哈希签名 pdf

2023-12-29

我正在尝试通过签名服务签署 pdf。此服务需要发送十六进制编码的 SHA256 摘要,作为回报,我收到十六进制编码的签名值。除此之外,我还收到签名证书、中间证书、OCSP 响应和 TimeStampToken。但是,我已经在尝试使用签名值对 pdf 进行签名时陷入困境。

我读过布鲁诺的白皮书,过度浏览互联网,并尝试了许多不同的方法,但签名总是显示为无效。

我的最新尝试:

首先,准备pdf

PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Certificate = signingCertificate;
IExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
MakeSignature.SignExternalContainer(appearance, external, 8192);

string hashAlgorithm = "SHA-256";
PdfPKCS7 sgn = new PdfPKCS7(null, chain, hashAlgorithm, false);
PdfSignatureAppearance appearance2 = stamper.SignatureAppearance;
Stream stream = appearance2.GetRangeStream();
byte[] hash = DigestAlgorithms.Digest(stream, hashAlgorithm);
byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CMS);

哈希 byte[] sh 并转换为字符串,如下所示

private static String sha256_hash(Byte[] value)
{
    using (SHA256 hash = SHA256.Create())
    {
         return String.Concat(hash.ComputeHash(value).Select(item => item.ToString("x2"))).ToUpper();
    }
}

并发送至签名服务。然后我将收到的十六进制编码的签名值转换为字节

private static byte[] StringToByteArray(string hex)
{
    return Enumerable.Range(0, hex.Length).Where(x => x % 2 == 0).Select(x => Convert.ToByte(hex.Substring(x, 2), 16)).ToArray();
}

最后,创建签名

private void CreateSignature(string src, string dest, byte[] sig) 
{
    PdfReader reader = new PdfReader(src); // src is now prepared pdf
    FileStream os = new FileStream(dest, FileMode.Create);
    IExternalSignatureContainer external = new MyExternalSignatureContainer(sig);
    MakeSignature.SignDeferred(reader, "Signature1", os, external);

    reader.Close();
    os.Close();
}
private class MyExternalSignatureContainer : IExternalSignatureContainer
{
    protected byte[] sig;
    public MyExternalSignatureContainer(byte[] sig)
    {
        this.sig = sig;
    }
    public byte[] Sign(Stream s)
    {
        return sig;
    }
    public void ModifySigningDictionary(PdfDictionary signDic) { }
}

我究竟做错了什么?非常感谢您的帮助。谢谢!

编辑:当前状态

感谢 mkl 的帮助并遵循 Bruno 的延迟签名示例,我已经克服了无效签名消息。显然我没有从签名服务收到完整的链,而只是收到一个中间证书,这导致了无效的消息。不幸的是,签名仍然存在缺陷。

我这样构建链:

List<X509Certificate> certificateChain = new List<X509Certificate>
{
     signingCertificate,
     intermediateCertificate
}; 

在 MyExternalSignatureContainer 的 Sign 方法中,我现在构造并返回签名容器:

public byte[] Sign(Stream s)
{
    string hashAlgorithm = "SHA-256";
    PdfPKCS7 sgn = new PdfPKCS7(null, chain, hashAlgorithm, false);

    byte[] ocspResponse = Convert.FromBase64String("Base64 encoded DER representation of the OCSP response received from signing service");
    byte[] hash = DigestAlgorithms.Digest(s, hashAlgorithm);
    byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, ocspResponse, null, CryptoStandard.CMS);

    string messageDigest = Sha256_hash(sh);
    // messageDigest sent to signing service
    byte[] signatureAsByte = StringToByteArray("Hex encoded SignatureValue received from signing service");

    sgn.SetExternalDigest(signatureAsByte, null, "RSA");

    ITSAClient tsaClient = new MyITSAClient();

    return sgn.GetEncodedPKCS7(hash, tsaClient, ocspResponse, null, CryptoStandard.CMS); 
}

public class MyITSAClient : ITSAClient
{
    public int GetTokenSizeEstimate()
    {
        return 0;
    }

    public IDigest GetMessageDigest()
    {
        return new Sha256Digest();
    }

    public byte[] GetTimeStampToken(byte[] imprint)
    {
        string hashedImprint = HexEncode(imprint);
        // Hex encoded Imprint sent to signing service

        return Convert.FromBase64String("Base64 encoded DER representation of TimeStampToken received from signing service");
    }
}

仍然收到这些消息:

  1. “签名者的身份未知,因为它尚未包含在可信身份列表中,并且没有人或其父身份 证书是可信身份”
  2. “签名带有时间戳,但无法验证时间戳”

再次非常感谢您的进一步帮助!


“我究竟做错了什么?”

问题是,一方面,您开始使用PdfPKCS7实例

PdfPKCS7 sgn = new PdfPKCS7(null, chain, hashAlgorithm, false);

以及计算出的文档摘要hash检索签名属性

byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CMS);

送他们签字。

到目前为止,一切都很好。

但随后您忽略了开始构建的 CMS 容器,而是注入裸签名字节你从你的服务中得到进入 PDF.

这不起作用,因为您的签名字节不直接对文档进行签名,而是对这些签名属性进行签名(因此,间接对文档进行签名,因为文档哈希是签名属性之一)。因此,通过忽略正在构建的 CMS 容器,您删除了实际签名的数据......

此外,子过滤器ADBE_PKCS7_DETACHED您使用承诺嵌入的签名是完整的 CMS 签名容器,而不是一些裸露的签名字节,因此格式也是错误的。

该怎么做呢?

您必须将它们设置为外部摘要,而不是将您从服务中获得的裸签名字节按原样注入到 PDF 中。PdfPKCS7您最初开始构建签名容器的实例:

sgn.SetExternalDigest(sig, null, ENCRYPTION_ALGO);

(ENCRYPTION_ALGO必须是签名算法的加密部分,我假设在你的情况下"RSA".)

然后就可以检索生成的CMS签名容器:

byte[] encodedSig = sgn.GetEncodedPKCS7(hash, null, null, null, CryptoStandard.CMS);

现在这是要注入到文档中的签名容器MyExternalSignatureContainer:

IExternalSignatureContainer external = new MyExternalSignatureContainer(encodedSig);
MakeSignature.SignDeferred(reader, "Signature1", os, external);

遗留问题

更正您的代码后,Adobe Reader 仍会警告您的签名:

  1. “签名者的身份未知,因为它尚未包含在可信身份列表中,并且没有一个或其父证书是可信身份”

此警告是预期且正确的!

签名者身份未知因为您的签名服务仅使用演示证书,而不是用于生产用途的证书:

如您所见,证书是由“GlobalSign Non-Public HVCA Demo”颁发的,并且非公开演示发行人出于显而易见的原因一定不能被信任(除非您出于测试目的手动将它们添加到您的信任存储中)。

  1. “签名带有时间戳,但无法验证时间戳”

Adobe 不批准您的时间戳有两个原因:

一方面,就像上面一样,时间戳证书是非公开的演示证书(“DSS Non-Public Demo TSA Responder”)。因此,验证者没有理由相信你的时间戳。

但另一方面,您的时间戳代码中存在实际错误,您应用了哈希算法两次!在你的MyITSAClient你有的课

public byte[] GetTimeStampToken(byte[] imprint)
{
    string hashedImprint = Sha256_hash(imprint);
    // hashedImprint sent to signing service

    return Convert.FromBase64String("Base64 encoded DER representation of TimeStampToken received from signing service");
}

The imprint你的参数GetTimeStampToken实现已经经过哈希处理,因此您必须对这些字节进行十六进制编码并发送它们以进行时间戳处理。但你应用你的方法Sha256_hash首先对这个新的哈希值进行哈希处理,然后进行十六进制编码。

因此,而不是应用Sha256_hash仅十六进制编码imprint!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

itextsharp 使用签名哈希签名 pdf 的相关文章

  • 如何在 iOS 上反转使用 CoreGraphics 渲染的 pdf 上的文本颜色?

    我正在使用开源 PDF 查看库 VFR PDF Readerhttps github com vfr Reader https github com vfr Reader 我正在尝试实现 夜间模式 或黑色背景与白色文本 我可以将背景设置为我
  • 使用 /CCITTFaxDecode 过滤器从 PDF 中提取图像

    我有一个通过扫描软件生成的 pdf 文件 该 pdf 每页有 1 个 TIFF 图像 我想从每个页面中提取 TIFF 图像 我正在使用 iTextSharp 我已经成功找到了图像 并且可以从PdfReader GetStreamBytesR
  • R 在设置宽度和高度的 PDF 中缩放绘图元素

    尽管发送到 PDF 的 R 图可以在插图或页面布局软件中随意重新缩放 但科学期刊通常坚持提供的图具有特定的尺寸 是否可以直接在 R 中在给定 PDF 大小内缩放所有绘图元素的大小 require ggplot2 p lt qplot dat
  • 从 .docx 转换为 pdf 时,图像显示效果不佳

    我转换了 docx文件至 pdf文件中 文本转换得很好 但是图像 docx文件没有出现 而是表示为一些特殊字符 下面是我的代码 import com lowagie text Document import com lowagie text
  • 使用 ITextSharp 从内存流附加 PDF 文件时遇到问题

    我在附加内存中创建的 PDF 文件并将其附加到电子邮件模板时遇到问题 电子邮件没有任何问题 但没有附件 我不明白为什么会发生这种情况 这是该过程的完整代码 ExtendedEmailTemplate emailTemp new Extend
  • 使用 ApacheFOP 从 Java 中的 XML 生成 PDF

    我正在尝试从 Java 对象生成即时 PDF 报告 我找不到很多这方面的例子 所以我一直在关注这个例子 http svn apache org viewvc xmlgraphics fop trunk examples embedding
  • 如何从文本视图制作多页 PDF?

    我从 iPhone 应用程序生成了一个 PDF 文件 虽然大多数文档只有一页 但我希望能够检测文本是否超出 边距 如果是 则将其添加到下一页 我对此很陌生 所以不太确定如何做到这一点 下面是代码 有什么建议么 void drawBorder
  • 显示来自 weburl iphone sdk 的 pdf

    我正在开发一个项目 我想显示网站上的 pdf 我有 pdf 的 url 知道如何做到这一点 我还想创建网站上 pdf 的缩略图 您可以在您的设备中显示 pdf 文件 直接将 url 传递给 UIWebView UIWebView webVi
  • PDFBox - 无障碍 PDF - 如何检查 PDF 标签是否具有符合无障碍指南的属性

    需要检查 PDF 标签是否具有符合辅助功能指南的属性 例子 H1 验证 PDF 中是否存在 H1 图像 图形标签 验证图像 图形是否具有 Alt 文本 语言 验证语言属性是否已设置 以便屏幕阅读器能够正确阅读 对于西班牙语和英语文档 应更新
  • 打开 PDF 到书签/指定目标?

    我正在尝试使用 python 打开特定书签的 PDF 到目前为止 我可以在命令提示符中运行以下命令并得到我想要的 last是 PDF test pdf 中指定目的地的名称 C Program Files x86 Adobe Reader 1
  • JsPdf 库无法读取 PDF 中的阿拉伯语

    在 pdf 中显示阿拉伯值的代码不起作用 它向我展示了一些我无法理解的奇怪语言 var sm nature name nature1 ar 1 name nature2 ar 2 name nature3 ar 3 name nature4
  • JavaScript 文件中的快速低冲突非加密哈希

    我正在寻找一种用 JavaScript 实现的低冲突的快速哈希 它不需要是加密哈希 我基本上使用它作为查看给定文件是否已上传 或部分上传 到用户帐户的方式 以节省他们在大型 视频 文件上上传的时间 我正在使用新的 HTML5 文件 API
  • 如何使用 iTextSharp 从 PDF 中提取突出显示的文本?

    根据以下帖子 iTextSharp PDF 使用 C 读取突出显示的文本 突出显示注释 https stackoverflow com questions 23342500 itextsharp pdf reading highlighed
  • iText - 将内容添加到现有页面的底部

    我想向 PDF 文件的每一页添加一段文本 这个答案在SO https stackoverflow com questions 3335126 itext add content to existing pdf file工作正常 但是 文本被
  • 隐藏嵌入的 pdf 周围的工具栏?

    虽然我认为答案可能在这另一个问题 https stackoverflow com questions 770949 how to disable the default toolbar of pdf page关于pdf规范的回答 是否可以不
  • 使用 ITextsharp 将 Html 导出为 PDF

    我已经尝试了下面的代码 我也遇到了错误 我正在使用最新的 DLL String strSelectUserListBuilder h1 My First Heading h1 p My first paragraph p String ht
  • 从图像创建 PDF 时设置文档名称

    我使用以下代码从 jpg 图像创建 pdf im new Imagick im gt readImage image jpg im gt setImageFormat pdf im gt writeImage images pdf imag
  • 迭代哈希数组

    我编写了下面的例程 迭代哈希值 0 7 并打印出每个哈希值中特定键的值 我需要获取每个哈希中 b4 的值 我想取消 0 7 当存在不同数量的哈希值时使用更智能的东西 例如 有时只有 2 个 也可能有 160 个 my out decode
  • 使用 PHP/linux 将文件合并为单个 PDF

    我正在研究如何将多个 PDF 合并为一个 PDF 我正在寻找一个图书馆可靠且坚固尽可能 最好有一个库可以保留书签 鬼脚本 http pages cs wisc edu ghost 可以在保存书签的位置进行连接 但我遇到了麻烦 在一种情况下它
  • .NET 中是否有内置函数可以对密码进行哈希处理?

    我看到这个问题加密 散列数据库中的纯文本密码 https stackoverflow com questions 287517 encrypting hashing plain text passwords in database 我知道我

随机推荐

  • .NET DDD 示例 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 您使用哪些 Python 重构工具? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有很多类想要重命名 其中一些名称很小 并且该名称在其他类名称中重复使用 我不希望更改该名称 其中大部分
  • GitHub Action:如何在 docker 容器内运行命令

    今天刚开始学习CI CD 今天不知道 docker 之前是什么 我能够通过我的 Unity 项目在 CircleCI 上运行 CD 所有运行命令都发生在 docker 容器内 version 2 1 executors unity dock
  • 修复 HTML 视频元素的黑色矩形

    我正在实施 WebRTC 视频聊天 我想实现以下案例 默认情况下 视频元素通过 CSS 具有背景图像 如果没有视频输入 则用户会看到他 或对话者 的头像 No video expected result No video actual re
  • 如何设置 Angular Timepicker 的最短时间和最长时间?

    有没有办法为 Angular 的引导时间选择器设置最短时间和最长时间 使用 Angular 的 Datepicker 设置支持最小和最大日期 我想知道 Timepicker 是否允许类似的功能 查看中的设置Timepicker 的 Angu
  • 如何在 EF Code First 中创建/更新 LastModified 字段

    我想添加一个列 用于在将记录保存到磁盘时存储当前的日期时间 实现这一目标的最佳方法是什么 我知道这不是一个非常复杂的问题 但我想知道 EF 是否有任何最佳实践或任何功能可以简化任务 例如 有没有什么方法可以将该字段的逻辑包含在表类中 以便在
  • Java EE DAO / DTO(数据传输对象)设计模式

    目前 我正在为我的工作项目使用 struts2 框架 在设计我的 DAO 类时 我心中有一个改进设计模式的问题 在我的搜索功能上 我有3种搜索 使用一个参数和另一个参数进行搜索 使用多个参数进行搜索 不带参数搜索 我的问题是 做DAO方法最
  • 如何查询 Sphinx 精确匹配的短语?

    Sphinx 似乎正在逐字搜索文档 我不知道如何在文档中搜索确切的短语 我试过SPH MATCH ALL SPH MATCH PHRASE但所有人都逐字搜索文档 我在我的 PHP 应用程序中使用它 如何查询 Sphinx 以匹配精确的字符串
  • 如何制作“空”RSS 提要

    我对 RSS 提要不太熟悉 但我可以使用 PHP 动态创建提要 而且效果很好 我的问题是 有时提要没有任何项目 我将提要项目的期限限制为 60 天 有时在这段时间内什么也没有发生 我期望发生的是我根本不会有任何
  • 如何在同一台服务器上托管两个公开端口 80 的 Docker 容器

    我有 2 个网站 客户端需要在端口 80 上连接到 每个网站都在自己的容器中运行 我想在同一台 Docker 主机上运行这两个容器 据我所知 80端口只能在主机上暴露一次 存在哪些具有最小开销 管理的解决方案 允许我在同一主机上简单地运行两
  • 从实体框架类获取默认sql值

    我使用的是 T4 模板 对中提出的模板稍加修改this https stackoverflow com a 15936878 1641172答案是从我的 EF POCO 生成打字稿接口 EF Core POCO 首先生成数据库 并且某些数据
  • React TestUtils,如何模拟文档mouseMove?

    我想用TestUtils Simulate mouseMove on the document 我有一个组件Dragger这增加了一个mouseMove事件侦听器document 这是一个不完整的版本 Dragger js use stri
  • 从 readr::read_csv 中读取的数据中删除属性

    readr read csv添加编辑数据时不会更新的属性 例如 library tidyverse df lt read csv A B C na 1 x nb 1 y nc 1 z Remove columns with only one
  • LiveCharts WPF 中单独着色的数据点

    我正在使用 Live Charts WPF 来绘制一些图表 为了使每个栏具有不同的颜色 我添加了多个系列 但它没有显示x axis所有系列的标签 为什么 senderChart Series new SeriesCollection int
  • 如何在 Java 中将布尔数组转换为二进制数组,反之亦然?

    在 Java 中将布尔数组输出到文件 以及从文件输入 的最有效方法是什么 我打算使用一个字符串 每个字符要么是 t 要么是 f 然后我想 为什么不减少八倍的空间呢 NOTE 我实际上不知道哪个答案是更好的方法 我只是选择了彼得的 因为我理解
  • 使用 Clips 专家系统中的 Python 函数

    使用 PyClips 我尝试在 Clips 中构建规则 从 Python 解释器动态检索数据 为此 我注册了一个外部函数 如下所示手册 http pyclips sourceforge net manual pyclips overview
  • 在 Razor 视图中渲染 Telerik MVC Grid 时出现问题

    我在 内容 页面中有以下标记 如果没有 Render 调用 则不会呈现任何内容 而使用 Render 调用时 网格将呈现为整个页面中的第一个元素 而不是在我的视图定义的 内容 部分内 using Telerik Web Mvc UI mod
  • 从 BroadcastReceiver 调用活动方法。是否可以?

    我陷入了开发应用程序的困境 因为我需要在触发 BroadcastReceiver 时调用我的活动的方法 我希望 BroadcastReceiver 能够检测到网络连接何时断开并调用我已经编写的活动方法 我一直在搜索 发现以前有更多人问过这个
  • Android 作为 SIP 转 GSM 网关

    很快我就可以使用 SIP 转 GSM 网关 因为我需要从德国向捷克共和国的手机拨打电话 因此 我考虑实施一个 现在 问题是 这样的解决方案是否已经存在 价格合理 是否可以使用可用的 Android API SDK 或 NDK 将 语音 流重
  • itextsharp 使用签名哈希签名 pdf

    我正在尝试通过签名服务签署 pdf 此服务需要发送十六进制编码的 SHA256 摘要 作为回报 我收到十六进制编码的签名值 除此之外 我还收到签名证书 中间证书 OCSP 响应和 TimeStampToken 但是 我已经在尝试使用签名值对