SSL通信涉及两方的参与者,通常采用的模型是Client/Server 。如果我们开发Client端产品(比如浏览器),可能会和多方的Server产品对接 。那么问题来了,双方是如何知道对方使用了国密算法呢?这个问题非常重要,只有双方采用同样的加密标准,才能正常通信 。难道采用“天王盖地虎,宝塔镇河妖”的接头暗号?
在揭开这个谜底之前,我们先了解一下OID(Object Identifier,对象标志符),然后再聊一聊密码套件(Cipher Suite),就可以慢慢理解SSL通信双方是如何接上头的 。当然,整个SSL通信涉及到很多标准和协议,不是一篇文章能讲完的,所以本文只是抛砖引玉,探讨一些基本的概念 。可能对于资深人士而言,不值得一提,但我初入门时,也是摸索了好久,才慢慢能深入到细节 。
OIDOID是由ISO/IEC、ITU-T国际标准化组织上世纪80年代联合提出的标识机制,其野心很大,为任何类型的对象(包括实体对象、虚拟对象和组合对象)进行全球唯一命名 。通过唯一的编码,我们就可以识别出对象 。但要为所有对象进行唯一命名,其难度和工作量都很大,所以它采用了分层树形结构 。
OID对应于“OID树”或层次结构中的一个节点,该节点是使用ITU的OID标准X.660正式定义的 。树的根包含以下三个起点:
0:ITU-T1:ISO2:ITU-T/ISO联合发布
树中的每个节点都由一系列由句点分隔的整数表示 。比如,表示英特尔公司的OID如下所示:
1.3.6.1.4.1.343
对应于OID树中的含义:
1ISO1.3识别组织1.3.6美国国防部1.3.6.1互联网1.3.6.1.4私人1.3.6.1.4.1IANA企业编号1.3.6.1.4.1.343 英特尔公司
这里采用分而治之的策略,解决编码重复问题 。树中的每个节点均由分配机构控制,该机构可以在该节点下定义子节点,并为子节点委托分配机构 。
在上面的例子中,根节点“1”下的节点号由ISO分配,“1.3.6”下的节点由美国国防部分配,“1.3.6.1.4.1”下的节点由IANA分配,“1.3.6.1.4.1.343”下的节点由英特尔公司分配,依此类推 。只要有需求,可以一直往下分配下去,也解决了编码不够的问题 。
在实际应用中,ISO/IEC国际标准化机构维护顶层OID标签,各个国家负责该国家分支下的OID分配、注册和解析等工作,实现自我管理和维护 。
相应的,针对国密,国家密码局也定义了各类对象的标识符:
文章插图
国密相关OID定义
详细可参考 GM/T 0006-2012 这份标准 。
像"1.2.156.10197.1.100"这种字符串,人读起来比较直观,但对于计算机处理而言,却是大大的不方便,要知道字符串处理的效率非常低,所以在程序代码中,对OID又进行了一次编码 。
在GmSSL源码中,原始的OIDs定义在objects.txt文件中,在文件的尾部,我们可以看到国密的相关定义:
# GM/Tmember-body 156: ISO-CN: ISO CN Member BodyISO-CN 10197: osccaoscca 1: sm-schemesm-scheme 103 1: SSF33-ECB: ssf33-ecbsm-scheme 103 2: SSF33-CBC: ssf33-cbc!Cname ssf33-ofb128sm-scheme 103 3: SSF33-OFB: ssf33-ofb!Cname ssf33-cfb128sm-scheme 103 4: SSF33-CFB: ssf33-cfbsm-scheme 103 5: SSF33-CFB1: ssf33-cfb1sm-scheme 103 6: SSF33-CFB8: ssf33-cfb8sm-scheme 103 7: SSF33-CBC-mac: ssf33-cbc-macsm-scheme 102 1: SM1-ECB: sm1-ecbsm-scheme 102 2: SM1-CBC: sm1-cbc!Cname sm1-ofb128sm-scheme 102 3: SM1-OFB: sm1-ofb!Cname sm1-cfb128sm-scheme 102 4: SM1-CFB: sm1-cfbsm-scheme 102 5: SM1-CFB1: sm1-cfb1sm-scheme 102 6: SM1-CFB8: sm1-cfb8# SM2 OIDssm-scheme 301: sm2p256v1sm-scheme 301 1: sm2signsm-scheme 301 2: sm2exchangesm-scheme 301 3: sm2encrypt
【SSL 通信双方如何判断对方采用了国密?】通过 objects.pl 脚本,生成 obj_data.h文件,这个才是在代码中使用到的OID编码 。boringssl也类似,不过其采用了 go 语言编写的转换脚本 。
密码套件仅仅定义了OID还不够,因为国密并不是一个单一的标准,包含了很多加密、解密、哈希等算法,可以形成很多种组合,不能简单假定对方采用了国密就可以建立通信 。
在SSL通信开始,双方就需要进行协商,采用何种算法进行通信 。这里需要重点理解密码套件(CipherSuite)的概念 。
密码套件是一系列密码学算法的组合,主要包含多个密码学算法:
- 身份验证算法 。
- 密码协商算法 。
- 加密算法或者加密模式 。
- HMAC算法的加密基元 。
- PRF算法的加密基元,需要注意的是,不同的TLS/SSL协议版本、密码套件,PRF算法最终使用的加密基元和HMAC算法使用的加密基元是不一样的 。
推荐阅读
- 详解 Linux 虚拟机的网络通信原理
- LPWAN 低功耗广域网技术 - Wize简介
- 数据通信 交换机原理
- 什么是NFC?近场通信用途,芯片,标签和阅读器介绍
- 串口通信RS232的基本接法,原来这么简单,今天终于弄明白了
- 数据通信 路由器原理
- 通信运营商|第四大运营商来了!中国广电经营范围新增5G通信
- 进程间的五种通信方式介绍
- 制作自己的SSL证书
- 通信行程卡可以精确到什么位置 行程卡能定位到区吗