自应用签名后文档已被更改或损坏 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:扩展类并实现具有相同方法的接口

    可能无法完成以下操作 我收到编译错误 继承的方法 A doSomthing int 无法隐藏 B 中的公共抽象方法 public class A int doSomthing int x return x public interface
  • TreeMap 删除所有大于某个键的键

    在项目中 我需要删除键值大于某个键的所有对象 键类型为Date 如果重要的话 据我所知TreeMapJava中实现的是红黑树 它是一种二叉搜索树 所以我应该得到O n 删除子树时 但除了制作尾部视图并一一删除之外 我找不到任何方法可以做到这
  • Java Logger 未记录到 Netbeans 中的输出

    我正在 Netbeans 中使用 Maven 启动一个 Java 项目 我编写了一些代码来使用 Logger 类进行日志记录 但是 日志记录似乎不起作用 在程序开始时 我运行 Logger getLogger ProjectMainClas
  • 如何在 JavaFX 中连接可观察列表?

    我所说的串联是指获得一个新列表 该列表侦听所有串联部分的更改 方法的目的是什么FXCollections concat ObservableList
  • 为什么即使我的哈希码值相同,“==”也会返回 false

    我写了一个像这样的课程 public class HashCodeImpl public int hashCode return 1 public static void main String args TODO Auto generat
  • 什么是抽象类? [复制]

    这个问题在这里已经有答案了 当我了解抽象类时 我说 WT H 问题 创建一个无法实例化的类有什么意义呢 为什么有人想要这样的课程 什么情况下需要抽象类 如果你明白我的意思 最常见的是用作基类或接口 某些语言有单独的interface构建 有
  • 如何在 Java 中向时间戳添加/减去时区偏移量?

    我正在使用 JDK 8 并且玩过ZonedDateTime and Timestamp很多 但我仍然无法解决我面临的问题 假设我得到了格式化的Timestamp在格林威治标准时间 UTC 我的服务器位于某处 假设它设置为Asia Calcu
  • 从 MATLAB 调用 Java?

    我想要Matlab程序调用java文件 最好有一个例子 需要考虑三种情况 Java 内置库 也就是说 任何描述的here http docs oracle com javase 6 docs api 这些项目可以直接调用 例如 map ja
  • java inputstream 打印控制台内容

    sock new Socket www google com 80 out new BufferedOutputStream sock getOutputStream in new BufferedInputStream sock getI
  • 如何在 Spring 中使 @PropertyResource 优先于任何其他 application.properties ?

    我正在尝试在类路径之外添加外部配置属性资源 它应该覆盖任何现有的属性 但以下方法不起作用 SpringBootApplication PropertySource d app properties public class MyClass
  • 提高 PostgreSQL 1 亿数据左连接查询性能

    我在用Postgresql 9 2 version Windows 7 64 bit RAM 6GB 这是一个Java企业项目 我必须在我的页面中显示订单相关信息 有三个表通过左连接连接在一起 Tables TV HD 389772 行 T
  • 如何在JPanel中设置背景图片

    你好 我使用 JPanel 作为我的框架的容器 然后我真的想在我的面板中使用背景图片 我真的需要帮助 这是我到目前为止的代码 这是更新 请检查这里是我的代码 import java awt import javax swing import
  • 将 JavaFX FXML 对象分组在一起

    非常具有描述性和信息性的答案将从我这里获得价值 50 声望的赏金 我正在 JavaFX 中开发一个应用程序 对于视图 我使用 FXML
  • 使用 HtmlUnit 定位弹出窗口

    我正在构建一个登录网站并抓取一些数据的程序 登录表单是一个弹出窗口 所以我需要访问这个www betexplorer com网站 在页面的右上角有一个登录链接 写着 登录 我单击该链接 然后出现登录弹出表单 我能够找到顶部的登录链接 但找不
  • 手动设置Android Studio的JDK路径

    如何为 Android Studio 使用自定义 JDK 路径 我不想弄乱 PATH 因为我没有管理员权限 是否有某个配置设置文件允许我进行设置 如果您查看项目设置 您可以从那里访问 jdk 在标准 Windows 键盘映射上 您可以在项目
  • 在java中以原子方式获取多个锁

    我有以下代码 注意 为了可读性 我尽可能简化了代码 如果我忘记了任何关键部分 请告诉我 public class User private Relations relations public User relations new Rela
  • Java 正则表达式中的逻辑 AND

    是否可以在 Java Regex 中实现逻辑 AND 如果答案是肯定的 那么如何实现呢 正则表达式中的逻辑 AND 由一系列堆叠的先行断言组成 例如 foo bar glarch 将匹配包含所有三个 foo bar 和 glarch 的任何
  • Android View Canvas onDraw 未执行

    我目前正在开发一个自定义视图 它在画布上绘制一些图块 这些图块是从多个文件加载的 并将在需要时加载 它们将由 AsyncTask 加载 如果它们已经加载 它们只会被绘制在画布上 这工作正常 如果加载了这些图片 AsyncTask 就会触发v
  • MiniDFSCluster UnsatisfiedLinkError org.apache.hadoop.io.nativeio.NativeIO$Windows.access0

    做时 new MiniDFSCluster Builder config build 我得到这个异常 java lang UnsatisfiedLinkError org apache hadoop io nativeio NativeIO
  • Java 11 - 将 Spring @PostConstruct 替换为 afterPropertiesSet 或使用 initMethod

    我正在使用 spring 应用程序 有时会使用 PostConstruct用于代码和测试中的设置 看来注释将被排除在外Java 11 https www baeldung com spring postconstruct predestro

随机推荐

  • 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 服务来签署哈希值 将签名哈希添加到准备好的文档中