如何对 PDF 中的证书吊销列表 (CRL) 流字节进行编码?
Posted
技术标签:
【中文标题】如何对 PDF 中的证书吊销列表 (CRL) 流字节进行编码?【英文标题】:How do you encode the Certificate Revocation List (CRL) stream bytes in PDF? 【发布时间】:2020-06-11 10:24:56 【问题描述】:我签署了一份 PDF 并添加了更新版本,我在其中编写了带有 CRL、证书、VRI 的 DSS。
19 0 obj
[15 0 R 16 0 R]
endobj
20 0 obj
[13 0 R 14 0 R]
endobj
11 0 obj
[15 0 R 16 0 R]
endobj
12 0 obj
[13 0 R 14 0 R]
endobj
17 0 obj
<<
/CRL 11 0 R
/Cert 12 0 R
>>
endobj
18 0 obj
<<
/5F44CF6F351DFD45FB62F3D0ED046408BC892797 17 0 R
>>
endobj
21 0 obj
<<
/VRI 18 0 R
/CRLs 19 0 R
/Certs 20 0 R
>>
我对如何编写证书和 CRL 流感到困惑。
15 0 obj
<<
/Length 1454
/Filter /FlateDecode
>>
stream
xÚ3hb0hbÅÄÈhÀÉƪÍÇÌ$ÅÊ`àcÈä2‡²° 3…Šˆ€8\¼®y%E¥Å%:žyÉz†ªÊ
ZbXd0%KW÷ýY¯’ó‚-ØÂÛ„OÏó½z•î ‰`®•® K-›2tÖ§^_8;xÉì¥Ó®~›.g9A'Õüê½—
ZbXd0%KW÷ýY¯’ó‚-ØÂÛ„OÏó½z•î ‰`®•® K-›2tÖ§^_8;xÉì¥Ó®~›.g9A'Õüê½—
endstream
endobj
16 0 obj
<<
/Length 1477
/Filter /FlateDecode
>>
stream
„kâR7Å41*!‡#8Íñ3 Ź˜@‰o=«‡çƒ#yë:X]r\~¼)/Ñmç×£¦³äsËê]ÓÕ_+µ¥$Ô¿¾ÜÏiÁÝT!¹ôi–Í9üÀŠ¸|
ìŒH¿GÓø^ú¿ÔVÜK–qõ†µ®“¸»Ý*Žh¾JzåU7c~÷•ÔêýK*îú®¹¸DcÁ³·NtV~Vóåíé5\‚&½|¶NäïŽ[K
î›NRZbXd0%KW÷ýY¯’ó‚-ØÂÛ„OÏó½z•î ‰`®•® K-›2tÖ§^_8;xÉì¥Ó®~›.g9A'Õüê½—›oÇ:ç-¶?
endstream
endobj
13 0 obj
<<
/Length 1240
/Filter /FlateDecode
>>
stream
%ŸwC[í2×¾Iej©úkŽ-:ݳÔ<¼a£ƒô/5›‡~zÒ•7ü9uãcfk?ËÅ`ßÃ:Èb—’‚ŸõÏÅ—¢]HçQ”9w(ÂB#í×g¥ìþè
^–F«š/r§š¿ì=#,^pëO€äú=RÎêð¦ÉŠ7or¼±Ëtë–x·˜§LÌŒŒ‹› Cd0€eùÿ³°03±>0P ñUY$
endstream
endobj
14 0 obj
<<
/Length 1159
/Filter /FlateDecode
>>
stream
4!>T‚êPpÎI,.V0Ò™@ûœºƒ=LÍš•ãˆ‘•¹‰‘Ÿ(ÎÅÔÄÈÈplŽ÷A¯¹7k/[‡O\
öe™¨îö£œ¶ä'¶ÌpžªweÞª[¡$¼ØÍþþtó[½xÉO4ÞZ¥ØŸ^g ø,mu„_Rz™_PÏê.||º¶*þîÝxv½"»êôó»ø%Ü%ý
endstream
endobj
请忽略以上流的长度和内容。我截断了它们,所以长度不再对应。溪流比这更大。
问题是我的 PDF 没有启用 LTV,我测试了一些场景,从中得出结论: 我的流没有以正确的方式写入。
我使用 WinCrypt.h 中的以下结构:
typedef struct _CERT_CONTEXT
DWORD dwCertEncodingType;
BYTE *pbCertEncoded;
DWORD cbCertEncoded;
PCERT_INFO pCertInfo;
HCERTSTORE hCertStore;
CERT_CONTEXT, *PCERT_CONTEXT;
typedef const CERT_CONTEXT *PCCERT_CONTEXT;
我通过它们并以这种方式获取字节:
PCCERT_CONTEXT cngContext = (PCCERT_CONTEXT)(*itChain);
ByteArray certBytes(cngContext->pbCertEncoded, (size_t)cngContext->cbCertEncoded);
然后,我只需在获得的字节上应用 FlateDecode 并将它们像流一样写入 PDF,正如您在第二个代码块中看到的那样。
我是否缺少任何步骤?比如转换之类的?我看到流应该是 BER 编码的。那么我应该将字节转换为 BER-Encoded 然后应用 FlateDecode 吗?
编辑:
你可以在这里找到My File
【问题讨论】:
您能否发布一个指向 PDF 文件的链接以供下载? 我在底部添加了 流已经被 DER 编码。问题是(可能)CRLs 数组中的流不是 CRL,而是 OCSP 响应。 Godaddy 的 CRL 列表(crl.godaddy.com/repository/mastergodaddy2issuing.crl,在 OCSP 响应之一中引用)为 118MB。 文档声明 CRL 流应进行 BER 编码。这会是个问题吗?作为记录,我看到 DER 是 BER 的一个子集。另外,为什么我会得到 OCSP 而不是 CRL .. 你能检查一下这篇文章吗?这也是我的,有人注意到与 OCSP 相同的事情。 ***.com/questions/60413766/… 在您的previous question 的两个答案中检查过,您的“CRL”根本不是 CRL。它们是包装在其他结构中的 OCSP 响应。因此,您可以随心所欲地使用编码,通过将这些结构 作为 CRLs 嵌入 DSS 中,您不会获得支持 LTV 的 PDF。而是提取实际的 OCSP 响应并将它们嵌入为 OCSP。 【参考方案1】:解决方案
问题在于我在 PDF 文件中写入的 CRL 流。
拥有来自每个证书的 CRL_CONTEXT 结构,我只需获取 pbCrlEncoded 变量并将其直接写入 CRL 的流中。
这似乎是正确的,但我注意到我在此结构的 CRL_INFO 中没有任何 CRL_ENTRY,因此编码的 BYTE 不包含任何已撤销证书的列表。 因此,发现证书有一个 URL,您可以从该 URL 下载更新的 CRL。您可以通过在 Windows 中打开 管理计算机证书 -> 找到您的证书并 打开证书 -> 详细信息 -> CRL分发点 -> URL = ".."。通过访问此 url,浏览器会自动下载 CRL 信息。您可以访问它并查看诸如下一次更新之类的信息,这是此列表有效的最后一天。在那之后,我假设您需要再次下载它以获得更新版本。您还可以查看已撤销证书的列表本身。
这是我需要放入 PDF 中的 CRL 流中的列表。 所以我找到了一种通过代码完成下载过程的方法。这是使用的代码的sn-p:
PCERT_CHAIN_ELEMENT chainElement; // this is the certification in the chain
pExtension = CertFindExtension(szOID_CRL_DIST_POINTS, chainElement->pCertContext->pCertInfo->cExtension, chainElement->pCertContext->pCertInfo->rgExtension);
if (!pExtension)
return ByteArray();
if (!CryptDecodeObject(X509_ASN_ENCODING, szOID_CRL_DIST_POINTS, pExtension->Value.pbData, pExtension->Value.cbData, 0, 0, &cbStructInfo))
return ByteArray();
if (!(pvStructInfo = LocalAlloc(LMEM_FIXED, cbStructInfo)))
return ByteArray();
CryptDecodeObject(X509_ASN_ENCODING, szOID_CRL_DIST_POINTS, pExtension->Value.pbData, pExtension->Value.cbData, 0, pvStructInfo, &cbStructInfo);
pInfo = (CRL_DIST_POINTS_INFO*)pvStructInfo;
Net::HttpRequest req;
Net::HttpRequestOptions ops;
ops.verb = Net::GET;
crllist = req.send(pInfo->rgDistPoint->DistPointName.FullName.rgAltEntry->pwszURL);
通过这种方式,我获得了在对它们应用 FlateDecode 后可以粘贴到 PDF 中的字节。 现在 PDF 已启用 LTV。
【讨论】:
虽然这当然可以做到,但并不是很好。正如在回答您之前的问题时已经讨论过的那样,CrlEncoded
缓冲区中实际上有一个包装的 OCSP 响应,因此您确实已经有了撤销信息,您只需正确提取并添加到 OCSP 部分。获取 CRL 会使用 PKI 基础架构创建额外的网络流量。此外,通常应该首选 OCSP 响应,因为它们通常比 CRL 更短(在某些 PKI 中非常短)并且更新。以上是关于如何对 PDF 中的证书吊销列表 (CRL) 流字节进行编码?的主要内容,如果未能解决你的问题,请参考以下文章
将证书吊销列表 (CRL) 文件从 .crl 转换为 .pem 扩展名 - Python 3
MIMEKIT Multipart Signed.Verify 如何禁用证书吊销列表检查?