我正在使用iTextSharp 5.5.10来生成签名PDF。特别是,我需要LTV签名。LTV可以通过CRL和OCSP请求来完成。
IOcspClient ocspClient = new OcspClientBouncyCastle();
ICrlClient crlClient = new CrlClientOnline(myCert.Chain);
List<ICrlClient> lstCrlClients = new List<ICrlClient> { crlClient };
MakeSignature.SignDetached(sap, signature, this.myCert.Chain, lstCrlClients, ocspClient, null, 0, CryptoStandard.CMS);
我设法用这种代码缓存CRL(它依赖于C#MemoryCache):
private List<ICrlClient> GetCachedListCrlClient()
{
var key = "LstCrlClient";
List<ICrlClient> lstCrlClients = MyGlobalCachingProvider.GetItem<List<ICrlClient>>(key);
if (lstCrlClients == null)
{
lstCrlClients = new List<ICrlClient>();
for (int i = 0; i < myCert.Chain.Length; i++)
{
String crlUrl = CertificateUtil.GetCRLURL(myCert.Chain[i]);
if (crlUrl != null)
{
byte[] crlDownloaded = new System.Net.WebClient().DownloadData(crlUrl);
ICrlClient crlClient = new CrlClientOffline(crlDownloaded);
lstCrlClients.Add(crlClient);
}
}
MyGlobalCachingProvider.AddItem(key, lstCrlClients, DateTime.Now.AddHours(2));
}
return lstCrlClients;
}
但是,我找不到任何缓存OCSP响应的解决方案。有人有线索吗?
多亏了mlk注释,我做到了:我实现了自己的类,灵感来自于OcspClientBouncyCastle代码。代码确实是微不足道的。我的类管理缓存:它只发送一个OCSP请求。这是做这件事的好方法。
示例代码:
// Once instanciated, this class fires one and only one OCSP request : it keeps the first result in memory.
// You may want to cache this object ; ie with MemoryCache.
public class MyOcspClientBouncyCastleSingleRequest : IOcspClient
{
private static readonly ILogger LOGGER = LoggerFactory.GetLogger(typeof(OcspClientBouncyCastle));
private readonly OcspVerifier verifier;
// The request-result
private Dictionary<String, BasicOcspResp> _cachedOcspResponse = new Dictionary<string, BasicOcspResp>();
/**
* Create default implemention of {@code OcspClient}.
* Note, if you use this constructor, OCSP response will not be verified.
*/
[Obsolete]
public MyOcspClientBouncyCastleSingleRequest()
{
verifier = null;
}
/**
* Create {@code OcspClient}
* @param verifier will be used for response verification. {@see OCSPVerifier}.
*/
public MyOcspClientBouncyCastleSingleRequest(OcspVerifier verifier)
{
this.verifier = verifier;
}
/**
* Gets OCSP response. If {@see OCSPVerifier} was set, the response will be checked.
*/
public virtual BasicOcspResp GetBasicOCSPResp(X509Certificate checkCert, X509Certificate rootCert, String url)
{
String dicKey = checkCert.SubjectDN.ToString() + "-" + rootCert.SubjectDN.ToString() + "-" + url;
if (_cachedOcspResponse != null && _cachedOcspResponse.Count > 0 && _cachedOcspResponse.ContainsKey(dicKey))
{
BasicOcspResp cachedResult = _cachedOcspResponse[dicKey];
return cachedResult;
}
else
{
try
{
OcspResp ocspResponse = GetOcspResponse(checkCert, rootCert, url);
if (ocspResponse == null)
{
_cachedOcspResponse.Add(dicKey, null);
return null;
}
if (ocspResponse.Status != OcspRespStatus.Successful)
{
_cachedOcspResponse.Add(dicKey, null);
return null;
}
BasicOcspResp basicResponse = (BasicOcspResp)ocspResponse.GetResponseObject();
if (verifier != null)
{
verifier.IsValidResponse(basicResponse, rootCert);
}
_cachedOcspResponse.Add(dicKey, basicResponse);
return basicResponse;
}
catch (Exception ex)
{
if (LOGGER.IsLogging(Level.ERROR))
LOGGER.Error(ex.Message);
}
return null;
}
}
/**
* Gets an encoded byte array with OCSP validation. The method should not throw an exception.
*
* @param checkCert to certificate to check
* @param rootCert the parent certificate
* @param url to get the verification. It it's null it will be taken
* from the check cert or from other implementation specific source
* @return a byte array with the validation or null if the validation could not be obtained
*/
public byte[] GetEncoded(X509Certificate checkCert, X509Certificate rootCert, String url)
{
try
{
BasicOcspResp basicResponse = GetBasicOCSPResp(checkCert, rootCert, url);
if (basicResponse != null)
{
SingleResp[] responses = basicResponse.Responses;
if (responses.Length == 1)
{
SingleResp resp = responses[0];
Object status = resp.GetCertStatus();
if (status == CertificateStatus.Good)
{
return basicResponse.GetEncoded();
}
else if (status is RevokedStatus)
{
throw new IOException(MessageLocalization.GetComposedMessage("ocsp.status.is.revoked"));
}
else
{
throw new IOException(MessageLocalization.GetComposedMessage("ocsp.status.is.unknown"));
}
}
}
}
catch (Exception ex)
{
if (LOGGER.IsLogging(Level.ERROR))
LOGGER.Error(ex.Message);
}
return null;
}
/**
* Generates an OCSP request using BouncyCastle.
* @param issuerCert certificate of the issues
* @param serialNumber serial number
* @return an OCSP request
* @throws OCSPException
* @throws IOException
*/
private static OcspReq GenerateOCSPRequest(X509Certificate issuerCert, BigInteger serialNumber)
{
// Generate the id for the certificate we are looking for
CertificateID id = new CertificateID(CertificateID.HashSha1, issuerCert, serialNumber);
// basic request generation with nonce
OcspReqGenerator gen = new OcspReqGenerator();
gen.AddRequest(id);
// create details for nonce extension
IDictionary extensions = new Hashtable();
extensions[OcspObjectIdentifiers.PkixOcspNonce] = new X509Extension(false, new DerOctetString(new DerOctetString(PdfEncryption.CreateDocumentId()).GetEncoded()));
gen.SetRequestExtensions(new X509Extensions(extensions));
return gen.Generate();
}
private OcspResp GetOcspResponse(X509Certificate checkCert, X509Certificate rootCert, String url)
{
if (checkCert == null || rootCert == null)
return null;
if (url == null)
{
url = CertificateUtil.GetOCSPURL(checkCert);
}
if (url == null)
return null;
LOGGER.Info("Getting OCSP from " + url);
OcspReq request = GenerateOCSPRequest(rootCert, checkCert.SerialNumber);
byte[] array = request.GetEncoded();
HttpWebRequest con = (HttpWebRequest)WebRequest.Create(url);
con.ContentLength = array.Length;
con.ContentType = "application/ocsp-request";
con.Accept = "application/ocsp-response";
con.Method = "POST";
Stream outp = con.GetRequestStream();
outp.Write(array, 0, array.Length);
outp.Close();
HttpWebResponse response = (HttpWebResponse)con.GetResponse();
if (response.StatusCode != HttpStatusCode.OK)
throw new IOException(MessageLocalization.GetComposedMessage("invalid.http.response.1", (int)response.StatusCode));
Stream inp = response.GetResponseStream();
OcspResp ocspResponse = new OcspResp(inp);
inp.Close();
response.Close();
return ocspResponse;
}
我正在使用iText 5.5.3来签署PDF文档。我需要这些文件是时间戳和LTV启用。我按照说明使用addLtv方法(代码示例5.9,Lowagie白皮书第137页)。我得到一个带有2个签名的PDF,这是正常的:第一个是我自己的签名,第二个是文档级时间戳。 但是,Acrobat告诉我我的签名启用了LTV,但时间戳签名没有: 图片来自Acrobat Pro XIhttp://img15.hostin
我是iText的新手。我想签署一个PDF并添加LTV到它。签署PDF是好的但当我想添加LTV到PDF时,它不显示我的OCSP和时间戳证书的CRL信息。首先,我想描述一下我是如何签约的。-我的证书链:签名证书,签名证书根,时间戳证书,时间戳证书根。(我忘了锁链上有什么东西吗?) 要签名PDF,我使用的是: 之后,我将为签名和时间戳添加LTV。 谢谢你。
在过去的几周里,我一直在使用iText对PDF文件进行数字签名,根据我的理解,有两种方法可以将信息添加到PDF中,使其启用LTV: > 使用iText示例中提供的代码添加信息,此方法要求签名已经存在,因为DSS 嵌入crl字节 尽管第一种方法生成了一个整洁的pdf文件,但问题是它修改pdf文件以创建/附加条目,从而导致认证签名无效,第二个很好,但它会根据crl列表的大小大幅增加pdf大小(这也可能
我正在尝试使用远程web服务来演唱pdf,该服务返回一个XML签名,该签名由签名和最终用户证书组成。 我需要使用此签名通过IText签名对pdf进行签名,因为web服务。 所有IText示例都使用消息格式,但我不确定应该如何处理XML签名。 打开临时Pdf并嵌入接收到的签名的代码 从web服务返回的XML签名: 当我将返回的签名与上面的代码一起使用时,签名验证失败,出现“错误遇到时BER解码”。
据我所知有两种方法 添加DSS字典 在签名时在签名中嵌入CRL或OCSP响应 DSS方法似乎是可行的,Adobe将签名识别为启用了LTV。第二种方法更适合我们的应用程序,所以我仍在努力让它工作。我在向签名添加OCSP响应时遇到了问题,所以我只尝试添加证书和CRL。如果我错了,请纠正我,但据我所知,CRL或OCSP响应都应该添加到签名中。不需要两者兼而有之吗?我收集签名证书及其根证书,还有TSA证书
我想知道是否有一个替代包括完整的CRL同时仍然支持LTV?包含完整的CRL似乎有点矫枉过正,而似乎唯一需要的“东西”是包含一个可验证的证明,证明链中的证书在签名时没有被撤销。我认为使用OCSP可能会提供这样的功能,但是简单地删除CRL并包含一个OcspClientBouncyCastle实例并不能起到作用。授予SignDetached的OCSP是否用于检查证书是否在签名时被吊销? 一个相关的问题涉