我正在使用iTextSharp库来签署PDF文档。当我使用标准TSAClientBouncyCastle类从GoDaddy的服务器(http://tsa.starfieldtech.com)获取时间戳时,响应是一个空流。同时,它与其他符合RFC 3161标准的时间戳服务器完美配合。此外,当我使用microsoft的signtool.exe用/ tr选项签署exe文件时,它可以与Godaddy的服务器一起使用。 所以我想知道我尝试使用iTextSharp库以编程方式获取时间戳有什么问题。
提前致谢。
UPD:
我使用过这个样本:
只进行了修改,我已经使用带有URL的构造函数指定了TSAClient。
代码以下列方式修改:而不是
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, subfilter);
我用
ITSAClient tsaClient = new TSAClientBouncyCastle("http://tsa.starfieldtech.com/");
MakeSignature.SignDetached(appearance, pks, chain, null, null, tsaClient, 0, subfilter);
答案 0 :(得分:1)
当我使用标准
TSAClientBouncyCastle
类从GoDaddy的服务器(http://tsa.starfieldtech.com)获取时间戳时,响应是一个空流。
我可以使用iTextSharp& amp;来重现这种行为。 C#但不是iText& Java的。
通过检查实际网络流量,时间戳请求对象被证明是相同构建的,但在封装HTTP请求中使用的HTTP头存在细微差别。
逐个调整TSAClientBouncyCastle.GetTSAResponse
中的请求标头, User-Agent 标头被证明是罪魁祸首:
HttpWebRequest
似乎不会添加此类标题,但HttpURLConnection
会添加包含Java版本作为值的标头,例如: "爪哇/ 1.8.0_20" 在TSAClientBouncyCastle.GetTSAResponse
中明确添加此类标题后,例如像这样:
/**
* 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";
时间戳服务器返回正确的时间戳响应。
由于User-Agent标头被指定为建议但不是必需的,因此时间戳服务器的这种行为是非常值得怀疑的。
实际上我必须首先解决另一个问题:我必须在这里使用HTTP代理,并且代理总是干扰iTextSharp / C#时间戳请求(但同样不是iText / Java时间戳请求)一个
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标题应该没什么坏处但我怀疑一般将HTTP限制为1.0是一个好主意。)