当前位置: 首页 > 知识库问答 >
问题:

带时间戳的数字签名Java

咸利
2023-03-14

我在使用可信时间戳创建Bouncy Castle的有效CMS签名时遇到了问题。签名创建工作正常(我想将签名包含到PDF文件中),签名是有效的。但是在我将可信时间戳包含到签名的无符号属性表后,签名仍然有效,但是读者报告签名包括嵌入的时间戳,但它是无效的。这让我相信,哈希I时间戳不是正确的,但我似乎无法弄清楚它的问题。

签署代码:

Store store = new JcaCertStore(Arrays.asList(certContainer.getChain()));

CMSSignedDataGenerator signedDataGenerator = new CMSSignedDataGenerator();
JcaSignerInfoGeneratorBuilder infoGeneratorBuilder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build());
JcaContentSignerBuilder contentSignerBuilder = new JcaContentSignerBuilder("SHA1withRSA");
signedDataGenerator.addSignerInfoGenerator(
                       infoGeneratorBuilder.build(contentSignerBuilder.build(certContainer.getPrivateKey()), (X509Certificate)certContainer.getSignatureCertificate()));
signedDataGenerator.addCertificates(store);
CMSTypedData cmsData = new CMSProcessableByteArray(data);
signedData = signedDataGenerator.generate(cmsData, false);
Collection<SignerInformation> ss = signedData.getSignerInfos().getSigners();
SignerInformation si = ss.iterator().next(); // get first signer (should be only one)
ASN1EncodableVector timestampVector = new ASN1EncodableVector();
Attribute token = createTSToken(si.getSignature());
timestampVector.add(token);
AttributeTable at = new AttributeTable(timestampVector);
si = SignerInformation.replaceUnsignedAttributes(si, at);
ss.clear();
ss.add(si);
SignerInformationStore newSignerStore = new SignerInformationStore(ss);
CMSSignedData newSignedData = CMSSignedData.replaceSigners(signedData, newSignerStore);

createTSToken代码:

public Attribute createTSToken(byte[] data) throws NoSuchProviderException, NoSuchAlgorithmException, IOException {
    // Generate timestamp
    MessageDigest digest = MessageDigest.getInstance("SHA1", "BC");
    TimeStampResponse response = timestampData(digest.digest(data));
    TimeStampToken timestampToken = response.getTimeStampToken();
    // Create timestamp attribute

    Attribute a = new Attribute(PKCSObjectIdentifiers.id_aa_signatureTimeStampToken, new DERSet(ASN1Primitive.fromByteArray(timestampToken.getEncoded())));
    return a;
}

时间戳数据

TimeStampRequestGenerator reqgen = new TimeStampRequestGenerator();
TimeStampRequest req = reqgen.generate(TSPAlgorithms.SHA1, data);
byte request[] = req.getEncoded();

URL url = new URL("http://time.certum.pl");
HttpURLConnection con = (HttpURLConnection) url.openConnection();

con.setDoOutput(true);
con.setDoInput(true);
con.setRequestMethod("POST");
con.setRequestProperty("Content-type", "application/timestamp-query");
con.setRequestProperty("Content-length", String.valueOf(request.length));

OutputStream out = con.getOutputStream();
out.write(request);
out.flush();

if (con.getResponseCode() != HttpURLConnection.HTTP_OK) {
    throw new IOException("Received HTTP error: " + con.getResponseCode() + " - " +                 con.getResponseMessage());
}
InputStream in = con.getInputStream();
TimeStampResp resp = TimeStampResp.getInstance(new ASN1InputStream(in).readObject());
response = new TimeStampResponse(resp);
response.validate(req);
if(response.getStatus() != 0) {
    System.out.println(response.getStatusString());
    return null;
}
return response;

谢谢你的帮助!

示例文件:

签名PDF

未签名的PDF

用iText签名的PDF

带LTV的签名PDF-已编辑

共有1个答案

赵鸿畴
2023-03-14

时间戳令牌引用为签名者一些

CN=e-Szigno Test TSA2,OU=e-Szigno CA,O=Microsec Ltd.,L=Budapest,C=HU

已由

CN=Microsec e-Szigno测试根CA 2008,OU=e-Szigno CA,O=Microsec Ltd.,L=布达佩斯,C=HU

序列号是7。

不过,它本身并不提供该证书,它也不是由封装签名html" target="_blank">html" target="_blank">CMS容器提供的,也不是在一些与验证相关的信息PDF文档部分中提供的。

因此,至少在我的计算机上,不可能以任何方式验证时间戳令牌,Adobe Reader完全正确地不接受时间戳。

您是否以适合您的Adobe Reader的方式在您的计算机上提供了有问题的证书?如果您有,但它仍然不起作用,请提供它以供进一步测试。如果您没有,请尝试检索并提供它们。

