- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有这样的场景。
我有一个生成 PDF 的应用程序,需要对其进行签名。
我们没有用于签署文档的证书,因为它们位于 HSM 中,而我们使用证书的唯一方法是使用 Web 服务。
此网络服务提供两个选项,发送 PDF 文档,并返回签名的 pdf,或发送将签名的哈希值。
第一个选项不可行,因为 PDF 签名时没有时间戳(这是一个非常重要的先决条件),因此选择第二个选项。
这是我们的代码,首先,我们获取签名外观,并计算哈希值:
PdfReader reader = new PdfReader(Base64.decode(pdfB64));
reader.setAppendable(true);
baos = new ByteArrayOutputStream();
PdfStamper stamper = PdfStamper.createSignature(reader, baos, '\0', null, true);
appearance = stamper.getSignatureAppearance();
appearance.setCrypto(null, chain, null, PdfSignatureAppearance.SELF_SIGNED);
appearance.setVisibleSignature("Representant");
cal = Calendar.getInstance();
PdfDictionary dic = new PdfDictionary();
dic.put(PdfName.TYPE, PdfName.SIG);
dic.put(PdfName.FILTER, PdfName.ADOBE_PPKLITE);
dic.put(PdfName.SUBFILTER, new PdfName("adbe.pkcs7.detached"));
dic.put(PdfName.M, new PdfDate(cal));
appearance.setCryptoDictionary(dic);
HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
exc.put(PdfName.CONTENTS, Integer.valueOf(reservedSpace.intValue() * 2 + 2));
appearance.setCertificationLevel(1);
appearance.preClose(exc);
AbstractChecksum checksum = JacksumAPI.getChecksumInstance("sha1");
checksum.reset();
checksum.update(Utils.streamToByteArray(appearance.getRangeStream()));
hash = checksum.getByteArray();
此时,我们就得到了文档的哈希码。然后我们将哈希发送到网络服务,并获得签名的哈希代码。
最后,我们将签名的哈希值放入 PDF:
byte[] paddedSig = new byte[reservedSpace.intValue()];
System.arraycopy(signedHash, 0, paddedSig, 0, signedHash.length);
PdfDictionary dic = new PdfDictionary();
dic.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true));
appearance.close(dic);
byte[] pdf = baos.toByteArray();
此时,我们得到了一个已签名的 PDF,但签名无效。 Adobe 表示“文档自签名以来已被更改或损坏”。
我认为我们在这个过程中犯了一些错误,而且我们不知道到底会发生什么。
我们感谢您提供这方面的帮助,或者提供替代方法。
谢谢。
<小时/>已编辑
根据mkl的建议,我遵循了本书的4.3.3部分Digital Signatures for PDF documents ,我的代码如下:
第一部分,当我们计算哈希时:
PdfReader reader = new PdfReader(Base64.decode(pdfB64));
reader.setAppendable(true);
baos = new ByteArrayOutputStream();
PdfStamper stamper = PdfStamper.createSignature(reader, baos, '\0');
appearance = stamper.getSignatureAppearance();
appearance.setReason("Test");
appearance.setLocation("A casa de la caputeta");
appearance.setVisibleSignature("TMAQ-TSR[0].Pagina1[0].DadesSignatura[0].Representant[0]");
appearance.setCertificate(chain[0]);
PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
dic.setReason(appearance.getReason());
dic.setLocation(appearance.getLocation());
dic.setContact(appearance.getContact());
dic.setDate(new PdfDate(appearance.getSignDate()));
appearance.setCryptoDictionary(dic);
HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
exc.put(PdfName.CONTENTS, new Integer(reservedSpace.intValue() * 2 + 2));
appearance.preClose(exc);
ExternalDigest externalDigest = new ExternalDigest()
{
public MessageDigest getMessageDigest(String hashAlgorithm) throws GeneralSecurityException
{
return DigestAlgorithms.getMessageDigest(hashAlgorithm, null);
}
};
sgn = new PdfPKCS7(null, chain, "SHA256", null, externalDigest, false);
InputStream data = appearance.getRangeStream();
hash = DigestAlgorithms.digest(data, externalDigest.getMessageDigest("SHA256"));
cal = Calendar.getInstance();
byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, cal, null, null, CryptoStandard.CMS);
sh = MessageDigest.getInstance("SHA256", "BC").digest(sh);
hashPdf = new String(Base64.encode(sh));
在第二部分中,我们获得签名的哈希值,并将其放入 PDF 中:
sgn.setExternalDigest(Base64.decode(hashSignat), null, "RSA");
byte[] encodedSign = sgn.getEncodedPKCS7(hash, cal, null, null, null, CryptoStandard.CMS);
byte[] paddedSig = new byte[reservedSpace.intValue()];
System.arraycopy(encodedSign, 0, paddedSig, 0, encodedSign.length);
PdfDictionary dic2 = new PdfDictionary();
dic2.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true));
appearance.close(dic2);
byte[] pdf = baos.toByteArray();
现在,Adobe 提出内部加密库错误。错误代码:0x2726,当我们尝试验证签名时。
最佳答案
In this point, we have the hash code of the document. Then we send the hash to the webservice, and we get the signed hash code.
Finally, we put the signed hash to the PDF:
如果网络服务仅返回签名哈希,则您的 PDF 签名不正确:您将签名 SubFilter 设置为 adbe.pkcs7.detached。这意味着签名内容必须包含完整的 PKCS#7 签名容器,而不仅仅是签名的哈希值。
您可能想要下载Digital Signatures for PDF documents ,Bruno Lowagie(iText 软件)的白皮书,介绍使用 iText 创建和验证数字 PDF 签名。它特别包含“4.3 用于签名的客户端/服务器架构”部分,其中应包含您的用例。
根据上述解释,OP 开始使用上述白皮书第 4.3.3 节中的代码,该代码旨在使用外部生成的签名哈希进行签名。由于这也导致了 Adobe Reader 不满意的签名文档,因此他提供了使用此新代码创建的示例文档。
对样本的分析表明,嵌入在文档中的 CMS 签名容器包含另一个 CMS 签名容器,其中应该包含签名属性的签名字节(签名哈希):
2417 13: SEQUENCE {
2419 9: OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
2430 0: NULL
: }
2432 5387: OCTET STRING, encapsulates {
2436 NDEF: SEQUENCE {
2438 9: OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)
2449 NDEF: [0] {
2451 NDEF: SEQUENCE {
(签名算法后面的 OCTET STRING 应包含签名字节,并且不能嵌入另一个 SignedData 结构。)
这表明 Web 服务确实已经返回了一个成熟的 CMS 容器。
对于这种情况,原始代码看起来相当不错。该问题可能是由于使用了错误的哈希算法(原始代码使用 SHA1 进行哈希处理)等细节造成的。
嵌入在 CMS 容器中的 Web 服务的 CMS 签名容器是由 iText 从 OP 提供的第一个示例生成的,提示可能存在问题:查看嵌入的外部结构大小上方的 ASN.1 转储CMS 容器通常是 NDEF
。
这表明这些外部结构是使用不太严格的 BER(基本编码规则)创建的,而不是更严格的 DER(区分编码规则),因为在 DER 中禁止使用 BER 选项来启动结构而不说明其大小。
PDF 规范引用的 CMS 规范 (RFC 3852) 确实允许对容器的外部结构进行任何 BER 编码,而 PDF 规范则要求:
the value of Contents shall be a DER-encoded PKCS#7 binary dataobject containing the signature. The PKCS#7 object shall conform to RFC3852 Cryptographic Message Syntax.
因此,严格来说,嵌入 PDF 中的签名容器需要全部进行 DER 编码。
据我所知,只要签名容器对某些关键元素进行 DER 编码,PDF 签名验证器就不会拒绝此类签名。不过,对于 future 的工具来说,此类签名可能是一个失败点。
关于itext - 使用外部服务和 iText 签署 PDF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28717704/
有人可以告诉我签署我的 clickonce 应用程序的步骤吗? 如果从某人那里购买证书,我该如何安装它在我的开发盒以及我希望它运行的服务器上? 请概述步骤。 马尔科姆 最佳答案 以下是我相信您正在执行
我正在使用命令行 jarsigner.exe -keystore Keys.jks base.apk debug0 使用我自己的 key 退出 APK ,在删除 META-INF/CERT.RSA、C
我使用 iTextSharp 签署 PDF 文件。但是 Adobe Reader 无法验证我的签名。我使用证书颁发机构生成的 SHA-2 测试证书(我也尝试过 SHA-1)。我已经为该机构的测试证
我在尝试签署 F# 类库项目时遇到了很多麻烦。 首先我试过这个thread ,使用 AssemblyKeyFileAttribute 但没有成功。 我还尝试将标志“--keyfile:keyfile.
我正在尝试掌握 .NET dll/程序集的正式签名。 尤其 何时以及如何使用私钥 创建/控制私钥的最佳实践 需要签署什么样的模块/最佳实践 最佳答案 请参阅使用 Strong Name Signatu
我有一个由五个项目组成的解决方案,每个项目都编译成单独的程序集。现在我正在对它们进行代码签名,但我很确定我做错了。这里的最佳做法是什么? 用不同的 key 对每个签名;确保密码不同 用不同的 key
我有一个由五个项目组成的解决方案,每个项目都编译为单独的程序集。现在我正在对它们进行代码签名,但我很确定我做错了。这里的最佳实践是什么? 使用不同的 key 对每个签名进行签名;确保密码不同 使用不同
尝试在 Java 中签署 SOAP 消息时抛出异常: 14:47:39.896 [AWT-EventQueue-0] ERROR com.ui.FinestraPrincipal - WSHandle
我正在运行 java web start 应用程序。由于应用程序数字签名已过期。我已经从 CA 购买了签名,并使用 storetype 作为 pkcs12 对我的 jar 文件进行了签名。 对 JNL
我已经在jar中手动添加了一些类文件。并在服务器中替换。但服务器没有拿出这个新的 jar 说:java.lang.SecurityException:类“test.TestProcess2”的签名者信
我想使用 keytool 对我的插件 jar 进行签名以生成 key 。 我知道有 -validity 选项,但如何设置它以使插件始终有效且永不过期。 谢谢 最佳答案 查看 keytool 文档: V
我有一个需要互联网访问的 Java 应用程序,因为它通过 WebView 嵌入了 Web 浏览器。 JavaFX 组件。 如果应用程序未打包在 Jar 中,则执行不会出现问题。但是,当打包在 Jar
我以前做过,但我完全忘记了如何签署 activeX 控件? 最佳答案 Digital Signing for ActiveX Components (MSDN) 关于activex - 签署 Acti
不知不觉中我删除了通常命名如下的钥匙串(keychain)系统证书 Software Signing com.apple.systemdefault com.apple.kerberos.kdc Ap
我尝试了一些基于 iText v1 或 v2 的数字 PDF 签名实用程序,发现似乎整个 PDF 都加载到内存中(对于 60M PDF 进程可能需要多达 300-400MB 的内存)。 最近的 iTe
我正在尝试使用 Python 对 Amazon 的 SimpleDB 服务进行 API 调用。例如,我使用的是最简单的请求 ListDomains。然而,无论我如何尝试,响应始终是“我们计算的请求签名
我的同事给了我一个Java项目来支持和增强。我需要签署 .jar 文件。我只找到了下一个文件:genkey.bat、project.cer、signjar.bat 和 keystore-jar.jar
目前我正在升级我的旧应用程序,它是使用 itextsharp 5.0.0 完成的到 5.4.5(最新)...但是我在获取等效代码时遇到了问题 PdfSignatureAppearance.SetCry
如果我有一个作为 API 请求发送的复杂对象(例如下面的订单),我应该在生成签名时包括所有属性还是应该只使用一个子集? 我问是因为我不清楚,而且从查看其他 API 的请求参数来看,请求参数是扁平和简单
为什么 WP7 项目不支持强名称签名?项目属性中没有签名选项卡。 无论如何,我已经使用 AssemblyInfo.cs 中的 AssemblyKeyFile 和 AssemblyDelaySign 属
我是一名优秀的程序员,十分优秀!