带有 TSA 时间戳的 PDF 签名
PDF Signature with timestamping from TSA
我们正在尝试将时间戳签名作为 CMS 格式的未签名属性嵌入,但在 PDF 中标记签名后,提供 签名的 PDF 查看器包含嵌入的时间戳,但它是无效的 消息.
我们使用内部 TSA 服务(自签名)TSA 和充气城堡 API 进行加密和签名操作。但是不知道时间戳发生了什么。谁能知道我在做什么错。
hello_signed.pdf
还添加了 Java 代码库和签名的 pdf 示例以供参考。
如有任何帮助,我们将不胜感激。
这意味着 Acrobat 找不到用于创建时间戳的证书。查看 ASN.1 decode for your PDF signature CMS,您似乎没有在请求中请求 Timestamp Authority 的证书(搜索 timeStampToken 将您带到 CMS 的相应部分)。在 Bouncy Castle 中,这是通过在 TimeStampRequestGenerator 实例上调用 SetCertReq(true) 来实现的,如下所示:
TimeStampRequestGenerator reqGenerator = new TimeStampRequestGenerator();
// Request the server to also include the signing certificate:
reqGenerator.SetCertReq(true);
设置时,时间戳机构将包括证书,或更常见的时间戳证书及其链,作为实际时间戳的 SignedCms 中的签名属性。
要确认证书包含在响应中,您可以将时间戳机构的响应作为十六进制字符串写入文本文件,并使用此网站对其进行解码 https://lapo.it/asn1js/。
TSTInfo
结构有问题,它的tsa
成员是
C = IN,S = MH,L = NSDL,O = NSDL,OU = NSDL,CN = NSDL,E = nsdl@nsdl.co.in
但您的 TSA 证书的主题相反
E = nsdl@nsdl.co.in,CN = NSDL,OU = NSDL,O = NSDL,L = NSDL,S = MH,C = IN
根据 RFC 3161,tsa 字段的目的是在识别
TSA 的名称。 如果存在,它必须对应于其中一个
证书中包含的主题名称,用于
验证令牌。
因此,细心的验证者无法使用您提供的证书来验证时间戳。
我不知道这是否是唯一的问题,但它绝对是一个阻碍。
根据 TSA RFC 3161,tsa 字段的目的是提供识别 TSA 名称的提示。如果存在,它必须对应于证书中包含的主题名称之一,用于验证令牌。然而,签署响应的实体的实际标识将始终通过使用 SigningCertificate 属性内的证书标识符(ESSCertID 属性)来实现,该属性是 signerInfo 的一部分(请参阅 [ESS] 的第 5 节)。
针对此问题,TSA 需要按以下方式构建 tsa
GeneralName
属性。对源进行了以下更改。使用 TSA 证书构建 tsa
SubjectDN
不工作
GeneralName gn = new GeneralName(GeneralName.directoryName, new X500Name(cacert.getSubjectX500Principal().getName()));
工作代码
X500Name iss = X500Name.getInstance(cacert.getSubjectX500Principal().getEncoded()); GeneralName gn = new GeneralName(GeneralName.directoryName, iss); tkg.setTSA(gn);
我们正在尝试将时间戳签名作为 CMS 格式的未签名属性嵌入,但在 PDF 中标记签名后,提供 签名的 PDF 查看器包含嵌入的时间戳,但它是无效的 消息.
我们使用内部 TSA 服务(自签名)TSA 和充气城堡 API 进行加密和签名操作。但是不知道时间戳发生了什么。谁能知道我在做什么错。
hello_signed.pdf 还添加了 Java 代码库和签名的 pdf 示例以供参考。
如有任何帮助,我们将不胜感激。
这意味着 Acrobat 找不到用于创建时间戳的证书。查看 ASN.1 decode for your PDF signature CMS,您似乎没有在请求中请求 Timestamp Authority 的证书(搜索 timeStampToken 将您带到 CMS 的相应部分)。在 Bouncy Castle 中,这是通过在 TimeStampRequestGenerator 实例上调用 SetCertReq(true) 来实现的,如下所示:
TimeStampRequestGenerator reqGenerator = new TimeStampRequestGenerator();
// Request the server to also include the signing certificate:
reqGenerator.SetCertReq(true);
设置时,时间戳机构将包括证书,或更常见的时间戳证书及其链,作为实际时间戳的 SignedCms 中的签名属性。
要确认证书包含在响应中,您可以将时间戳机构的响应作为十六进制字符串写入文本文件,并使用此网站对其进行解码 https://lapo.it/asn1js/。
TSTInfo
结构有问题,它的tsa
成员是
C = IN,S = MH,L = NSDL,O = NSDL,OU = NSDL,CN = NSDL,E = nsdl@nsdl.co.in
但您的 TSA 证书的主题相反
E = nsdl@nsdl.co.in,CN = NSDL,OU = NSDL,O = NSDL,L = NSDL,S = MH,C = IN
根据 RFC 3161,tsa 字段的目的是在识别 TSA 的名称。 如果存在,它必须对应于其中一个 证书中包含的主题名称,用于 验证令牌。
因此,细心的验证者无法使用您提供的证书来验证时间戳。
我不知道这是否是唯一的问题,但它绝对是一个阻碍。
根据 TSA RFC 3161,tsa 字段的目的是提供识别 TSA 名称的提示。如果存在,它必须对应于证书中包含的主题名称之一,用于验证令牌。然而,签署响应的实体的实际标识将始终通过使用 SigningCertificate 属性内的证书标识符(ESSCertID 属性)来实现,该属性是 signerInfo 的一部分(请参阅 [ESS] 的第 5 节)。
针对此问题,TSA 需要按以下方式构建 tsa
GeneralName
属性。对源进行了以下更改。使用 TSA 证书构建 tsa
SubjectDN
不工作
GeneralName gn = new GeneralName(GeneralName.directoryName, new X500Name(cacert.getSubjectX500Principal().getName()));
工作代码
X500Name iss = X500Name.getInstance(cacert.getSubjectX500Principal().getEncoded()); GeneralName gn = new GeneralName(GeneralName.directoryName, iss); tkg.setTSA(gn);