带有Java时间戳的数字签名 [英] Digital signature with timestamp in Java

查看:1130
本文介绍了带有Java时间戳的数字签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用受信任的时间戳,我在使用Bouncy Castle创建有效的CMS签名时遇到问题。签名创建效果很好(我希望将签名包含在PDF文件中),签名有效。但是,在我将可信时间戳包含在签名的无符号属性表中后,签名仍然有效,但Reader报告签名包含嵌入时间戳,但它无效。这让我相信,哈希我的时间戳不是正确的,但我似乎无法弄清楚它有什么问题。

I have an issue creating a valid CMS signature with Bouncy Castle using a trusted timestamp. The signature creation works well (I want to include the signature to a PDF file), the signature is valid. But after I include a trusted timestamp to the signature's unsigned attribute table, the signature still stays valid, but the Reader reports that The signature includes an embedded timestamp but it is invalid. This leads me to believe, that the hash I timestamp is not the correct one, but I cannot seem to figure out what is the problem with it.

签名代码:

Signing code:

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;
}

timestampData

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 - 已编辑

推荐答案

signed_lipsum.pdf,第一个版本



时间戳令牌引用为签名者

signed_lipsum.pdf, first version

The time stamp token references as signer some


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

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

已由


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

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

序列号为7。

但它本身并不提供此证书,也不是由封装签名CMS容器提供的,也不是一些验证相关信息PDF文档部分。

It does not provide this certificate itself, though, and neither is it provided by the encapsulating signature CMS container nor in some validation related information PDF document section.

因此,至少在我的计算机上没有机会以任何方式验证时间戳令牌而Adobe Reader是完全正确的接受时间戳。

Thus, at least on my computer there is no chance of verifying the time stamp token in any way and Adobe Reader is completely right not to accept the time stamp.

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

Have you provided the certificate in question on your computer in a way appropriate for your Adobe Reader? If you have and it still does not work, please supply it for further tests. If you have not, try to retrieve and provide them.

您可能希望加强时间戳令牌本身以包含该证书,然后再将其包含在签名中。

You might want to beef up the time stamp token itself to include that certificate before including it into the signature.

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

In the updated file signed_lipsum.pdf the signature time stamp contains a TSA certificate, but it is the wrong one!

就像在第一个版本中一样,时间戳引用签名者证书

Just like in the first version the time stamp references a signer certificate with


  • 主题CN = e-Szigno测试TSA2,OU = e-Szigno CA,O = Microsec Ltd.,L =布达佩斯,C = HU

  • 发行人CN = Microsec e-Szigno Test Root CA 2008,OU = e-Szigno CA,O = Microsec Ltd.,L = Budapest,C = HU

  • 序列号7.

  • Subject CN=e-Szigno Test TSA2,OU=e-Szigno CA,O=Microsec Ltd.,L=Budapest,C=HU
  • Issuer CN=Microsec e-Szigno Test Root CA 2008,OU=e-Szigno CA,O=Microsec Ltd.,L=Budapest,C=HU
  • Serial number 7.

另一方面,所包含的证书

The contained certificate, on the other hand, has


  • 主题CN = e-Szigno测试TSA2,OU = e-Szigno CA,O = Microsec Ltd.,L =布达佩斯,C = HU

  • 发行人CN = Microsec e-Szigno Test Root CA 2008,OU = e-Szigno C. A,O = Microsec Ltd.,L =布达佩斯,C = HU

  • 序列号5。

  • Subject CN=e-Szigno Test TSA2,OU=e-Szigno CA,O=Microsec Ltd.,L=Budapest,C=HU
  • Issuer CN=Microsec e-Szigno Test Root CA 2008,OU=e-Szigno CA,O=Microsec Ltd.,L=Budapest,C=HU
  • Serial number 5.

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

I assume that test TSA uses multiple signing devices / soft-tokens with individual certificates and the OP included the wrong one.

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

You, therefore, might want to include the correct certificate instead.

BTW,由iText签名的PDF中的时间戳包含与图章中的参考相匹配的证书...

BTW, the time stamp in the PDF signed by iText contains a certificate matching the references in the stamp...

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

RFC 3161 time stamp requests can ask the TSA to include the signer certificate automatically. Bouncy Castle allows to set this flag like this:

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

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

Instead of including the certificate yourself, you might try this.

来自评论:


出于好奇,需要添加什么额外的东西才能启用PDF LTV?

Just out of curiosity, what extra needs to be added to make a PDF LTV enabled?

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

To quote Leonard Rosenthol (PDF guru at Adobe):


启用LTV意味着验证文件所需的所有信息(减去根证书)都包含在其中。所以这个陈述是真的。

LTV enabled means that all information necessary to validate the file (minus root certs) is contained within. So this statement [...] would be true.


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

the PDF is signed correctly and contains all necessary certificates, a valid CRL or OSCP response for every certificate

2013年1月10日;下午7:07; Leonard Rosenthol on itext-general

这篇关于带有Java时间戳的数字签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