3. EST协议消息格式:基于PKCS#10的CSR、基于CMS的响应封装、HTTP头与Content-Type定义、JSON与二进制编码对比

EST协议的消息格式,说白了就是客户端和服务端之间怎么“说话”。你发一个证书请求,它得有个固定的格式;它回你一个证书,也得有个标准的包装。我刚开始接触EST时,觉得不就是发个请求收个响应嘛,结果一看抓包数据,差点没晕过去——又是PKCS#10,又是CMS,还有一堆HTTP头。今天咱们就把这些一层层剥开。

3.1 基于PKCS#10的CSR:证书请求的“标准信封”

EST协议里,客户端申请证书时,用的就是PKCS#10格式。PKCS#10是公钥密码学标准系列里的一个,专门用来封装证书签名请求(CSR)。你想想看,你要向CA证明“我是我”,总得把你的公钥、身份信息、签名打包在一起吧?PKCS#10就是干这个的。

一个典型的PKCS#10结构包含三部分:

  • 证书请求信息:包括版本号、主题名(DN)、公钥信息。
  • 签名算法标识:告诉CA你用的是SHA256WithRSA还是ECDSA。
  • 签名值:用你的私钥对请求信息签名,证明你拥有对应的私钥。

我记得有一次,一个同事死活发不出EST请求,抓包一看,CSR里主题名写错了格式,CA直接拒收。嗯,这里要注意:主题名必须用LDAP格式,比如 CN=mydevice, O=MyCompany, C=CN,别写成逗号分隔的字符串。

核心要点:PKCS#10是EST请求的“身份证”,格式必须严格遵循ASN.1 DER编码。CA解析失败时,90%的问题出在主题名或公钥编码上。

3.2 基于CMS的响应封装:CA的“加密快递”

CA收到你的CSR后,会签发证书。但EST不会直接把裸证书扔回来,而是用CMS(Cryptographic Message Syntax)包一层。CMS是PKCS#7的升级版,支持数字签名、加密、摘要等多种操作。

EST响应里,CMS主要用来做两件事:

  • 封装证书链:把服务器证书、中间CA证书、根证书打包成一个CMS SignedData结构。
  • 提供完整性保护:CA用自己的私钥对响应签名,客户端可以验证响应是否被篡改。

你可能会问:为什么不用裸证书?我刚开始也有这个疑问。后来在项目里遇到一个场景——客户端需要同时拿到证书链和CRL(证书吊销列表),如果分开发送,网络丢包或乱序就麻烦了。CMS一次打包,客户端一次解析,省心多了。

个人经验:解析CMS响应时,记得检查 eContentType 字段。如果是 id-smime-ct-pkcs7,说明里面是证书链;如果是 id-smime-ct-certsOnly,说明只有裸证书。我踩过这个坑,解析错了直接报错。

3.3 HTTP头与Content-Type定义:EST的“通信协议”

EST跑在HTTP之上,所以请求和响应都得遵守HTTP的规矩。但EST定义了自己的一套Content-Type,用来区分不同的消息类型。

常用的Content-Type有这些:

操作 请求Content-Type 响应Content-Type
简单证书申请 application/pkcs10 application/pkcs7-mime
带密钥更新的证书申请 application/pkcs10 application/pkcs7-mime
CA证书检索 无(GET请求) application/pkix-cert
CRL检索 无(GET请求) application/pkix-crl

除了Content-Type,HTTP头里还有几个关键字段:

  • Content-Transfer-Encoding:通常用 base64,因为PKCS#10和CMS都是二进制数据,HTTP传输需要转成文本。
  • Content-Length:明确告诉对方数据有多长,避免粘包。
  • Authorization:EST支持HTTP Basic认证或TLS客户端证书认证,这个头用来传递凭证。

避坑指南:我曾经遇到一个CA服务器,它要求Content-Type必须严格小写,否则返回415错误。所以,建议统一用小写,比如 application/pkcs10 而不是 Application/PKCS10。

3.4 JSON与二进制编码对比:选哪个?

EST标准里,消息格式默认是二进制DER编码。但有些场景下,JSON格式更友好——比如在物联网设备上,内存小、CPU弱,解析DER太费劲。所以,EST也支持JSON编码,但有个前提:CA和客户端都得支持。

我整理了一个对比表,方便你选型:

特性 二进制DER编码 JSON编码
数据大小 小(约1KB的CSR) 大(约2-3KB,含Base64)
解析复杂度 高(需要ASN.1库) 低(JSON解析器遍地都是)
可读性 差(二进制乱码) 好(人类可读)
标准支持 RFC 7030强制要求 可选(RFC 7030扩展)
适用场景 企业级PKI、高性能场景 物联网、调试阶段

我个人习惯是:生产环境用DER,调试环境用JSON。为什么呢?因为DER编码紧凑,网络传输快;JSON虽然大一点,但出问题时一眼就能看出字段对不对。比如有一次,我调试一个EST客户端,CSR里的公钥长度写错了,用DER抓包根本看不出来,换成JSON一看,"publicKeyLength": 2047,明显少了一位。

建议:如果你的设备支持,可以在HTTP头里加一个 Accept: application/json,看CA是否返回JSON格式。如果不支持,就老老实实用DER。

3.5 整体消息流程:一张图看懂

说了这么多,咱们用一张SVG图把EST的消息流转串起来。从客户端发起CSR,到CA返回CMS封装的证书,每一步的格式和编码都标清楚了。

EST消息格式与编码流程 EST消息格式与编码流程 客户端 生成PKCS#10 CSR (DER或JSON编码) HTTP POST请求 Content-Type: application/pkcs10 CA服务器 验证CSR签名 签发证书 CMS封装响应 Content-Type: application/pkcs7-mime TLS握手 CSR (DER/JSON) CMS响应 (DER/JSON) 编码选择说明 生产环境推荐DER编码:体积小、解析快、标准强制支持 调试环境可用JSON编码:可读性强、便于排查字段错误

这张图把EST的消息流转拆成了四步:客户端生成CSR、通过HTTP POST发送、CA验证并签发证书、用CMS封装后返回。每一步的编码格式和Content-Type都标出来了,你对照着看,应该能理清整个流程。

3.6 实战中的编码选择建议

最后,我根据实际项目经验,给你几个编码选择的建议:

  • 如果你在做企业级PKI:用DER编码,兼容性最好,所有CA都支持。
  • 如果你在做物联网设备:优先用JSON编码,设备端解析压力小。但记得先确认CA是否支持。
  • 如果你在调试:先用JSON,等调通了再切回DER。我曾经用JSON定位过一个CSR签名算法不匹配的问题,换成DER抓包根本看不出来。
  • 如果你不确定CA支持什么:发一个带 Accept: application/json 的请求试试,如果返回406,就老老实实用DER。

小技巧:用Wireshark抓EST流量时,可以设置 Content-Type 过滤条件,比如 http.content_type == "application/pkcs10",快速定位请求包。我每次调试都这么干,省了不少时间。