自应用签名后文档已被更改或损坏 itext 5.5.11

2024-03-25

基本上,我收到错误“自应用签名以来文档已被更改或损坏”,我按照 itext 网站的示例并根据我的情况进行了调整。

  • 准备好要签名的文档,添加append模式,因为可以 已经签署的文件
  • 调用 Web 服务来签署哈希值
  • 将签名哈希添加到准备好的文档中

我没有想法了,希望能得到一些帮助 这是我的代码片段:

    public static final String src = "DynamicClient\sample.pdf";
    public static final String temp= "DynamicClient\sampleTEMP.pdf";
    public static final String dest= "DynamicClient\sampleFINAL.pdf";

    public static void emptySignatureSVC(String src, String dest, String fieldname, Certificate[] chain) throws IOException, DocumentException, GeneralSecurityException {
            PdfReader reader = new PdfReader(src);
            reader.setAppendable(true);
            FileOutputStream os = new FileOutputStream(dest);
            PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0',null,true);
            PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
            appearance.setVisibleSignature(new Rectangle(0, 0, 0, 0), 1, fieldname);
            appearance.setCertificate(chain[0]);
            ExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ETSI_CADES_DETACHED);
            MakeSignature.signExternalContainer(appearance, external, 8192);
            reader.close();
            
        }

    public static void createSignatureSVC(String src, String dest, String fieldname, byte[] sign, Certificate[] chain) throws IOException, DocumentException, GeneralSecurityException {
            
            PdfReader reader = new PdfReader(src);
            FileOutputStream os = new FileOutputStream(dest);
            ExternalSignatureContainer external = new MyExternalSignatureContainer(sign, chain);
            MakeSignature.signDeferred(reader, fieldname, os, external);
        }


    public static void main(String[] args) throws Exception {

                Certificate[] chain = signWS.getChain();//External WS to get chain
                emptySignatureSVC(src, temp, "signature", chain);               
                InputStream is = new FileInputStream(new File(temp));
                PdfPKCS7 sgn = new PdfPKCS7(null, chain, "SHA256", null, digest, false);
                byte[] hash = DigestAlgorithms.digest(is, digest.getMessageDigest("SHA256"));
                byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CADES);
                
                byte[] extSignature = signWS(sh);//External WS to sign
                sgn.setExternalDigest(extSignature, null, "RSA");
    
                createSignatureSVC(temp, dest, "signature", sgn.getEncodedPKCS7(hash,null, null, null, CryptoStandard.CADES), chain);
}

这是文件:原来的 https://drive.google.com/file/d/1GVP77ZA7ysCRInf1ddKBmJjOhNZPwPjc/view?usp=sharing 签了一份 https://drive.google.com/file/d/1NvY2LukwL2WoA3nkayWxAOoB89hlndoK/view?usp=sharing

EDIT:忘记添加我使用的容器:

class MyExternalSignatureContainer implements ExternalSignatureContainer {
    protected byte[] sig;
    protected Certificate[] chain;
    public MyExternalSignatureContainer(byte[] sig,Certificate[] chain) {
        this.sig = sig;
        this.chain=chain;
    }
    public byte[] sign(InputStream is)throws GeneralSecurityException  {
        
        return sig;
        
    }

    @Override
    public void modifySigningDictionary(PdfDictionary signDic) {
        // TODO Auto-generated method stub
        
    }
}

您的代码中有两个问题:

  • 你散列了错误的数据并且
  • 你签名错误。

散列错误的数据

您正在对整个准备好的 PDF 进行哈希处理,如下所示:

InputStream is = new FileInputStream(new File(temp));
PdfPKCS7 sgn = new PdfPKCS7(null, chain, "SHA256", null, digest, false);
byte[] hash = DigestAlgorithms.digest(is, digest.getMessageDigest("SHA256"));

这是不正确的。

签名的 PDF 本质上具有这种结构(阅读here https://security.stackexchange.com/a/35131/16096更多细节):

(顺便说一句,该草图并非 100% 正确,因为签名值周围的尖括号分隔符 '' 也不得进行哈希处理。)

您准备好的 PDF 位于temp具有相同的结构,只是“签名值”还不是实际的签名值,而是 8192 十六进制编码的零字节的占位符(8192 因为这是您在MakeSignature.signExternalContainer).

不过,正如您在草图中看到的那样,签名值(或者在您的情况下为占位符)不得进行哈希处理以进行签名。

您可以使用返回的数据计算哈希值PdfSignatureAppearance.getRangeStream之后MakeSignature.signExternalContainer正如 @LkbhaiLr 所提议的他的回答 https://stackoverflow.com/a/66776866/1729265.

或者,您可以使用(而不是ExternalBlankSignatureContainer) 一个习俗ExternalSignatureContainer实施其中sign方法只是对其进行散列InputStream参数并提供该哈希值。

我更喜欢后一种方法,但前一种方法也被广泛使用。

签名错误

您可以像这样检索裸签名值:

byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CADES);
byte[] extSignature = signWS(sh);//External WS to sign

