3

信頼できるタイムスタンプを使用して、Bouncy Castle で有効な CMS 署名を作成する際に問題があります。署名の作成はうまく機能し (署名を PDF ファイルに含めたい)、署名は有効です。しかし、信頼できるタイムスタンプを署名の unsigned 属性テーブルに含めた後も、署名は引き続き有効ですが、リーダーはThe signature includes an embedded timestamp but it is invalid と報告します。これにより、ハッシュ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;
}

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 - 編集済み

4

1 に答える 1

2

signed_lipsum.pdf、初版

タイムスタンプ トークンは、署名者として参照します

CN=e-Szigno Test 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=ブダペスト、C=HU

シリアルナンバー7です。

ただし、この証明書自体は提供されず、カプセル化された署名 CMS コンテナーによっても、一部の検証関連情報 PDF ドキュメント セクションでも提供されません。

したがって、少なくとも私のコンピューターでは、タイムスタンプトークンを検証する機会はまったくなく、Adobe Reader がタイムスタンプを受け入れないのは完全に正しいことです。

Adobe Reader に適した方法で問題の証明書をコンピューターに提供しましたか? 持っていてまだ動作しない場合は、さらにテストするために提供してください。まだ取得していない場合は、それらを取得して提供してみてください。

署名に含める前に、その証明書を含めるようにタイムスタンプトークン自体を強化することをお勧めします。

signed_lipsum.pdf、第 2 バージョン

更新されたファイル signed_lipsum.pdf では、署名のタイム スタンプに TSA 証明書が含まれていますが、これは間違っています。

最初のバージョンと同様に、タイム スタンプは署名者証明書を参照します。

  • Subject CN=e-Szigno Test 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=ブダペスト、C=HU
  • シリアルナンバー7。

一方、含まれている証明書には、

  • Subject CN=e-Szigno Test 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=ブダペスト、C=HU
  • シリアルナンバー5。

テストTSAは複数の署名デバイス/ソフトトークンを個別の証明書とともに使用し、OPには間違ったものが含まれていると思います。

したがって、代わりに正しい証明書を含めることをお勧めします。

ところで、iText によって署名された PDF のタイムスタンプには、スタンプ内の参照と一致する証明書が含まれています...

RFC 3161 タイム スタンプ要求は、署名者証明書を自動的に含めるよう TSA に要求できます。Bouncy Castle では、このフラグを次のように設定できます。

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

自分で証明書を含める代わりに、これを試すことができます。

LTV が有効

コメントから:

PDF LTV を有効にするには、何を追加する必要がありますか?

Leonard Rosenthol (Adobe の PDF グル) を引用するには:

LTV が有効になっているということは、ファイルの検証に必要なすべての情報 (ルート証明書を除く) が含まれていることを意味します。したがって、このステートメント [...] は真実です。

PDF は正しく署名されており、必要なすべての証明書、すべての証明書に対する有効な CRL または OSCP 応答が含まれています。

( 2013 年 1 月 10 日、午後 7 時 7 分、itext-general の Leonard Rosenthol )

于 2014-02-19T08:59:30.573 に答える