编者按:为积极贯彻落实《密码法》,秦商密隆重推出《深入浅出》和《自己动手》原创技术科普系列,旨在普及商用密码知识,培养密码应用创新人才。上一篇讲了如何将数字证书从证书链中剥离出来并校验链关系的正确性、真实性。而本篇则介绍一下怎样采用CRL和OCSP在线请求为主、字段合规性判断为辅的方式验证根证书是否可信,从而判断整个链是否可信。本系列文章旨在抛砖引玉,如有不足之处,请各位专家不吝珠玉!
How:如何实现提出的需求——数字证书合规性验证工具
上一章将数字证书从证书链中剥离出来并校验链关系的正确性、真实性。然而链本身的真实性需要依赖根证书的真实性,我的想法是采用CRL和OCSP在线请求为主、字段合规性判断为辅的方式验证根证书是否可信,从而判断整个链是否可信、真实;密评人员可以以此为依据评估信息系统密码技术的应用是否合规、有效。
(1)证书撤销状态、证书有效性在线请求
1.从证书中读取CRL列表下载地址,把最新的CRL列表文件下载下来,然后在CRL列表中匹配本数字证书的序列号,若没有出现,则CRL检验通过
在证书中读取OCSP请求地址,将响应状态码翻译成字符。OCSP响应状态共有3种:Good (良好): 证书是有效的、Revoked (已废除): 证书已被吊销,不再有效、Unknown (未知): OCSP服务器无法确定证书的状态。
构造一个OCSP请求,在验证证书OCSP状态的时候还需要提供一个发行者(issuer)证书,而不仅仅是一个单独的目标证书。
(2)字段编码、格式合规性验证
3.证书的序列号长度应不大于20个8位字节,应为唯一正整数
4.证书的签名算法OID应为1.2.156.10197.1.501 (sm3Withsm2)
5.证书的有效期编码规则为,在2049年之前(包括2049年)必须将该时间编码为UTCTime类型,在2050年之后,编码为GeneralizedTime类型,生效期必须早于失效期。
6.证书中必须存在颁发机构密钥标识符扩展项,其中的值应与颁发者证书的使用者密钥标识符中的值一致。
7.名证书的密钥用法中应标识且只应标识数字签名digitalSignature和防抵赖nonRepudiation两项,加密证书的密钥用法中应标识且只应标识密钥加密keyEncipherment、数据加密dataEncipherment和密钥。
8.证书中必须存在CRL发布点扩展项,根据CRL发布点扩展项中的URL,应可以下载到对应的CRL文件,CRL应符合X.509 V2标准,其颁发者应与用户证书的颁发者一致,且CRL中的签名值应能使用证书的颁发者证书进行验证。
可以采用python的pyOpenssl库和X509库对与证书指定字段进行读取、后自行按照《GM/T 0015-2012 基于SM2密码算法的数字证书格式》中的要求进行匹配校验。
想要使用第三方库函数读取证书,则将证书统一整理成PEM。
3.算法OID核查:国密证书目前唯一的签名算法为SM3 With SM2,即:1.2.516.10197.1.501。
5.证书时间检查:是否过期,时间编码格式是否正确?{2049年以前使用UTC编码,2049年之后使用GeneralizedTime}
(3)证书签名值验证
由于Windows自带的加密扩展外壳目前不能够对SM2证书进行签名验证,故不可通过像验证RSA证书那般实现:证书安装 => 链自动验证。故需要验证工具能够提取证书的[tbs基本证书域][签名值域]以及上级CA证书的公钥。使用SM2算法模块,依据SM2签名算法标准,在待签明文前添加hash(ENTL || ID || a || b || x_P || y_P)
1.使用ASN.1查看器打开待验证的证书:将基本证书域的Hex流复制下来作为待验签的原文值。保存在“input/2.基本证书域”下;
2.使用ASN.1查看器将签名值域的Hex流复制下来作为待验签的签名值。保存在“input/3.签名值域”下;
3.打开目标证书的上一级CA证书,复制上一级CA证书的公钥,保存在“input/1.上一级CA公钥”下;
![自己动手 | 从零开始制作密评工具(二) 自己动手 | 从零开始制作密评工具(二)]()
这个模块是我在制作[国密证书全自动验证工具]时的副产物,当时顺手编译了下,故如今已经没有源代码存留了。我简单介绍一下实现原理:
基本证书域(tbscertificate):版本号、序列号、签名算法、颁发者、有效日期、主体、主体公钥信息、颁发者唯一标识、扩展项——全部作为代签原文
签名值域(signatureValue):已知签名值是R点和S点的TLV值;根据GM/T 0015-2012,签名值的Type为0x02一个字节表示,又知R点和S点的长度分别都为32byte,故而坐标点实际的Length的值为0x20;当Length长度为0x21时,那么L值后方的00即不能够被视为坐标点的值;如下图所示:
我们需要的是R,S点TLV值中的V,故可以使用python脚本直接先截取签名值域(signatureValue)的后64位Hex——S点的Value值。后对剩下的签名值域部分内容进行检查,如果末尾是“00”,那么删除末尾6位,即3字节(02 21 00),否则删除末尾4位,即2字节(02 20)的R点的TL值;对删除完成后的签名值域的剩下后64位进行截取,便是R点的坐标值。
SM2签名验证:根据《GM/T 0003.2 SM2椭圆曲线公钥密码算法第2部分:数字签名算法》5.5节,签名时应该在代签消息前增加:hash(ENTL || ID || a || b || x_P || y_P)的用户标识信息,默认的用户标识为:1234567812345678(底层走的是UTF8编码,
byte表示为:0x31323334353637383132333435363738),
对应的ENTL = "0x0080"(ENTL用两个字节表示) # 123456781234567812345678的长度为:16 * 8 = 128个bit即为0x80长度。
Z = hash(ENTL || ID || a || b || x_P || y_P)->{“||”在代码操作中直接作为字符串拼接即可}
参与杂凑运算的内容整体为Z + M(原文);故校验时应当将Z + 基本证书域进行拼接,作为待验签的原文。
——SM2功能调用的是python gmssl V3.2.1
这是我们的SSL握手报文验签模块和证书解析、合规性校验界面(建设中):供密评人员从wireshark中手动提取签名值、加解密证书、加解密证书长度,自定义用户ID,对签名真实性进行验证。
![自己动手 | 从零开始制作密评工具(二) 自己动手 | 从零开始制作密评工具(二)]()
(END)
原文始发于微信公众号(网络安全等保与关保):自己动手 | 从零开始制作密评工具(二)
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
点赞
https://cn-sec.com/archives/2470224.html
复制链接
复制链接
-
左青龙
- 微信扫一扫
-
-
右白虎
- 微信扫一扫
-
评论