IE。您将属性结构按原样转发到签名服务,并期望它为其创建正确的签名值。

检查你的签名示例文件 https://drive.google.com/file/d/1NvY2LukwL2WoA3nkayWxAOoB89hlndoK/view?usp=sharing但是,很明显,该签名服务没有达到您的期望:而不是signing使用 SHA256withRSA,它只是encrypts使用 RSA 和 PKCS#1 填充。因此,它希望您为您完成一半的签名工作,即使用 SHA256 进行哈希处理并构建一个DigestInfo结构。

因此,在调用之前signWS您必须对返回的属性结构进行哈希处理sgn.getAuthenticatedAttributeBytes然后将生成的哈希值包装在DigestInfo object.

当您在其他地方计算哈希时,这对您来说不应该是问题。并将哈希包装在DigestInfo RFC 8017 第 9.2 节注释 1 https://www.rfc-editor.org/rfc/rfc8017#section-9.2提供了一条捷径:

对于附录 B.1 中提到的九个哈希函数,其 DER 编码 TDigestInfo值等于以下内容:

...
SHA-256: (0x)30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || H.
...

IE。你只需要用字节序列作为哈希前缀30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20.

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

自应用签名后文档已被更改或损坏 itext 5.5.11 的相关文章

  • 在 Java 中连接和使用 Cassandra

    我已经阅读了一些关于 Cassandra 是什么以及它可以做什么的教程 但我的问题是如何在 Java 中与 Cassandra 交互 教程会很好 如果可能的话 有人可以告诉我是否应该使用 Thrift 还是 Hector 哪一个更好以及为什
  • Java EE:如何获取我的应用程序的 URL?

    在 Java EE 中 如何动态检索应用程序的完整 URL 例如 如果 URL 是 localhost 8080 myapplication 我想要一个可以简单地将其作为字符串或其他形式返回给我的方法 我正在运行 GlassFish 作为应
  • 如何在 Play java 中创建数据库线程池并使用该池进行数据库查询

    我目前正在使用 play java 并使用默认线程池进行数据库查询 但了解使用数据库线程池进行数据库查询可以使我的系统更加高效 目前我的代码是 import play libs Akka import scala concurrent Ex
  • Java - 将节点添加到列表的末尾?

    这是我所拥有的 public class Node Object data Node next Node Object data Node next this data data this next next public Object g
  • Java JDBC:更改表

    我希望对此表进行以下修改 添加 状态列 varchar 20 日期列 时间戳 我不确定该怎么做 String createTable Create table aircraft aircraftNumber int airLineCompa
  • 制作一个交互式Windows服务

    我希望我的 Java 应用程序成为交互式 Windows 服务 用户登录时具有 GUI 的 Windows 服务 我搜索了这个 我发现这样做的方法是有两个程序 第一个是服务 第二个是 GUI 程序并使它们进行通信 服务将从 GUI 程序获取
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • 多个 Maven 配置文件激活多个 Spring 配置文件

    我想在 Maven 中构建一个环境 在其中我想根据哪些 Maven 配置文件处于活动状态来累积激活多个 spring 配置文件 目前我的 pom xml 的相关部分如下所示
  • 控制Android的前置LED灯

    我试图在用户按下某个按钮时在前面的 LED 上实现 1 秒红色闪烁 但我很难找到有关如何访问和使用前置 LED 的文档 教程甚至代码示例 我的意思是位于 自拍 相机和触摸屏附近的 LED 我已经看到了使用手电筒和相机类 已弃用 的示例 但我
  • 我可以使用 HSQLDB 进行 junit 测试克隆 mySQL 数据库吗

    我正在开发一个 spring webflow 项目 我想我可以使用 HSQLDB 而不是 mysql 进行 junit 测试吗 如何将我的 mysql 数据库克隆到 HSQLDB 如果您使用 spring 3 1 或更高版本 您可以使用 s
  • 斯坦福 NLP - 处理文件列表时 OpenIE 内存不足

    我正在尝试使用斯坦福 CoreNLP 中的 OpenIE 工具从多个文件中提取信息 当多个文件 而不是一个 传递到输入时 它会给出内存不足错误 All files have been queued awaiting termination
  • 使用Caliper时如何指定命令行?

    我发现 Google 的微型基准测试项目 Caliper 非常有趣 但文档仍然 除了一些示例 完全不存在 我有两种不同的情况 需要影响 JVM Caliper 启动的命令行 我需要设置一些固定 最好在几个固定值之间交替 D 参数 我需要指定
  • getResourceAsStream() 可以找到 jar 文件之外的文件吗?

    我正在开发一个应用程序 该应用程序使用一个加载配置文件的库 InputStream in getClass getResourceAsStream resource 然后我的应用程序打包在一个 jar文件 如果resource是在里面 ja
  • 在 Mac 上正确运行基于 SWT 的跨平台 jar

    我一直致力于一个基于 SWT 的项目 该项目旨在部署为 Java Web Start 从而可以在多个平台上使用 到目前为止 我已经成功解决了由于 SWT 依赖的系统特定库而出现的导出问题 请参阅相关thread https stackove
  • Eclipse Java 远程调试器通过 VPN 速度极慢

    我有时被迫离开办公室工作 这意味着我需要通过 VPN 进入我的实验室 我注意到在这种情况下使用 Eclipse 进行远程调试速度非常慢 速度慢到调试器需要 5 7 分钟才能连接到远程 jvm 连接后 每次单步执行断点 行可能需要 20 30
  • 如何在桌面浏览器上使用 webdriver 移动网络

    我正在使用 selenium webdriver 进行 AUT 被测应用程序 的功能测试自动化 AUT 是响应式网络 我几乎完成了桌面浏览器的不同测试用例 现在 相同的测试用例也适用于移动浏览器 因为可以从移动浏览器访问 AUT 由于它是响
  • Firebase 添加新节点

    如何将这些节点放入用户节点中 并创建另一个节点来存储帖子 我的数据库参考 databaseReference child user getUid setValue userInformations 您需要使用以下代码 databaseRef
  • 捕获的图像分辨率太大

    我在做什么 我允许用户捕获图像 将其存储到 SD 卡中并上传到服务器 但捕获图像的分辨率为宽度 4608 像素和高度 2592 像素 现在我想要什么 如何在不影响质量的情况下获得小分辨率图像 例如我可以获取或设置捕获的图像分辨率为原始图像分
  • 使用 JMF 创建 RTP 流时出现问题

    我正处于一个项目的早期阶段 需要使用 RTP 广播DataStream创建自MediaLocation 我正在遵循一些示例代码 该代码目前在rptManager initalize localAddress 出现错误 无法打开本地数据端口
  • 使用 xpath 和 vtd-xml 以字符串形式获取元素的子节点和文本

    这是我的 XML 的一部分

