我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。
这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。
此文介绍如何使用gmssl的tls示例。
一、GmSSL的源码结构
下载过来的目录结构如下:
.vs是我加的,因为我习惯用visual studio查看源代码。
- include 头文件
- src C文件
- tests 测试代码
- tools 工具的代码,对应gmssl命令的command
二、gmssl命令
安装完成就可以在系统里直接使用gmssl命令了:
user@vm-ubuntu:~/gmssl$ gmssl
Usage: gmssl command [options]
command -help
Commands:
help Print this help message
version Print version
rand Generate random bytes
sm2keygen Generate SM2 keypair
sm2sign Generate SM2 signature
sm2verify Verify SM2 signature
sm2encrypt Encrypt with SM2 public key
sm2decrypt Decrypt with SM2 private key
sm3 Generate SM3 hash
sm3hmac Generate SM3 HMAC tag
sm3_pbkdf2 Hash password into key using PBKDF2 algoritm
sm3xmss_keygen Generate SM3-XMSS keypair
sm4_ecb Encrypt or decrypt with SM4 ECB
sm4_cbc Encrypt or decrypt with SM4 CBC
sm4_ctr Encrypt or decrypt with SM4 CTR
sm4_cfb Encrypt or decrypt with SM4 CFB
sm4_ofb Encrypt or decrypt with SM4 OFB
sm4_ccm Encrypt or decrypt with SM4 CCM
sm4_gcm Encrypt or decrypt with SM4 GCM
sm4_xts Encrypt or decrypt with SM4 XTS
sm4_cbc_sm3_hmac Encrypt or decrypt with SM4 CBC with SM3-HMAC
sm4_ctr_sm3_hmac Encrypt or decrypt with SM4 CTR with SM3-HMAC
sm4_cbc_mac Generate SM4 CBC-MAC
ghash Generate GHASH
zuc Encrypt or decrypt with ZUC
sm9setup Generate SM9 master secret
sm9keygen Generate SM9 private key
sm9sign Generate SM9 signature
sm9verify Verify SM9 signature
sm9encrypt SM9 public key encryption
sm9decrypt SM9 decryption
reqgen Generate certificate signing request (CSR)
reqsign Generate certificate from CSR
reqparse Parse and print a CSR
crlget Download the CRL of given certificate
crlgen Sign a CRL with CA certificate and private key
crlverify Verify a CRL with issuer's certificate
crlparse Parse and print CRL
certgen Generate a self-signed certificate
certparse Parse and print certificates
certverify Verify certificate chain
certrevoke Revoke certificate and output RevokedCertificate record
cmsparse Parse CMS (cryptographic message syntax) file
cmsencrypt Generate CMS EnvelopedData
cmsdecrypt Decrypt CMS EnvelopedData
cmssign Generate CMS SignedData
cmsverify Verify CMS SignedData
sdfinfo Print SDF device info
sdfdigest Generate SM3 hash with SDF device
sdfexport Export SM2 signing public key from SDF device
sdfsign Generate SM2 signature with SDF internal private key
sdfencrypt SM2/SM4-CBC hybrid encryption with SDF device
sdfdecrypt SM2/SM4-CBC hybrid decryption with SDF device
sdftest Test vendor's SDF library and device
tlcp_client TLCP client
tlcp_server TLCP server
tls12_client TLS 1.2 client
tls12_server TLS 1.2 server
tls13_client TLS 1.3 client
tls13_server TLS 1.3 server
run `gmssl <command> -help` to print help of the given command
user@vm-ubuntu:~/gmssl$
具体功能的源代码在tools目录下的同名C文件里。
三、使用tlcp_server
3.1 需要key、证书和密钥链
直接运行gmssl tlcp_server是不行的,需要太多参数:
user@vm-ubuntu:~/gmssl$ gmssl tlcp_server
usage: tlcp_server [-port num] -cert file -key file [-pass str] -ex_key file [-ex_pass str] [-cacert file]
对SSL有经验的知道这些参数就是证书和私钥。
3.2 生成根证书、服务端签名证书、服务端加密证书和密钥链
我看了看源代码,国密需要的证书文件(-cert参数)里面必须包含两个证书,第一个对应-key,第二个对应-ex_key。具体我还没太了解,先跑起来再说。
在一个干净的目录下执行以下脚本就可以生成所需的这些文件(执行前最好先仔细看一遍,因为我先删除了所有crt和pem!):
rm *.crt *.pem
echo 生成根证书
gmssl sm2keygen -pass 123456 -out cakey.pem -pubout capubkey.pem
gmssl certgen -C CN -ST PROVINCE -L LOCALITY -O ORG -OU ORGUINT -CN CA -days 3650 -key cakey.pem -key_usage keyCertSign -pass 123456 -out ca.crt
gmssl certparse -in ca.crt
echo 生成服务端签名证书
gmssl sm2keygen -pass 123456 -out s_signkey.pem -pubout s_signpubkey.pem
gmssl reqgen -C CN -ST PROVINCE -L LOCALITY -O ORG -OU ORGUINT -CN s_sign -key s_signkey.pem -pass 123456 -out s_signreq.pem
gmssl reqsign -in s_signreq.pem -days 3650 -key_usage digitalSignature -cacert ca.crt -key cakey.pem -pass 123456 -out s_sign.crt
gmssl certparse -in s_sign.crt
echo 生成服务端加密证书
gmssl sm2keygen -pass 123456 -out s_enckey.pem -pubout s_encpubkey.pem
gmssl reqgen -C CN -ST PROVINCE -L LOCALITY -O ORG -OU ORGUINT -CN s_enc -key s_enckey.pem -pass 123456 -out s_encreq.pem
gmssl reqsign -in s_encreq.pem -days 3650 -key_usage keyEncipherment -cacert ca.crt -key cakey.pem -pass 123456 -out s_enc.crt
gmssl certparse -in s_enc.crt
echo 生成证书链
cat s_sign.crt s_enc.crt | tee server.crt
gmssl certparse -in server.crt
生成的文件如下:
-rw-rw-r-- 1 user user 684 Aug 27 16:49 ca.crt
-rw-rw-r-- 1 user user 436 Aug 27 16:49 cakey.pem
-rw-rw-r-- 1 user user 178 Aug 27 16:49 capubkey.pem
-rw-rw-r-- 1 user user 688 Aug 27 16:49 s_enc.crt
-rw-rw-r-- 1 user user 436 Aug 27 16:49 s_enckey.pem
-rw-rw-r-- 1 user user 178 Aug 27 16:49 s_encpubkey.pem
-rw-rw-r-- 1 user user 465 Aug 27 16:49 s_encreq.pem
-rw-rw-r-- 1 user user 1376 Aug 27 16:49 server.crt
-rw-rw-r-- 1 user user 688 Aug 27 16:49 s_sign.crt
-rw-rw-r-- 1 user user 436 Aug 27 16:49 s_signkey.pem
-rw-rw-r-- 1 user user 178 Aug 27 16:49 s_signpubkey.pem
-rw-rw-r-- 1 user user 465 Aug 27 16:49 s_signreq.pem
注意一下日志,里面显示了算法,都是sm系列的。
3.3 运行tlcp_server
现在可以执行了:
启动服务端:
gmssl tlcp_server -port 10000 -cert ./server.crt -key ./s_signkey.pem -pass 123456 -ex_key ./s_enckey.pem -ex_pass 123456
启动客户端:
gmssl tlcp_client -host 127.0.0.1 -port 10000
你需要在两个控制台分别执行服务端和客户端。
服务端执行结果:
user@vm-ubuntu:~/gmssl$ gmssl tlcp_server -port 10000 -cert ./server.crt -key ./s_signkey.pem -pass 123456 -ex_key ./s_enckey.pem -ex_pass 123456
start listen ...
这样就跑起来了。(你看我云淡风轻,其实折腾参数折腾了好久,怎么弄都不对,看了源代码才意识到证书里面必须包含两个证书)
客户端也有证书参数,不过也可以不用,先跑起来看吧:
user@vm-ubuntu:~/gmssl$ gmssl tlcp_client -host 127.0.0.1 -port 10000
Connection established!
再看看服务端:
Connection Established!
现在可以在客户端随便输入,服务端会原样返回(服务端源代码显示确实如此)。
(这里是文档结束)