国密ssl协议
- 国密ssl协议(gmssl)指的是采用国密算法,符合国密标准的安全传输协议。简而言之,国密ssl就是ssl/tls协议的国密版本。
- 国密ssl是作为密码行业标准存在的,定义在ssl vpn产品的技术规范《gm/t 0024-2014 ssl vpn技术规范》中,于2012年3月发布并实施。
- tls协议定义有三个版本号,为0x0301、0x0302、0x0303,分别对应tls 1.0、1.1、1.2。国密ssl协议为了避免冲突,选择了0x0101。国密ssl协议规范是tls 1.1和tls 1.2的混合体,大部分情况下参考tls 1.1,少数地方又参考了tls 1.2。
tlcp协议
- tlcp协议(transport layer cryptography protocol)作为独立的国家标准,被定义于《gb/t 38636-2020 信息安全技术 传输层密码协议》中,于2020年4月发布,在2020年11月实施。
- tlcp协议在国密ssl协议的基础上进一步规范化和标准化,全面采用了国密算法,并可能对原有协议的某些方面进行了优化和扩展,以更好地适应现代网络环境的安全挑战和合规要求。
国密ssl协议与tlcp协议异同
- 国密ssl协议是密码行业标准,tlcp协议为独立的国家标准。
- 国密ssl协议可以被视为tlcp协议的前身或基础版本,主要应用于ssl vpn领域,侧重于在特定应用场景中实现国密算法的支持。tlcp协议是国密ssl协议的升级版和标准化成果,不仅限于ssl vpn,而是作为一种通用的传输层安全协议,更加正式和广泛地适用于各类网络服务,完全符合中国最新的密码技术和信息安全政策。
- 国密ssl协议和tlcp协议版本号都为 0x0101,具体区别可以查看对应的技术规范。实际使用时,不用关注两者的区别,可以都看作国密ssl协议,后文也统称为国密ssl协议。
国密ssl协议与标准ssl/tls协议
- 标准ssl/tls协议使用的密码协商算法,身份验证算法,加密算法和mac算法使用的都是国际算法,如密钥协商算法使用ecdh、身份验证算法使用rsa、加密算法使用aes、摘要算法使用sha256等。国密ssl协议在标准ssl/tls协议中加入了国密算法,如密钥协商和身份验证加入了sm2算法,加密算法加入了sm4,摘要算法加入了sm3。
- 虽然国密ssl协议作为密码行业标准于2012年就发布实施,且于2020年上升为国家标准,但目前大部分的https网站还是使用的标准ssl/tls协议。并且主流浏览器,如google chrome、microsoft edge、mozilla firefox等,不支持国密ssl协议。目前只有部分国产浏览器对国密ssl协议进行了支持,如360安全浏览器、奇安信浏览器等。
- 目前国密ssl协议主要还是用于安全性要求较高的领域,如政府、银行、科研机构等。
国密ssl协议结构
- 国密ssl协议与标准ssl/tls协议一样都位于应用层协议和传输层协议(tcp协议)之间,分为两层,接近应用层协议的高层协议是握手协议(tls handshaking protocols),接近tcp协议的底层协议是记录层协议(tls record protocol)。结构如下
记录层协议
- 记录层协议会封装所有的握手协议,记录层协议有固定的消息头格式。分别为消息类型、版本号和消息长度。
- 可以用wireshark抓个包看下,国密ssl协议显示的版本号都为0x0101。
握手协议
- 握手协议由4个子协议构成,分别是握手子协议(也称为握手协议)、警告协议、密码切换协议和应用层协议。这四个协议跟tcp和udp协议一样,是并行的关系。
- 握手协议(tls handshaking protocols)
-
ssl协议中最重要的握手子协议,后面会重点介绍。后文提到的ssl握手协议都指此子协议。结构如下
-
-
用wireshark抓包看下,client hello就属于握手协议
-
-
- 警告协议(alert protocol)
- 警告协议用于关闭连接的通知以及对整个连接过程中出现的错误进行报警。
- 警告协议结构如下
-
struct{ alertlevel level; //警告错误级别 alertdescription description; //警告协议的详细描述信息 } alert; // 错误级别结构 enum{ warning(1), fatal(2), (255) } alertlevel; // 详细描述信息 enum { close_notify(0), //正常关闭通知,表示会话正常结束。 unexpected_message(10) , //表示收到了不适当或未预期的消息类型 bad_record_mac(20), // 记录层的消息认证码(mac)验证失败 decryption_failed_reserved(21), //解密接收到的数据时出现了问题 record_overflow(22), //接收到的数据记录长度超过了协议所规定的最大长度,违反了协议的格式要求 decompression_failure(30), //解压缩操作失败 handshake_failure(40), // 握手过程中发生错误,无法完成握手 no_certificate_reserved(41), //未接收到有效证书 bad_certificate(42), //证书无效或格式错误 unsupported_certificate(43), //对端提供的证书不受本地信任存储支持 certificate_revoked(44), //证书已被吊销 certificate_expired(45), //证书已过期 certificate_unknown(46), //无法验证对端提供的证书的有效性 illegal_parameter(47), //在握手消息中遇到了非法或不支持的参数 unknown_ca(48), //验证过程中使用的证书颁发机构未知 access_denied(49), //访问被拒绝 decode_error(50), //解码消息时出错 decrypt_error(51) , //解密消息时出错 export_restriction_reserved(60), protocol_version(70), //不支持的协议版本 insufficient_security(71), //安全度低于最低要求 internal_error(80), //发生了内部错误 user_canceled(90) , // 用户主动取消了相关操作 no_renegotiation(100) , //客户端或服务器拒绝重新协商请求时产生 unsupported_extension(110) , //一方接收到的ssl/tls扩展不被另一方支持或理解 (255) } alertdescription;
- 结构图示
- 警告协议中最常见的是 handshake_failure,抓包看下
- 密码切换协议(change cipher spec protocol)
- change cipher spec 协议的作用就是通知tls记录层协议其加密所需的密钥块已经准备好了,tls记录层协议就可以对应用层协议进行加密保护了。
- 该消息占一个字节。
- 应用层协议(application data protocol)
- 应用层协议就是tls记录层协议的上层协议,包括http、ftp、smtp等应用协议。tls记录层协议密码学保护的主要信息就是应用层协议数据。
国密ssl握手协议握手图示
- 虚线是双向认证时需要额外发送的消息。
- 整体抓包截图
- 可以访问这个网站 https://www.wotrus.com 进行抓包。
- 需要注意的是必须使用支持国密ssl协议的浏览器,可以下载奇安信浏览器或者360安全浏览器。
- 协议这一栏显示的是gmsslv1,不同wireshark版本可能显示的名字不一样,也可能显示tlcp,这个主要是不同版本对国密ssl协议的解析名称不一样。只要版本号是 0x0101,就是国密ssl协议。
国密ssl握手协议详解
结构定义
- 握手协议用于协商安全参数,握手协议的消息通过记录层协议传输,结构定义如下
-
struct{ handshaketype msg_type; uint24 length; select(msg_type){ case client_hello; clienthello; case server_hello; serverhello; case certificate; certificate; case server_key_exchange; serverkeyexchange; case certificate_request; certificaterequest; case server_hello_done; serverhellodone; case certificate_verify; certificateverify; case client_key_exchange; clientkeyexchange; case finished;finished; }body; }handshake;
-
- 握手消息类型定义如下
-
enum{ client_hello(1), server_hello(2), certificate(11), server_key_exchange(12), certificate_request(13), server_hello_done(14), certificate_verify(15), client_key_exchange(16), finished(20), (255) } handshaketype;
-
- 握手协议消息应按规定的流程顺序进行发送,否则将会导致致命的错误。
client hello
- client hello 消息作为握手协议的第一条消息,客户端发送client hello消息后,等待服务端响应server hello消息。
- client hello 消息结构定义如下
-
struct{ protocolversion client_version; random random; sessionid session_id; ciphersuite cipher_suites<2..2^16-1>; compressionmethod compression_methods<1..2^8-1>; } clienthello;
-
- client_version
- 客户端支持的ssl协议版本,国密ssl协议统一使用 0x0101
- random
- 客户端产生的随机信息,其内容包括时钟c和随机数,结构定义如下
-
struct{ uint32 gmt_unix_time; opaque randon_bytes[28]; }random;
-
- gmt_unix_time为标准unix 32位格式表示的发送者时钟,其值为从格林威治时间的1970年1月1日零点倒当前时间的秒数
- randon_bytes 为28个字节的随机数
- 客户端产生的随机信息,其内容包括时钟c和随机数,结构定义如下
- session_id
- 客户端在连接中使用的会话标识,定义为
-
opaque sessionid<0..32>
-
- 客户端在连接中使用的会话标识,定义为
- cipher_suites
- 技术规范《gm/t 0024-2014 ssl vpn技术规范》中,定义了国密ssl协议使用的加密套件如下
- 本标准中实现ecc和ecdhe的算法为sm2; 实现ibc和ibsdh的算法为sm9;
- 技术规范《gb/t 38636-2020 信息安全技术 传输层密码协议》中,对《gm/t 0024-2014 ssl vpn技术规范》中加密套件做了修改,具体如下
- 本标准中实现ecc和ecdhe的算法为sm2; 实现ibc和ibsdh的算法为sm9;
- 密码套件定义如下
-
uint8 ciphersuite[2];
-
- 每个密码套件包括一个密钥交换算法、一个加密算法及密钥长度和一个校验算法。
- 技术规范《gm/t 0024-2014 ssl vpn技术规范》中,定义了国密ssl协议使用的加密套件如下
- compression_methods
- 客户端所支持的压缩算法列表
- 抓包看下,可以看到密码套件列表中有好几个unkonwn,这是我使用的wireshark版本太旧,无法解析出《gb/t 38636-2020》中新增的密码套件,从上表可知,0xe053就是ecc_sm4_gcm_sm3密码套件。
server hello
- 客户端发送client hello消息后,服务端从client hello消息的密码套件列表中找到匹配的密码套件后进行回应。
- server hello 消息结构定义如下
-
struct{ protocolversion server_version; random random; sessionid session_id; ciphersuite cipher_suites; compressionmethod compression_methods; } serverhello;
-
- server_version
- 服务端支持的ssl协议版本,国密ssl协议统一使用 0x0101
- random
- 服务端产生的随机数
- session_id
- 服务端使用的会话标识
- cipher_suites
- 服务端从客户端的密码套件列表中选择一个支持的密码套件
- compression_methods
- 服务端从客户端hello消息中选取的一个压缩算法
- 抓包图示,服务端从客户端支持的密码套件中选择了 ecc_sm4_gcm_sm3 密码套件,并发送了服务端随机数等信息。
server certificate
- 本消息为服务端证书消息。
- 服务端应发送一个服务端证书消息给客户端,该消息总是紧跟在服务端hello消息之后。
- 当选中的密码套件使用rsa或ecc或ecdhe算法时,本消息的内容为服务端的签名证书和加密证书。
- 当选中的密码套件使用ibc或ibsdh算法时,本消息的内容为服务端标识和ibc公共参数,用于客户端与服务端协商ibc公开参数。
- 证书消息结构
-
opaque asn.1cert<1..2^24-1>; struct{ asn.1cert certificate<0..2^24-1>; } cerificate;
- 服务端证书:签名证书在前,加密证书在后。
-
- ibc标识及公共参数结构
-
opaque asn.1ibcparam<1..2^24-1>; struct{ opaque ibc_id<1..2^16-1>; //服务端标识 asn.1ibcparam ibc_parameter; //ibc公共参数,遵循asn.1编码 } cerificate;
-
- 抓包图示,这里和标准tls协议有区别,标准tls协议只需要发送一张证书,但国密ssl协议需要发送签名和加密证书。下面两张证书是对应的证书链。
server key exchange
- 本消息为服务端密钥交换信息。本消息传送的信息用于客户端计算产生48字节的预主密钥。
- 消息结构定义如下
-
enum{ ecdhe, ecc, ibsdh, ibc, rsa } keyexchangealgorithm; struct{ select(keyexchangealgorithm){ case ecdhe: serverecdheparams params; //服务端密钥交换参数,使用sm2算法时,服务端公钥不需要交换,客户端从服务端加密证书中获取 digitally-signed struct { opaque client_random[32]; opaque server_random[32]; serverecdheparams params; } signed_params; case ecc: digitally-signed struct { opaque client_random[32]; opaque server_random[32]; opaque asn.1cert<1..2^24-1>; } signed_params; case ibsdh: serveribsdhparams params; //使用ibsdh算法时,服务端的密钥交换参数 digitally-signed struct { opaque client_random[32]; opaque server_random[32]; serveribsdhparams params; } signed_params; case ibc: serveribcparams params; //使用ibc算法时,服务端的密钥交换参数 digitally-signed struct { opaque client_random[32]; opaque server_random[32]; serveribcparams params; opaque ibcencryptionkey[1024]; // 使用ibc算法时,服务端的加密公钥 } signed_params; case rsa: digitally-signed struct { opaque client_random[32]; opaque server_random[32]; opaque asn.1cert<1..2^24-1>; } signed_params; } } serverkeyexchange;
-
- signed_params
- 当密钥交换方式为ecdhe、ibsdh和ibc时,signed_params是服务端对双方随机数和服务端密钥交换参数的签名
- 当密钥交换方式为ecc和rsa时,signed_params是服务端对双方随机数和服务端加密证书的签名
- 抓包图示
certiticate request
- 本消息为证书请求消息。双向认证时有此消息。
- 如果服务端要求认证客户端,则应发送此消息,要求客户端发送自己的证书。
- 消息结构定义如下
-
struct{ clientcertificatetype certificate_types<1..2^8-1>; distinguishedname certificate_authorities<0..2^16-1>; }certificaterequest;
-
- certificate_types
- 要求客户端提供的证书类型列表
-
enum{ rsa_sign(1), ecdsa_sign(64), ibc_params(80),(255) } clientcertificatetype;
-
- 要求客户端提供的证书类型列表
- certificate_authoritiesc
- 如果clientcertificatetype是ibc_params,本字段的内容是ibc密钥管理中心的信任域名列表。否则是服务端信任的ca的证书dn列表,包括根ca或二级ca的dn。
- 定义如下
-
opaque distinguishedname<1..2^16-1>
-
- 抓包图示
serverhellodone
- 表示握手过程的hello消息阶段完成。发送完该消息后服务端会等待客户端的响应消息。
- 客户端接收道服务端的hello完成消息之后,应校验服务端证书是否有效,并校验服务端的hello消息参数是否可以接受。
- 抓包图示
client certificate
- 本消息为客户端证书消息。如果服务端请求客户端证书,客户端需要发送此消息。
- 该消息结构和 server certificate 消息一致。
- 按照规范,客户端也需要发送签名和加密两张证书,但在rsa和ecc两种密钥协商模式下,客户端加密证书在后续握手时用不到,因此实际使用时,客户端只发送签名证书,也可以握手成功,除非服务端作了强制校验。
- 握手图示,可以看到,客户端只发送了签名证书和对应的证书链,后续握手也是成功的。
client key exchange
- 本消息为客户端密钥交换消息。
- 如果服务端请求客户端证书,本消息紧跟于客户端证书消息之后,否则本消息是客户端接收道服务端hello完成消息后发送的第一条消息。
- 如果密钥交换算法使用rsa、ecc和ibc算法,本消息中包含预主密钥,该预主密钥由客户端产生,采用服务端的加密公钥进行加密。当服务端收到加密后的预主密钥后,利用相应的私钥进行解密,获取预主密钥明文。如果是ibc算法,客户端利用获取的服务端标识和ibc公开参数,产生服务端公钥。如果密钥交换算法使用ecdhe算法或ibsdh算法,本消息中包含计算预主密钥的客户端密钥交换参数。
- 客户端密钥交换消息结构定义如下
-
struct{ select(keyexchangealorithm){ case ecdhe: opaque clientecdheparams<1..2^16 - 1>; case ibsdh opaque clientibsdhparams<1..2^16 - 1>; case ecc: opaque eccencryptedpremastersecret<0..2^16 - 1>; case ibc: opaque ibcencryptedpremastersecret<0..2^16 - 1>; case rsa: opaque rsaencryptedpremastersecret<0..2^16 - 1>; } exchange_keys; } clientkeyexchange;
-
- clientecdheparams
- 使用ecdhe算法时,要求客户端发送证书。结构如下
-
struct{ ecparamters curve_params; ecpoint public; } clientecdheparams;
-
- 使用ecdhe算法时,要求客户端发送证书。结构如下
- clientibsdhparams
- 使用ibsdh算法时,客户端的密钥交换参数。
- eccencryptedpremastersecret
- 使用ecc加密算法时,用服务端加密公钥加密的预主密钥。
- ibcencryptedpremastersecret
- 使用ibc加密算法时,用服务端公钥加密的预主密钥。
- rsaencryptedpremastersecret
- 使用rsa加密算法时,用服务端加密公钥加密的预主密钥。
- 预主密钥的数据结构如下
-
struct { protocolversion client_version; // 客户端支持的版本号 opaque random[46]; // 46字节的随机数 } premastersecret;
-
- 握手图示
certificate verify
- 本消息为证书校验消息。
- 本消息用于鉴别客户端是否为证书的合法持有者,只有client certificate消息发送时才发送此消息,紧跟在客户端密钥交换消息之后
- 证书校验消息结构定义如下
-
struct{ signature signature; } certificateverify; enum{ rsa_sha256, rsa_sm3, ecc_sm3, ibc_sm3 } signaturealgorithm; struct{ select(signaturealgorithm){ case rsa_sha256: digitally-signed struct{ opaque sha256_hash[20]; }; case rsa_sm3: digitally-signed struct{ opaque sm3_hash[32]; }; case ecc_sm3: // 当ecc为sm2算法时,使用这个套件 digitally-signed struct{ opaque sm3_hash[32]; }; case ibs_sm3: digitally-signed struct{ opaque sm3_hash[32]; }; } } signature;
-
- sm3_hash和sha256_hash是指hash运算的结果,运算的内容是自客户端hello消息开始直到本消息为止的所有与握手有关的消息,包括握手消息的类型和长度域。
- 握手图示
finished
- 本消息为握手结束消息
- 服务端和客户端各自在密码规格变更消息之后发送本消息,用于验证密钥交换过程是否成功,并校验握手过程的完整性。
- 本消息用本次握手过程协商出的算法和密钥保护。
- 本消息的接收方应检验消息内容的正确性。一旦一方发送了握手结束消息,并且接收到了对方的握手结束消息并通过校验,就可以使用该连接进行数据安全传输。
- 握手结束消息数据结构如下
-
struct{ opaque verify_data[12]; //校验数据 } finished;
-
- verify_data 为校验数据,产生方法如下
-
prf(master_secret, finished_label, sm3(handshake_messages))[0..11]
- finished_label: 对于由客户端发送的结束消息,该标签是字符串 client finished。对于服务端,该标签是 server finished。
- handshake_messages: 自客户端hello消息开始直到本消息为止的所有与握手有关的消息,包括握手消息的类型和长度域。
-
国密nginx服务器部署
- 国密ssl实验室:此网站中有介绍如何部署国密nginx服务器的教程。
- 国密nginx部署包 : 我参考此网站将所需的安装包都下载上传到gitee了,需要的可自行下载,并参考以下步骤部署。
zlib安装
- 解压zlib.tar.gz
- 进入zlib目录, 分别执行以下命令
pcre安装
- 解压pcre-8.45.zip
- 进入pcre目录, 分别执行以下命令
国密版本openssl安装
- 解压openssl到指定目录
国密版本nginx安装与配置
- 解压 nginx-1.24.0.tar.gz
- 进入nginx目录
- 将auto/lib/openssl/conf文件中 $openssl/.openssl/全部修改为 $openssl/并保存
- 然后分别执行以下命令编译安装
- 默认会安装到这个目录下 /usr/local/nginx
- 将 sm2.smallwolf.zip 拷贝到 /usr/local/nginx/conf 目录下并解压
- 修改nginx配置文件 /usr/local/nginx/conf/nginx.conf 中的server项
-
server { listen 443 ssl; server_name localhost; ssl_protocols tlsv1 tlsv1.1 tlsv1.2; ssl_ciphers ecdhe-rsa-aes128-gcm-sha256:aes128-sha:des-cbc3-sha:ecc-sm4-cbc-sm3:ecc-sm4-gcm-sm3; ssl_verify_client off; ssl_certificate sm2.smallwolf.sig.crt.pem; ssl_certificate_key sm2.smallwolf.sig.key.pem; ssl_certificate sm2.smallwolf.enc.crt.pem; ssl_certificate_key sm2.smallwolf.enc.key.pem; location / { root html; index index.html index.htm; } }
- 然后进入 /usr/local/nginx/sbin目录启动nginx
国密浏览器安装
- 常用浏览器是不支持访问国密web服务器的,双击安装奇安信浏览器 qaxbrowser_1.1.45335.52.exe。也可以去奇安信官网去下载浏览器进行安装。
- 安装完成后,打开浏览器设置,选择高级设置,然后勾选启动国密ssl通信。
- 设置完成后,重启浏览器。访问搭建好的nginx服务器。
- 可以看到,站点证书已经是国密证书了。
国密版本wireshark安装
- 那么有没有走国密ssl通道呢,安装个国密版本的wireshark抓包看下。
- 双击安装 wireshark-win32-2.9.0-gm.3.exe。
- 抓包可以看到,使用的ssl协议确实是国密ssl协议。
参考
- 《gm/t 0024-2014 ssl vpn技术规范》
- 《gb/t 38636-2020 信息安全技术 传输层密码协议(tlcp)》
- 国密ssl实验室
- 关于tlcp
- tlcp的过去、现在与未来
发表评论