有効なPKCS7ファイルがCMSSignedDataオブジェクトにロードされています。このPKCS7ファイルには、プレーンテキストメッセージと有効な添付デジタル署名が含まれています(すべて同じファイル内にあります)。
次に、このファイルにタイムスタンプを付けます。これは私が使用しているコードです(ソース):
private static CMSSignedData addTimestamp(CMSSignedData signedData)
throws Exception {
Collection ss = signedData.getSignerInfos().getSigners();
SignerInformation si = (SignerInformation) ss.iterator().next();
TimeStampToken tok = getTimeStampToken();
ASN1InputStream asn1InputStream = new ASN1InputStream
(tok.getEncoded());
DERObject tstDER = asn1InputStream.readObject();
DERSet ds = new DERSet(tstDER);
Attribute a = new Attribute(new
DERObjectIdentifier("1.2.840.113549.1.9.16.2.14"), ds);
DEREncodableVector dv = new DEREncodableVector();
dv.add(a);
AttributeTable at = new AttributeTable(dv);
si = SignerInformation.replaceUnsignedAttributes(si, at);
ss.clear();
ss.add(si);
SignerInformationStore sis = new SignerInformationStore(ss);
signedData = CMSSignedData.replaceSigners(signedData, sis);
return signedData;
}
private static TimeStampToken getTimeStampToken() throws
Exception {
Security.addProvider (new
org.bouncycastle.jce.provider.BouncyCastleProvider());
PostMethod post = new PostMethod("http://My-TrustedTimeStampProvier.com");
// I'm omitting the part where I pass the user and password
TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
//request TSA to return certificate
reqGen.setCertReq (true); // In my case this works
//make a TSP request this is a dummy sha1 hash (20 zero bytes)
TimeStampRequest request =
reqGen.generate(TSPAlgorithms.SHA1, new byte[20], BigInteger.valueOf(100));
byte[] enc_req = request.getEncoded();
ByteArrayInputStream bais = new ByteArrayInputStream(enc_req);
post.setRequestBody(bais);
post.setRequestContentLength (enc_req.length);
post.setRequestHeader("Content-type","application/timestamp-query");
HttpClient http_client = new HttpClient();
http_client.executeMethod(post);
InputStream in = post.getResponseBodyAsStream();
//read TSP response
TimeStampResponse resp = new TimeStampResponse (in);
resp.validate(request);
TimeStampToken tsToken = resp.getTimeStampToken();
return tsToken;
}
有効なTimeStampを取得でき、それをCMSSignedDataオブジェクトに入れて、signedData.getEncoded()からハードディスクにバイトを書き込むファイルに保存できます。しかし、サードパーティのソフトウェアで新しい光沢のあるタイムスタンプ付きファイルを検証すると、このソフトウェアは元の署名に問題がないことを通知しますが、タイムスタンプは署名に対応していません。このソフトウェアは、元のプレーンテキストメッセージを表示することもできます。
私は問題がこの行にあると思います:
TimeStampRequest request =
reqGen.generate(TSPAlgorithms.SHA1, new byte[20], BigInteger.valueOf(100));
ダミーのバイト配列の代わりにダイジェストを渡す必要があると思いますが、どのダイジェスト、またはtimeStampに必要な正しいバイトは何かわかりません。SignerInformation
からオブジェクトを取得して検証することに成功しましたsignedData
。次にreqGen.generate()
、からのバイトを関数に渡そうとしましたmySignerInformation.getSignature()
。タイムスタンプの検証に失敗しました。次に、のSha1ダイジェストを渡しましたmySignerInformation.getSignature()
が、タイムスタンプの検証に再度失敗しました。
RFC3161の仕様は言います:
2.4.1。リクエストフォーマット
タイムスタンプの要求は次のとおりです。
TimeStampReq :: = SEQUENCE {バージョンINTEGER {v1(1)}、messageImprint MessageImprint、-ハッシュアルゴリズムのOIDとデータのハッシュ値
(...)
messageImprintフィールドには、タイムスタンプを付けるデータのハッシュを含める必要があります。ハッシュはOCTETSTRINGとして表されます。その
長さは、そのアルゴリズムのハッシュ値の長さと一致する必要があります
(たとえば、SHA-1の場合は20バイト、MD5の場合は16バイト)。MessageImprint :: = SEQUENCE {hashAlgorithm AlgorithmIdentifier、hashedMessage OCTET STRING}
ただし、CMSSignedDataオブジェクト内のバイトをタイムスタンプする場合、MessageImprintデータをどこでどのように取得するかはわかりません。
私はこのデジタル署名の初心者です。
そうです、問題は、間違ったデータにタイムスタンプを付けていることです。コードの残りの部分は私には正しいようです。
つまり、署名のハッシュにタイムスタンプを付ける必要があります。から署名を取得してCMSSignedData
ハッシュするには、次のコードを使用できます(署名者が1人だけで、ハッシュアルゴリズムPKCS7
を使用していると仮定しますSHA1
)。
CMSSignedData signedData = ...
// get the signers of your CMSSignedData signedData
Collection ss = signedData.getSignerInfos().getSigners();
SignerInformation si = (SignerInformation) ss.iterator().next();
// hash the signature
byte[] signDigest = MessageDigest
.getInstance(TSPAlgorithms.SHA1, new BouncyCastleProvider())
.digest(si.getSignature()); // since you're adding the bc provider with Security.addProvider you can use "BC" instead of passing the new BouncyCastleProvider()
TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
// generate the TSRequest
TimeStampRequest request =
reqGen.generate(TSPAlgorithms.SHA1, signDigest, BigInteger.valueOf(100));
...
お役に立てれば、
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加