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的消息流转拆成了四步:客户端生成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",快速定位请求包。我每次调试都这么干,省了不少时间。