随机推荐

  • Bud1%@@@@E%DSDB`@@@是什么?

    我为客户制作了一个小应用程序 该应用程序扫描files包含几个文本文件的目录 然后它将每个文件读入一个字符串 每个文件都有标题和文章文本 这两部分用管道字符分隔 如下所示 article title article text 该脚本显示用于
  • 我自己的 Python OCR 程序

    我还是一个初学者 但我想写一个字符识别程序 这个程序还没有准备好 而且我编辑了很多 所以评论可能不完全一致 我将使用 8 个连通性来标记连通分量 from PIL import Image import numpy as np im Ima
  • 文件夹浏览器对话框的问题

    如果对话框中单击Make newfolder 则开始编辑刚刚创建的文件夹的名称并单击OK OKdialogrezalt返回 但在属性中SelectedPath他将文件夹命名为New文件夹 然后就有默认的名称 发生这种情况是因为当我们创建时
  • 为什么对 Deref::deref 结果断言会因类型不匹配而失败?

    以下是Deref示例来自Rust 编程语言 https doc rust lang org book first edition deref coercions html除了我添加了另一个断言 为什么assert eq与deref也相等 a
  • 如何在nodeJS项目中使用Jest全局Setup和Teardown?

    我使用 jest 将测试添加到我的 Node js 项目中 但对于每个测试套件 都有一个 beforeAll 方法用于创建新的测试服务器并连接到 mongo 数据库 还有一个 afterAll 方法用于关闭测试服务器和数据库 我想对所有测试
  • AWS DocumentDB 与 Robo 3T (Robomongo)

    我想将 Mac 笔记本电脑上的 Robo 3T 以前称为 robomongo 与 AWS 的 DocumentDB 连接 我遵循了大量教程 但找不到任何特定于 DocumentDB 的教程 在测试阶段 它通过了步骤 1 连接到我的 EC2
  • INSTALL_FAILED_OLDER_SDK 的 minSdkVersion 低于设备 API 版本

    在全新安装最新的 AndroidStudio 时 运行新项目模板 最小 SDK 选择为 15 ICS 尝试在运行 API 19 的 Nexus 5 上运行 我收到 INSTALL FAILED OLDER SDK 错误并显示以下输出 我没有
  • 类型不匹配:无法从连接转换为连接

    我想要 JDBC 连接到 MS Access 但 Class forName sun jdbc odbc JdbcOdbcDriver Connection con DriverManager getConnection jdbc odbc
  • 如何在 Room 中插入具有一对多关系的实体

    我正在使用 Room 构建一个数据库 但我不知道如何将具有关系 在我的例子中是一对多 的新元素插入到数据库中 没有解决方案曾经讨论过插入 他们只讨论了查询数据 这是 DAO Dao abstract class ShoppingListsD
  • 在WPF中,为什么MouseLeave触发而不是MouseDown?

    这是我的代码
  • 这个特权准则有什么问题吗?

    如何检查 检查 php代码或页面中的权限 我使用爆炸和 in array 用户登录并进入 检查 页面后 代码必须检查用户的权限是否具有 dataDisplay 权限 但 检查 页面中的代码不会执行此操作 我的 检查 页面代码有什么问题 这是
  • Windows10 上使用 VirtualBox 的 Vagrant:在您的 PATH 中找不到“Rsync”

    我在 Windows 7 系统上使用 Vagrant 一段时间了 现在我有一台装有 Windows 10 的新 PC 我安装了 Oracle Virtual Box 和 Vagrant 并尝试使用命令 vagrant up 启动计算机 Va
  • r 中的 ifelse 匹配向量

    我有一个如下所示的数据框 gt df lt data frame A c NA 1 2 3 4 B c NA 5 2 6 4 C c NA NA 2 NA NA gt df A B C 1 NA NA NA 2 1 5 NA 3 2 2 2
  • C/C++ 的多线程内存分配器

    我目前有大量的多线程服务器应用程序 并且我正在寻找一个好的多线程内存分配器 到目前为止 我在以下两点之间左右为难 太阳乌梅 谷歌的tcmalloc 英特尔的线程构建块分配器 埃默里 伯杰的宝藏 据我所知 hoard 可能是最快的 但我在今天
  • 为什么冒泡排序最好情况的时间复杂度是O(n)

    我按照书中使用的方法推导了冒泡排序在最佳情况下的时间复杂度算法2 2 但结果是 O n 2 以下是我的推导 希望大家帮我找出哪里错了 public void bubbleSort int arr for int i 0 len arr le
  • 让 Kotlin 序列化器与 Retrofit 配合使用

    我无法让 Kotlin Serializer 与 Retrofit 一起使用 我在用com jakewharton retrofit retrofit2 kotlinx serialization converter 0 5 0与 Retr
  • 如何用networkx绘制社区

    如何使用 python networkx 绘制其社区的图表 如下图所示 图片网址 https data graphstream project org talks CSSS2012 media Community Structure2 jp
  • Pentaho Data Integration(最新版本)-未检测到 MySQL 驱动程序

    我是这个工具的新手 我正在尝试创建与数据库的 MySQL 连接 但是当我按下 测试 按钮时 它会显示以下消息 Error connecting to database MySQL configuracionesEF org pentaho
  • 将 UITableView 作为容器视图嵌入到 UIViewController 中

    我想添加一个文本字段和发送按钮 该按钮粘贴在 uitableview 的底部 类似于聊天应用程序 我遇到过关于将 UITableView 作为容器视图嵌入到 UIViewController 中的评论 然而 他们似乎缺乏如何实现这一目标的例
  • 自应用签名后文档已被更改或损坏 itext 5.5.11

    基本上 我收到错误 自应用签名以来文档已被更改或损坏 我按照 itext 网站的示例并根据我的情况进行了调整 准备好要签名的文档 添加append模式 因为可以 已经签署的文件 调用 Web 服务来签署哈希值 将签名哈希添加到准备好的文档中