GoDaddy 的时间戳服务器和 iTextSharp 有什么问题?

What is wrong with GoDaddy's timestamp server and iTextSharp?

我正在使用 iTextSharp 库来签署 PDF 文档。

当我使用标准 TSAClientBouncyCastle class 从 GoDaddy 的服务器 (http://tsa.starfieldtech.com) 获取时间戳时,响应是一个空流。

同时,它与其他符合 RFC 3161 标准的时间戳服务器完美配合。此外,当我使用 Microsoft 的 signtool.exe/tr 选项签署 exe 文件时,它可以与 Godaddy 的服务器一起使用。

所以我想知道我尝试使用 iTextSharp 库以编程方式获取时间戳有什么问题。

更新

我用过这个样本:

http://sourceforge.net/p/itextsharp/code/HEAD/tree/tutorial/signatures/chapter2/C2_01_SignHelloWorld/C2_01_SignHelloWorld.cs

我只修改了 TSAClient 构造函数,该构造函数采用 URL.

这意味着不是调用:

MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, subfilter);

我使用:

ITSAClient tsaClient = new TSAClientBouncyCastle("http://tsa.starfieldtech.com/");

MakeSignature.SignDetached(外观, pks, 链, null, null, tsaClient, 0, subfilter);

When I use the standard TSAClientBouncyCastle class to get time stamp from GoDaddy's server (http://tsa.starfieldtech.com), the response is an empty stream.

我可以使用 iTextSharp 和 C# 重现此行为,但不能使用 iText 和 Java。

通过检查实际的网络流量,时间戳请求 objects 结果是相同构建的,但在封装 HTTP 请求中使用的 HTTP headers 存在细微差别。

正在 TSAClientBouncyCastle.GetTSAResponse 中 header 一个一个地调整请求, User-Agent header被证明是罪魁祸首:

  • .Net HttpWebRequest默认好像没有加这样一个header但是
  • Java HttpURLConnection 默认添加这样一个 header 包含 Java 版本作为值,例如"Java/1.8.0_20".

TSAClientBouncyCastle.GetTSAResponse 中明确添加这样的 header 之后,例如像这样:

/**
 * Get timestamp token - communications layer
 * @return - byte[] - TSA response, raw bytes (RFC 3161 encoded)
 */
protected internal virtual byte[] GetTSAResponse(byte[] requestBytes) {
    HttpWebRequest con = (HttpWebRequest)WebRequest.Create(tsaURL);
    // Additional User-Agent header to make http://tsa.starfieldtech.com happy
    con.UserAgent = "iTextSharp";
    con.ContentLength = requestBytes.Length;
    con.ContentType = "application/timestamp-query";
    con.Method = "POST";

时间戳服务器returns 正确的时间戳响应。

由于 User-Agent header 被指定为推荐但不是必需的,因此关注的时间戳服务器的这种行为非常值得怀疑。


实际上我不得不先解决一个不同的问题:我必须在这里使用 HTTP 代理,代理总是干扰 iTextSharp/C# 时间戳请求(但同样不会干扰 iText/Java 时间戳请求)返回 a

System.Net.WebException : The remote server returned an error: (417) Expectation Failed.
at System.Net.HttpWebRequest.GetResponse()

将 HTTP 协议版本限制为 1.0

    con.ProtocolVersion = Version.Parse("1.0");

解决了这个问题。


(@BrunoLowagie、@PauloSoares:在 iTextSharp 中添加 User-Agent header 应该没什么坏处,但我怀疑通常将 HTTP 限制为 1.0 是个好主意。)