在将时间戳令牌包含到签名中之前,您可能需要增强时间戳令牌本身以包含该证书。

在更新的文件中signed_lipsum.pdf签名时间戳包含TSA证书,但它是错误的!

就像在第一个版本中一样,时间戳引用了带有

  • 主题CN=e-Szigno Test TSA2, OU=e-Szigno CA, O=Microsec Ltd., L=Budapest, C=HU
  • 发行人CN=Microsec e-Szigno测试根CA 2008, OU=e-Szigno CA, O=Microsec Ltd., L=Budapest, C=HU
  • 序列号7.

另一方面,包含的证书具有

  • 受试者CN=e-Szigno测试TSA2,OU=e-Szigno CA,O=Microsec有限公司,L=布达佩斯,C=HU

我假设测试TSA使用多个签名设备/软令牌和单个证书,而OP包含了错误的证书。

因此,您可能希望包含正确的证书。

顺便说一句,由iText签名的PDF中的时间戳包含与该戳中的引用相匹配的证书...

RFC 3161时间戳请求可以要求TSA自动包含签名者证书。Bouncy Castle允许像这样设置旗帜:

TimeStampRequestGenerator reqgen = new TimeStampRequestGenerator();
reqgen.setCertReq(true); // <<<<<<<<<<<<<<<<<<<<<<<<<<
TimeStampRequest req = reqgen.generate(TSPAlgorithms.SHA1, data);

您可以试试这个,而不是自己包含证书。

从评论中:

只是出于好奇,什么额外的需要添加,使PDF LTV启用?

引用Leonard Rosenthol(Adobe的PDF大师)的话:

启用LTV意味着验证文件(减去根证书)所需的所有信息都包含在中。所以这个声明[…]那是真的。

PDF已正确签名,并包含所有必要的证书、每个证书的有效CRL或OSCP响应

(2013年1月10日;晚上7:07;Leonard Rosenthol在itext general上)

 类似资料:
  • 问题内容: 我在使用受信任的时间戳与Bouncy Castle创建有效的CMS签名时遇到问题。签名创建工作良好(我想将签名包括到PDF文件中),签名有效。但是,当我在签名的未签名属性表中添加可信时间戳后,签名仍然保持有效,但是Reader会报告 该签名包括嵌入式时间戳,但是无效 。这使我相信,哈希时间戳是不正确的,但是我似乎无法弄清楚问题出在哪里。 签名代码: 该代码: : 谢谢你的帮助! 示例文

  • 我尝试使用外部Web服务对pdf进行数字签名。此Web服务包含用户证书,用户可以使用他们的凭据和一次性密码生成的代码访问该证书。 旁注:web服务应该期望pdf摘要(哈希),但奇怪的是,它却接受整个文件。 无论如何,实现如下: pdf已成功签名,但使用Adobe Reader并检查签名字段时,似乎缺少可信时间戳,如图所示: 看起来,来自远程服务的响应是一个签名对象,我只需要将其嵌入到PDF文件中。

  • 问题内容: 这是我的问题:我有一个用户输入日期,例如:2012-12-24(字符串)我将一个时间连接到该字符串,然后转换为java.util.Date我的代码如下: 我的问题是,当我使用该util.Date并将其设置为sql.Date时: 它不会给我分配的时间戳,只会以yyyy-MM-dd格式返回日期(例如2012-12-23)。 为什么!?我好沮丧 注意:我注意到当我使用断点时,我能够展开sql

  • 问题内容: 我想将时间戳添加到我的PDF文档中(不带数字签名)。我怎样才能做到这一点? 我可以使用Itext使用数字签名来做到这一点(我在这里有TSAClient): 但是在没有数字签名的情况下如何做类似的事情?使用Bouncy Castle或Itext或Pdfbox …或其他库。 问题答案: 在iText中,您正在寻找 也比照。JavaDoc文档: 您可能需要阅读章节5.4.1 在数字签名中为P

  • 问题内容: 当我尝试自签名时,如下所示。 它给出如下警告: 没有提供-tsa或- tsacert,并且这个jar没有时间戳记。如果没有时间戳,则用户可能无法在签署者证书的到期日期(2014-05-08)或以后的任何吊销日期之后验证此jar。 请帮助解决问题。 问题答案: 最近的Java 7提供了(礼貌吗?)关于已经存在十年的警告。 Trusted Timestamping在Java 5(2004)

  • 我正在使用iText 5.5.3来签署PDF文档。我需要这些文件是时间戳和LTV启用。我按照说明使用addLtv方法(代码示例5.9,Lowagie白皮书第137页)。我得到一个带有2个签名的PDF,这是正常的:第一个是我自己的签名,第二个是文档级时间戳。 但是,Acrobat告诉我我的签名启用了LTV,但时间戳签名没有: 图片来自Acrobat Pro XIhttp://img15.hostin