• 国密gmtls协议-双证书体系的服务端和客户端通信代码


    内容介绍

    • 国密的双证书体系,将证书按照使用目的的不同划分为加密证书和签名证书两种,也就是两对公私钥,二者本质一致,均为SM2密钥对,区别仅体现在用法
    • 国密CA体系中,加密密钥对由CA产生,签名密钥对由用户自己产生,那么加密密钥涉及到的 私钥是如何通过安全的方式由CA传递到用户侧呢?使用数字信封的机理
    • 从道理上来说两个密钥具有不同的属性,逻辑上应该分开处理。其实最主要的原因是国家要保证必要的时候有能力对某些通讯进行监控,如果采用单证书,除了自己谁也无法解密(理论上如此),不利于国家安全。因此某些国家法律规定使用双证书。如果拥有加密证书的私钥,可以进行实时监控。使用过wireshark抓HTTPS包的朋友应该知道,如果配置了RSA密钥,可以解密出HTTPS通信中的加密信息。

    加密证书和私钥的生成过程

    • 用户产生签名密钥对,生成签名证书的请求,发送签名证书给CA
    • CA验证用户的签名密钥对,产生加密证书
    • CA生成对称密钥,使用用户的签名公钥加密对称密钥,生成对称秘钥的密文
    • CA使用对称密钥对称加密 加密证书所对应的私钥,输出加密私钥的密文
    • CA将加密证书、对称密钥密文和加密私钥的密文 返还给 用户
    • 用户使用签名私钥解密对称密钥的密文得到对称密钥
    • 用户使用对称密钥解密加密私钥,得到加密私钥的明文

    国标文档

    注意事项

    • 双证书与标准TLS报文格式一样,但至少要包含两个证书,签名证书在前,加密证书在后。如果牵扯到证书链,问题就复杂了,而且协议这里也没有规定清楚。是签名证书 + 证书链 + 加密证书,还是签名证书 + 加密证书 + 证书链?在实现中发现TASSL采用的是前者,而沃通测试网站采用后者。在编码时请注意,最好是两者都兼容。

    参考链接

    最关键的参考链接

    命令行 模式

    -dcert filename-dkey keyname

    specify an additional certificate and private key, these behave in the same manner as the -cert and -key options except there is no default if they are not specified (no additional certificate and key is used). As noted above some cipher suites require a certificate containing a key of a certain type. Some cipher suites need a certificate carrying an RSA key and some a DSS (DSA) key. By using RSA and DSS certificates and keys a server can support clients which only support RSA or DSS cipher suites by using an appropriate certificate.

    -dcert文件名,-dkey密钥名
    指定一个额外的证书和私钥,它们的行为方式与-cert和-key选项相同,除非没有指定它们,否则没有默认值(不使用额外的证书和密钥)。如上所述,一些密码套件需要包含特定类型密钥的证书。一些密码套件需要携带RSA密钥和一些DSS (DSA)密钥的证书。通过使用RSA和DSS证书和密钥,服务器可以通过使用适当的证书来支持仅支持RSA或DSS密码套件的客户端。

    双证书双向认证 

    服务端

    • 在设置双证书时,需要先设置签名证书,然后再设置加密证书,具体可参考源码。
    • 服务端执行命令 需要在指定的文件下执行
    • 必须要有 verify,verify是开启gmtls双向证书认证的关键,也就是对等证书验证,客户端也会验证服务端的证书
    • gmssl s_server -gmtls -accept 44330 -key SS.key.pem -cert SS.cert.pem -dkey SE.key.pem -dcert SE.cert.pem -CAfile CA.cert.pem -state -verify 1
    1. chy-cpabe@ubuntu:~/GMSSL_certificate/sm2Certs$ gmssl s_server -gmtls -accept 44330 -key SS.key.pem -cert SS.cert.pem -dkey SE.key.pem -dcert SE.cert.pem -CAfile CA.cert.pem -state -verify 1
    2. verify depth is 1
    3. Using default temp DH parameters
    4. [GMTLS_DEBUG] set sm2 signing certificate
    5. [GMTLS_DEBUG] set sm2 signing private key
    6. [GMTLS_DEBUG] set sm2 encryption certificate
    7. [GMTLS_DEBUG] set sm2 decryption private key
    8. ACCEPT
    9. SSL_accept:before SSL initialization
    10. SSL_accept:before SSL initialization
    11. SSL_accept:SSLv3/TLS read client hello
    12. SSL_accept:SSLv3/TLS write server hello
    13. SSL_accept:SSLv3/TLS write certificate
    14. SSL_accept:SSLv3/TLS write key exchange
    15. SSL_accept:SSLv3/TLS write certificate request
    16. SSL_accept:SSLv3/TLS write server done
    17. SSL_accept:SSLv3/TLS write server done
    18. depth=1 C = CN, ST = BJ, L = HaiDian, O = Beijing JNTA Technology LTD., OU = SORB of TASS, CN = Test CA (SM2)
    19. verify return:1
    20. depth=0 C = CN, ST = BJ, L = HaiDian, O = Beijing JNTA Technology LTD., OU = BSRC of TASS, CN = client sign (SM2)
    21. verify return:1
    22. SSL_accept:SSLv3/TLS read client certificate
    23. ssl_get_algorithm2=f227000008x
    24. SSL_accept:SSLv3/TLS read client key exchange
    25. SSL_accept:SSLv3/TLS read certificate verify
    26. SSL_accept:SSLv3/TLS read change cipher spec
    27. SSL_accept:SSLv3/TLS read finished
    28. SSL_accept:SSLv3/TLS write change cipher spec
    29. SSL_accept:SSLv3/TLS write finished
    30. -----BEGIN SSL SESSION PARAMETERS-----
    31. MIICmAIBAQICAQEEAuATBCAWcAdtfPyMiEJmINUd/e/AmYdNqNTalV1AAbACRSQE
    32. CgQwtuURXPYQpQ7gQIZ3fWRd9QpsP0Zi57oDT1D/X1xVBL3wy9yrr/BOpRw2afsu
    33. 4DH3oQYCBGMw/gSiBAICHCCjggIfMIICGzCCAcGgAwIBAgIJAIVjx+dwZIdmMAoG
    34. CCqBHM9VAYN1MIGCMQswCQYDVQQGEwJDTjELMAkGA1UECAwCQkoxEDAOBgNVBAcM
    35. B0hhaURpYW4xJTAjBgNVBAoMHEJlaWppbmcgSk5UQSBUZWNobm9sb2d5IExURC4x
    36. FTATBgNVBAsMDFNPUkIgb2YgVEFTUzEWMBQGA1UEAwwNVGVzdCBDQSAoU00yKTAe
    37. Fw0yMDA2MjAxMDE4MjZaFw0yNDA3MjkxMDE4MjZaMIGGMQswCQYDVQQGEwJDTjEL
    38. MAkGA1UECAwCQkoxEDAOBgNVBAcMB0hhaURpYW4xJTAjBgNVBAoMHEJlaWppbmcg
    39. Sk5UQSBUZWNobm9sb2d5IExURC4xFTATBgNVBAsMDEJTUkMgb2YgVEFTUzEaMBgG
    40. A1UEAwwRY2xpZW50IHNpZ24gKFNNMikwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNC
    41. AARV/eII1n2NVqYjwt9r9A5Eh6Z0iG+WUpsw4sGxhfKL0vr0OKcur6DZqjqLDSCr
    42. ZEhU6yuntNtaW+pexPblqXAroxowGDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIGwDAK
    43. BggqgRzPVQGDdQNIADBFAiEAiX+PoCNW/n9SDbv6/o+NyCCV/7kBgunc7w5b7xGm
    44. 4RICIBMDlLjPZE2ACYhu1Wjqph23PfMPMgae4+Gtd7wzFz2UpAYEBAEAAAA=
    45. -----END SSL SESSION PARAMETERS-----
    46. Client certificate
    47. -----BEGIN CERTIFICATE-----
    48. MIICGzCCAcGgAwIBAgIJAIVjx+dwZIdmMAoGCCqBHM9VAYN1MIGCMQswCQYDVQQG
    49. EwJDTjELMAkGA1UECAwCQkoxEDAOBgNVBAcMB0hhaURpYW4xJTAjBgNVBAoMHEJl
    50. aWppbmcgSk5UQSBUZWNobm9sb2d5IExURC4xFTATBgNVBAsMDFNPUkIgb2YgVEFT
    51. UzEWMBQGA1UEAwwNVGVzdCBDQSAoU00yKTAeFw0yMDA2MjAxMDE4MjZaFw0yNDA3
    52. MjkxMDE4MjZaMIGGMQswCQYDVQQGEwJDTjELMAkGA1UECAwCQkoxEDAOBgNVBAcM
    53. B0hhaURpYW4xJTAjBgNVBAoMHEJlaWppbmcgSk5UQSBUZWNobm9sb2d5IExURC4x
    54. FTATBgNVBAsMDEJTUkMgb2YgVEFTUzEaMBgGA1UEAwwRY2xpZW50IHNpZ24gKFNN
    55. MikwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAARV/eII1n2NVqYjwt9r9A5Eh6Z0
    56. iG+WUpsw4sGxhfKL0vr0OKcur6DZqjqLDSCrZEhU6yuntNtaW+pexPblqXAroxow
    57. GDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIGwDAKBggqgRzPVQGDdQNIADBFAiEAiX+P
    58. oCNW/n9SDbv6/o+NyCCV/7kBgunc7w5b7xGm4RICIBMDlLjPZE2ACYhu1Wjqph23
    59. PfMPMgae4+Gtd7wzFz2U
    60. -----END CERTIFICATE-----
    61. subject=/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=BSRC of TASS/CN=client sign (SM2)
    62. issuer=/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    63. Shared ciphers:SM9-WITH-SMS4-SM3:SM9DHE-WITH-SMS4-SM3:SM2-WITH-SMS4-SM3:SM2DHE-WITH-SMS4-SM3:RSA-WITH-SMS4-SHA1:RSA-WITH-SMS4-SM3
    64. CIPHER is SM2-WITH-SMS4-SM3
    65. Secure Renegotiation IS supported

    客户端 

    • 客户端执行代码和执行结果  
    • gmssl s_client -gmtls -connect localhost:44330 -key CS.key.pem -cert CS.cert.pem -dkey CE.key.pem -dcert CE.cert.pem -CAfile CA.cert.pem -state -showcerts
    1. chy-cpabe@ubuntu:~/GMSSL_certificate/sm2Certs$ gmssl s_client -gmtls -connect localhost:44330 -key CS.key.pem -cert CS.cert.pem -dkey CE.key.pem -dcert CE.cert.pem -CAfile CA.cert.pem -state -showcerts
    2. [GMTLS_DEBUG] set sm2 signing certificate
    3. [GMTLS_DEBUG] set sm2 signing private key
    4. [GMTLS_DEBUG] set sm2 encryption certificate
    5. [GMTLS_DEBUG] set sm2 decryption private key
    6. CONNECTED(00000003)
    7. SSL_connect:before SSL initialization
    8. SSL_connect:SSLv3/TLS write client hello
    9. SSL_connect:SSLv3/TLS write client hello
    10. SSL_connect:SSLv3/TLS read server hello
    11. depth=1 C = CN, ST = BJ, L = HaiDian, O = Beijing JNTA Technology LTD., OU = SORB of TASS, CN = Test CA (SM2)
    12. verify return:1
    13. depth=0 C = CN, ST = BJ, L = HaiDian, O = Beijing JNTA Technology LTD., OU = BSRC of TASS, CN = server sign (SM2)
    14. verify return:1
    15. SSL_connect:SSLv3/TLS read server certificate
    16. Z=BCDCCB61AADD790C076DAC60ED09DDD5285A906A4025DD748DA2FB5816464C58
    17. C=00021E3082021A308201C0A0030201020209008563C7E770648765300A06082A811CCF55018375308182310B300906035504061302434E310B300906035504080C02424A3110300E06035504070C074861694469616E31253023060355040A0C1C4265696A696E67204A4E544120546563686E6F6C6F6779204C54442E31153013060355040B0C0C534F5242206F6620544153533116301406035504030C0D546573742043412028534D3229301E170D3230303632303130313832365A170D3234303732393130313832365A308185310B300906035504061302434E310B300906035504080C02424A3110300E06035504070C074861694469616E31253023060355040A0C1C4265696A696E67204A4E544120546563686E6F6C6F6779204C54442E31153013060355040B0C0C42535243206F6620544153533119301706035504030C1073657276657220656E632028534D32293059301306072A8648CE3D020106082A811CCF5501822D03420004B999853302F02CC522CC4CCA287019E86B901FC24E3CCF9A61B93BB177B28C2CE8E23C5C522DF73C23F7AC36FF688CB2E685A3FA4770103F7C99EFC32D06C11FA31A301830090603551D1304023000300B0603551D0F040403020338300A06082A811CCF550183750348003045022100EC4368F400870BED441817AF4D359BDC61A9EDFDDEE54AB0C185084B450C46B902206E0C3A08BC584590046DC85603CD4E8A51F97D9669B1ACA3E2A3627BE61D49A2
    18. SSL_connect:SSLv3/TLS read server key exchange
    19. SSL_connect:SSLv3/TLS read server certificate request
    20. SSL_connect:SSLv3/TLS read server done
    21. SSL_connect:SSLv3/TLS write client certificate
    22. SSL_connect:SSLv3/TLS write client key exchange
    23. ssl_get_algorithm2=3268600008x
    24. SSL_connect:SSLv3/TLS write certificate verify
    25. SSL_connect:SSLv3/TLS write change cipher spec
    26. SSL_connect:SSLv3/TLS write finished
    27. SSL_connect:SSLv3/TLS write finished
    28. SSL_connect:SSLv3/TLS read change cipher spec
    29. SSL_connect:SSLv3/TLS read finished
    30. ---
    31. Certificate chain
    32. 0 s:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=BSRC of TASS/CN=server sign (SM2)
    33. i:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    34. -----BEGIN CERTIFICATE-----
    35. MIICGjCCAcGgAwIBAgIJAIVjx+dwZIdkMAoGCCqBHM9VAYN1MIGCMQswCQYDVQQG
    36. EwJDTjELMAkGA1UECAwCQkoxEDAOBgNVBAcMB0hhaURpYW4xJTAjBgNVBAoMHEJl
    37. aWppbmcgSk5UQSBUZWNobm9sb2d5IExURC4xFTATBgNVBAsMDFNPUkIgb2YgVEFT
    38. UzEWMBQGA1UEAwwNVGVzdCBDQSAoU00yKTAeFw0yMDA2MjAxMDE4MjVaFw0yNDA3
    39. MjkxMDE4MjVaMIGGMQswCQYDVQQGEwJDTjELMAkGA1UECAwCQkoxEDAOBgNVBAcM
    40. B0hhaURpYW4xJTAjBgNVBAoMHEJlaWppbmcgSk5UQSBUZWNobm9sb2d5IExURC4x
    41. FTATBgNVBAsMDEJTUkMgb2YgVEFTUzEaMBgGA1UEAwwRc2VydmVyIHNpZ24gKFNN
    42. MikwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAAS0lHzt7CkOzCtyf6VwCqoT2PYD
    43. CL/AJrCsHa+6lE8wDZ7DShI2bvfmrpavndEW67CHQOlO0q6/aoEB0PoAgpopoxow
    44. GDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIGwDAKBggqgRzPVQGDdQNHADBEAiB06JWp
    45. uxFbGBfvG9juhe2Umu/auI1H2XeMdvDjbOtfuQIgMXT8jewkzq9TR3OPzRTkZCRH
    46. 3H+xKEb8r8JsEEStwaU=
    47. -----END CERTIFICATE-----
    48. 1 s:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=BSRC of TASS/CN=server enc (SM2)
    49. i:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    50. -----BEGIN CERTIFICATE-----
    51. MIICGjCCAcCgAwIBAgIJAIVjx+dwZIdlMAoGCCqBHM9VAYN1MIGCMQswCQYDVQQG
    52. EwJDTjELMAkGA1UECAwCQkoxEDAOBgNVBAcMB0hhaURpYW4xJTAjBgNVBAoMHEJl
    53. aWppbmcgSk5UQSBUZWNobm9sb2d5IExURC4xFTATBgNVBAsMDFNPUkIgb2YgVEFT
    54. UzEWMBQGA1UEAwwNVGVzdCBDQSAoU00yKTAeFw0yMDA2MjAxMDE4MjZaFw0yNDA3
    55. MjkxMDE4MjZaMIGFMQswCQYDVQQGEwJDTjELMAkGA1UECAwCQkoxEDAOBgNVBAcM
    56. B0hhaURpYW4xJTAjBgNVBAoMHEJlaWppbmcgSk5UQSBUZWNobm9sb2d5IExURC4x
    57. FTATBgNVBAsMDEJTUkMgb2YgVEFTUzEZMBcGA1UEAwwQc2VydmVyIGVuYyAoU00y
    58. KTBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABLmZhTMC8CzFIsxMyihwGehrkB/C
    59. TjzPmmG5O7F3sows6OI8XFIt9zwj96w2/2iMsuaFo/pHcBA/fJnvwy0GwR+jGjAY
    60. MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgM4MAoGCCqBHM9VAYN1A0gAMEUCIQDsQ2j0
    61. AIcL7UQYF69NNZvcYant/d7lSrDBhQhLRQxGuQIgbgw6CLxYRZAEbchWA81OilH5
    62. fZZpsayj4qNie+YdSaI=
    63. -----END CERTIFICATE-----
    64. 2 s:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    65. i:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    66. -----BEGIN CERTIFICATE-----
    67. MIICWjCCAgCgAwIBAgIJAP5W2mLaOWq5MAoGCCqBHM9VAYN1MIGCMQswCQYDVQQG
    68. EwJDTjELMAkGA1UECAwCQkoxEDAOBgNVBAcMB0hhaURpYW4xJTAjBgNVBAoMHEJl
    69. aWppbmcgSk5UQSBUZWNobm9sb2d5IExURC4xFTATBgNVBAsMDFNPUkIgb2YgVEFT
    70. UzEWMBQGA1UEAwwNVGVzdCBDQSAoU00yKTAeFw0yMDA2MjAxMDE4MjVaFw0yNDA3
    71. MjkxMDE4MjVaMIGCMQswCQYDVQQGEwJDTjELMAkGA1UECAwCQkoxEDAOBgNVBAcM
    72. B0hhaURpYW4xJTAjBgNVBAoMHEJlaWppbmcgSk5UQSBUZWNobm9sb2d5IExURC4x
    73. FTATBgNVBAsMDFNPUkIgb2YgVEFTUzEWMBQGA1UEAwwNVGVzdCBDQSAoU00yKTBZ
    74. MBMGByqGSM49AgEGCCqBHM9VAYItA0IABArjN7ag+H8D12eqXJpMeTOR9m3sB2RC
    75. ojH7fZPB77SDfHZb9g1lcqUhrug0nw2F8wBMsLfjvsK3wQn/ryi3YvSjXTBbMB0G
    76. A1UdDgQWBBRCcBGiEpd09qSpUlkiGkZ+q+CFbDAfBgNVHSMEGDAWgBRCcBGiEpd0
    77. 9qSpUlkiGkZ+q+CFbDAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjAKBggqgRzP
    78. VQGDdQNIADBFAiBjdylWVsUoTRcHu9DoMHv4lgtYJMf2xHAGLoJUjmbizAIhAOFD
    79. i3EmFVUgGVdgbnztFZcBLxtBzIAh/Q4Q3dm3/MFu
    80. -----END CERTIFICATE-----
    81. ---
    82. Server certificate
    83. subject=/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=BSRC of TASS/CN=server sign (SM2)
    84. issuer=/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    85. ---
    86. Acceptable client certificate CA names
    87. /C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    88. Client Certificate Types: RSA sign, DSA sign
    89. ---
    90. SSL handshake has read 2121 bytes and written 2115 bytes
    91. Verification: OK
    92. ---
    93. New, GMTLSv1.1, Cipher is SM2-WITH-SMS4-SM3
    94. Server public key is 256 bit
    95. Secure Renegotiation IS NOT supported
    96. Compression: NONE
    97. Expansion: NONE
    98. No ALPN negotiated
    99. SSL-Session:
    100. Protocol : GMTLSv1.1
    101. Cipher : SM2-WITH-SMS4-SM3
    102. Session-ID: 1670076D7CFC8C88426620D51DFDEFC099874DA8D4DA955D4001B0024524040A
    103. Session-ID-ctx:
    104. Master-Key: B6E5115CF610A50EE04086777D645DF50A6C3F4662E7BA034F50FF5F5C5504BDF0CBDCABAFF04EA51C3669FB2EE031F7
    105. PSK identity: None
    106. PSK identity hint: None
    107. SRP username: None
    108. Start Time: 1664155140
    109. Timeout : 7200 (sec)
    110. Verify return code: 0 (ok)
    111. Extended master secret: no
    112. ---

    双证书单向认证 

    • 同时指定签名和加密证书 且 采用双证书单向认证
    • 服务端执行代码
    • gmssl s_server -gmtls -accept 44330 -key SS.key.pem -cert SS.cert.pem -dkey SE.key.pem -dcert SE.cert.pem -CAfile CA.cert.pem -state
    • 只需要将verify删除,就由双向认证变成了单项认证
    • -state参数表示打印跟多信息,方便调试
    1. s_server: Cannot open input file gmcrt/2_sign.crt, No such file or directory
    2. s_server: Use -help for summary.
    3. chy-cpabe@ubuntu:~/test_double_ssl/GMSSL双证书demo/sm2Certs$ ls
    4. CA.cert.pem CA.key.pem CA.pem CE.cert.pem CE.key.pem CE.pem CS.cert.pem CS.key.pem CS.pem SE.cert.pem SE.key.pem SE.pem SS.cert.pem SS.key.pem SS.pem
    5. chy-cpabe@ubuntu:~/test_double_ssl/GMSSL双证书demo/sm2Certs$ gmssl s_server -gmtls -accept 44330 -key SS.key.pem -cert SS.cert.pem -dkey SE.key.pem -dcert SE.cert.pem -CAfile CA.cert.pem -state
    6. Using default temp DH parameters
    7. [GMTLS_DEBUG] set sm2 signing certificate
    8. [GMTLS_DEBUG] set sm2 signing private key
    9. [GMTLS_DEBUG] set sm2 encryption certificate
    10. [GMTLS_DEBUG] set sm2 decryption private key
    11. ACCEPT
    12. SSL_accept:before SSL initialization
    13. SSL_accept:before SSL initialization
    14. ssl_get_algorithm2=2b81000008x
    15. SSL_accept:SSLv3/TLS read client hello
    16. SSL_accept:SSLv3/TLS write server hello
    17. SSL_accept:SSLv3/TLS write certificate
    18. SSL_accept:SSLv3/TLS write key exchange
    19. SSL_accept:SSLv3/TLS write server done
    20. SSL_accept:SSLv3/TLS write server done
    21. SSL_accept:SSLv3/TLS read client key exchange
    22. SSL_accept:SSLv3/TLS read change cipher spec
    23. SSL_accept:SSLv3/TLS read finished
    24. SSL_accept:SSLv3/TLS write change cipher spec
    25. SSL_accept:SSLv3/TLS write finished
    26. -----BEGIN SSL SESSION PARAMETERS-----
    27. MHUCAQECAgEBBALgEwQg4tsFtm05e9thEdmOsDjCdEY797x1PAcVaGWd8chdLuoE
    28. MDqjvlXZek3vSlC1q+aYT7NA40D6C7sbR0gNowPIhMfVan396kWxthLUmXIgz3t1
    29. 5qEGAgRjAfsxogQCAhwgpAYEBAEAAAA=
    30. -----END SSL SESSION PARAMETERS-----
    31. Shared ciphers:SM9-WITH-SMS4-SM3:SM9DHE-WITH-SMS4-SM3:SM2-WITH-SMS4-SM3:SM2DHE-WITH-SMS4-SM3:RSA-WITH-SMS4-SHA1:RSA-WITH-SMS4-SM3
    32. CIPHER is SM2-WITH-SMS4-SM3
    33. Secure Renegotiation IS supported
    • 客户端执行代码
    • gmssl s_client -gmtls -connect localhost:44330 -key CS.key.pem -cert CS.cert.pem -dkey CE.key.pem -dcert CE.cert.pem -CAfile CA.cert.pem -state
    • 可以看出,现在使用的协议已经变成gmtlsv1.1
    • SSL-Session:
    •     Protocol  : GMTLSv1.1
    1. [GMTLS_DEBUG] set sm2 signing certificate
    2. [GMTLS_DEBUG] set sm2 signing private key
    3. [GMTLS_DEBUG] set sm2 encryption certificate
    4. [GMTLS_DEBUG] set sm2 decryption private key
    5. CONNECTED(00000003)
    6. SSL_connect:before SSL initialization
    7. SSL_connect:SSLv3/TLS write client hello
    8. SSL_connect:SSLv3/TLS write client hello
    9. SSL_connect:SSLv3/TLS read server hello
    10. depth=1 C = CN, ST = BJ, L = HaiDian, O = Beijing JNTA Technology LTD., OU = SORB of TASS, CN = Test CA (SM2)
    11. verify return:1
    12. depth=0 C = CN, ST = BJ, L = HaiDian, O = Beijing JNTA Technology LTD., OU = BSRC of TASS, CN = server sign (SM2)
    13. verify return:1
    14. SSL_connect:SSLv3/TLS read server certificate
    15. Z=BCDCCB61AADD790C076DAC60ED09DDD5285A906A4025DD748DA2FB5816464C58
    16. C=00021E3082021A308201C0A0030201020209008563C7E770648765300A06082A811CCF55018375308182310B300906035504061302434E310B300906035504080C02424A3110300E06035504070C074861694469616E31253023060355040A0C1C4265696A696E67204A4E544120546563686E6F6C6F6779204C54442E31153013060355040B0C0C534F5242206F6620544153533116301406035504030C0D546573742043412028534D3229301E170D3230303632303130313832365A170D3234303732393130313832365A308185310B300906035504061302434E310B300906035504080C02424A3110300E06035504070C074861694469616E31253023060355040A0C1C4265696A696E67204A4E544120546563686E6F6C6F6779204C54442E31153013060355040B0C0C42535243206F6620544153533119301706035504030C1073657276657220656E632028534D32293059301306072A8648CE3D020106082A811CCF5501822D03420004B999853302F02CC522CC4CCA287019E86B901FC24E3CCF9A61B93BB177B28C2CE8E23C5C522DF73C23F7AC36FF688CB2E685A3FA4770103F7C99EFC32D06C11FA31A301830090603551D1304023000300B0603551D0F040403020338300A06082A811CCF550183750348003045022100EC4368F400870BED441817AF4D359BDC61A9EDFDDEE54AB0C185084B450C46B902206E0C3A08BC584590046DC85603CD4E8A51F97D9669B1ACA3E2A3627BE61D49A2
    17. SSL_connect:SSLv3/TLS read server key exchange
    18. SSL_connect:SSLv3/TLS read server done
    19. SSL_connect:SSLv3/TLS write client key exchange
    20. SSL_connect:SSLv3/TLS write change cipher spec
    21. ssl_get_algorithm2=2790100008x
    22. SSL_connect:SSLv3/TLS write finished
    23. SSL_connect:SSLv3/TLS write finished
    24. SSL_connect:SSLv3/TLS read change cipher spec
    25. SSL_connect:SSLv3/TLS read finished
    26. ---
    27. Certificate chain
    28. 0 s:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=BSRC of TASS/CN=server sign (SM2)
    29. i:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    30. 1 s:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=BSRC of TASS/CN=server enc (SM2)
    31. i:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    32. 2 s:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    33. i:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    34. ---
    35. Server certificate
    36. -----BEGIN CERTIFICATE-----
    37. MIICGjCCAcGgAwIBAgIJAIVjx+dwZIdkMAoGCCqBHM9VAYN1MIGCMQswCQYDVQQG
    38. EwJDTjELMAkGA1UECAwCQkoxEDAOBgNVBAcMB0hhaURpYW4xJTAjBgNVBAoMHEJl
    39. aWppbmcgSk5UQSBUZWNobm9sb2d5IExURC4xFTATBgNVBAsMDFNPUkIgb2YgVEFT
    40. UzEWMBQGA1UEAwwNVGVzdCBDQSAoU00yKTAeFw0yMDA2MjAxMDE4MjVaFw0yNDA3
    41. MjkxMDE4MjVaMIGGMQswCQYDVQQGEwJDTjELMAkGA1UECAwCQkoxEDAOBgNVBAcM
    42. B0hhaURpYW4xJTAjBgNVBAoMHEJlaWppbmcgSk5UQSBUZWNobm9sb2d5IExURC4x
    43. FTATBgNVBAsMDEJTUkMgb2YgVEFTUzEaMBgGA1UEAwwRc2VydmVyIHNpZ24gKFNN
    44. MikwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAAS0lHzt7CkOzCtyf6VwCqoT2PYD
    45. CL/AJrCsHa+6lE8wDZ7DShI2bvfmrpavndEW67CHQOlO0q6/aoEB0PoAgpopoxow
    46. GDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIGwDAKBggqgRzPVQGDdQNHADBEAiB06JWp
    47. uxFbGBfvG9juhe2Umu/auI1H2XeMdvDjbOtfuQIgMXT8jewkzq9TR3OPzRTkZCRH
    48. 3H+xKEb8r8JsEEStwaU=
    49. -----END CERTIFICATE-----
    50. subject=/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=BSRC of TASS/CN=server sign (SM2)
    51. issuer=/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    52. ---
    53. No client certificate CA names sent
    54. ---
    55. SSL handshake has read 1973 bytes and written 320 bytes
    56. Verification: OK
    57. ---
    58. New, GMTLSv1.1, Cipher is SM2-WITH-SMS4-SM3
    59. Server public key is 256 bit
    60. Secure Renegotiation IS NOT supported
    61. Compression: NONE
    62. Expansion: NONE
    63. No ALPN negotiated
    64. SSL-Session:
    65. Protocol : GMTLSv1.1
    66. Cipher : SM2-WITH-SMS4-SM3
    67. Session-ID: E24D8195A9D25F9A6B877C63A85979492FA5199E58FA512A95915E33BA7A418B
    68. Session-ID-ctx:
    69. Master-Key: 2ED26139965074A55F65D011A370DF7A4672A0FC7BBB4A0ED991DCD55A6231E92B5A09225BFE9F1ABD0546F1F75885A2
    70. PSK identity: None
    71. PSK identity hint: None
    72. SRP username: None
    73. Start Time: 1661073328
    74. Timeout : 7200 (sec)
    75. Verify return code: 0 (ok)
    76. Extended master secret: no
    77. ---
    • 客户端命令
    • gmssl s_client -gmtls -connect localhost:44330 -key CS.key.pem -cert CS.cert.pem -dkey CE.key.pem -dcert CE.cert.pem -CAfile CA.cert.pem -state
    1. gmssl s_client -gmtls -connect localhost:44330 -key CS.key.pem -cert CS.cert.pem -dkey CE.key.pem -dcert CE.cert.pem -CAfile CA.cert.pem -state
    2. [GMTLS_DEBUG] set sm2 signing certificate
    3. [GMTLS_DEBUG] set sm2 signing private key
    4. [GMTLS_DEBUG] set sm2 encryption certificate
    5. [GMTLS_DEBUG] set sm2 decryption private key
    6. CONNECTED(00000003)
    7. SSL_connect:before SSL initialization
    8. SSL_connect:SSLv3/TLS write client hello
    9. SSL_connect:SSLv3/TLS write client hello
    10. SSL_connect:SSLv3/TLS read server hello
    11. depth=1 C = CN, ST = BJ, L = HaiDian, O = Beijing JNTA Technology LTD., OU = SORB of TASS, CN = Test CA (SM2)
    12. verify return:1
    13. depth=0 C = CN, ST = BJ, L = HaiDian, O = Beijing JNTA Technology LTD., OU = BSRC of TASS, CN = server sign (SM2)
    14. verify return:1
    15. SSL_connect:SSLv3/TLS read server certificate
    16. Z=BCDCCB61AADD790C076DAC60ED09DDD5285A906A4025DD748DA2FB5816464C58
    17. C=00021E3082021A308201C0A0030201020209008563C7E770648765300A06082A811CCF55018375308182310B300906035504061302434E310B300906035504080C02424A3110300E06035504070C074861694469616E31253023060355040A0C1C4265696A696E67204A4E544120546563686E6F6C6F6779204C54442E31153013060355040B0C0C534F5242206F6620544153533116301406035504030C0D546573742043412028534D3229301E170D3230303632303130313832365A170D3234303732393130313832365A308185310B300906035504061302434E310B300906035504080C02424A3110300E06035504070C074861694469616E31253023060355040A0C1C4265696A696E67204A4E544120546563686E6F6C6F6779204C54442E31153013060355040B0C0C42535243206F6620544153533119301706035504030C1073657276657220656E632028534D32293059301306072A8648CE3D020106082A811CCF5501822D03420004B999853302F02CC522CC4CCA287019E86B901FC24E3CCF9A61B93BB177B28C2CE8E23C5C522DF73C23F7AC36FF688CB2E685A3FA4770103F7C99EFC32D06C11FA31A301830090603551D1304023000300B0603551D0F040403020338300A06082A811CCF550183750348003045022100EC4368F400870BED441817AF4D359BDC61A9EDFDDEE54AB0C185084B450C46B902206E0C3A08BC584590046DC85603CD4E8A51F97D9669B1ACA3E2A3627BE61D49A2
    18. SSL_connect:SSLv3/TLS read server key exchange
    19. SSL_connect:SSLv3/TLS read server certificate request
    20. SSL_connect:SSLv3/TLS read server done
    21. SSL_connect:SSLv3/TLS write client certificate
    22. SSL_connect:SSLv3/TLS write client key exchange
    23. ssl_get_algorithm2=3c3f900008x
    24. SSL_connect:SSLv3/TLS write certificate verify
    25. SSL_connect:SSLv3/TLS write change cipher spec
    26. SSL_connect:SSLv3/TLS write finished
    27. SSL3 alert read:fatal:decrypt error
    28. SSL_connect:error in SSLv3/TLS write finished
    29. 140016949239808:error:1409441B:SSL routines:ssl3_read_bytes:tlsv1 alert decrypt error:ssl/record/rec_layer_s3.c:1385:SSL alert number 51
    30. ---
    31. Certificate chain
    32. 0 s:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=BSRC of TASS/CN=server sign (SM2)
    33. i:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    34. 1 s:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=BSRC of TASS/CN=server enc (SM2)
    35. i:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    36. 2 s:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    37. i:/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    38. ---
    39. Server certificate
    40. -----BEGIN CERTIFICATE-----
    41. MIICGjCCAcGgAwIBAgIJAIVjx+dwZIdkMAoGCCqBHM9VAYN1MIGCMQswCQYDVQQG
    42. EwJDTjELMAkGA1UECAwCQkoxEDAOBgNVBAcMB0hhaURpYW4xJTAjBgNVBAoMHEJl
    43. aWppbmcgSk5UQSBUZWNobm9sb2d5IExURC4xFTATBgNVBAsMDFNPUkIgb2YgVEFT
    44. UzEWMBQGA1UEAwwNVGVzdCBDQSAoU00yKTAeFw0yMDA2MjAxMDE4MjVaFw0yNDA3
    45. MjkxMDE4MjVaMIGGMQswCQYDVQQGEwJDTjELMAkGA1UECAwCQkoxEDAOBgNVBAcM
    46. B0hhaURpYW4xJTAjBgNVBAoMHEJlaWppbmcgSk5UQSBUZWNobm9sb2d5IExURC4x
    47. FTATBgNVBAsMDEJTUkMgb2YgVEFTUzEaMBgGA1UEAwwRc2VydmVyIHNpZ24gKFNN
    48. MikwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAAS0lHzt7CkOzCtyf6VwCqoT2PYD
    49. CL/AJrCsHa+6lE8wDZ7DShI2bvfmrpavndEW67CHQOlO0q6/aoEB0PoAgpopoxow
    50. GDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIGwDAKBggqgRzPVQGDdQNHADBEAiB06JWp
    51. uxFbGBfvG9juhe2Umu/auI1H2XeMdvDjbOtfuQIgMXT8jewkzq9TR3OPzRTkZCRH
    52. 3H+xKEb8r8JsEEStwaU=
    53. -----END CERTIFICATE-----
    54. subject=/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=BSRC of TASS/CN=server sign (SM2)
    55. issuer=/C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    56. ---
    57. Acceptable client certificate CA names
    58. /C=CN/ST=BJ/L=HaiDian/O=Beijing JNTA Technology LTD./OU=SORB of TASS/CN=Test CA (SM2)
    59. Client Certificate Types: RSA sign, DSA sign
    60. ---
    61. SSL handshake has read 2037 bytes and written 2116 bytes
    62. Verification: OK
    63. ---
    64. New, GMTLSv1.1, Cipher is SM2-WITH-SMS4-SM3
    65. Server public key is 256 bit
    66. Secure Renegotiation IS NOT supported
    67. Compression: NONE
    68. Expansion: NONE
    69. No ALPN negotiated
    70. SSL-Session:
    71. Protocol : GMTLSv1.1
    72. Cipher : SM2-WITH-SMS4-SM3
    73. Session-ID: 12664AE82CE989580C27B14AFF7487B19FF1C159C94291A0B76AA5F80D28317F
    74. Session-ID-ctx:
    75. Master-Key: AD4D5164B7F54B9FA1F74A7A569C6B6E75CFD96967AB7519658C33E9C6FB8851EBCF1B10E175E736E9C7127E5FA8D32D
    76. PSK identity: None
    77. PSK identity hint: None
    78. SRP username: None
    79. Start Time: 1661074697
    80. Timeout : 7200 (sec)
    81. Verify return code: 0 (ok)
    82. Extended master secret: no
    83. ---

    双证书双向认证-代码实现

     参考链接

     注意事项

    • 基于TASSL开源项目中的Tassl_demo/mk_tls_cert 下的 SM2certgen.sh 脚本,共生成 15 个 PEM 文件,即根证书、服务端和客户端的签名和加密证书
    • 上述参考链接里面的下面这句话是错误的,服务端都不验证客户端身份了,还叫双向认证嘛??
    • 修改后代码如下
    1. // 是否要求校验对方证书 此处不验证客户端身份所以为: SSL_VERIFY_NONE
    2. SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);

     服务端代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #define MAXBUF 1500
    12. //#define CA_CERT_FILE "/home/chy-cpabe/GMSSL_certificate/sm2Certs/CA.cert.pem"
    13. //#define SIGN_CERT_FILE "/home/chy-cpabe/GMSSL_certificate/sm2Certs/SS.cert.pem"
    14. //#define SIGN_KEY_FILE "/home/chy-cpabe/GMSSL_certificate/sm2Certs/SS.key.pem"
    15. //#define ENCODE_CERT_FILE "/home/chy-cpabe/GMSSL_certificate/sm2Certs/SE.cert.pem"
    16. //#define ENCODE_KEY_FILE "/home/chy-cpabe/GMSSL_certificate/sm2Certs/SE.key.pem"
    17. #define CA_CERT_FILE "/home/chy-cpabe/tmp/second/rootcert.pem"
    18. #define SIGN_CERT_FILE "/home/chy-cpabe/tmp/second/sign.pem"
    19. #define SIGN_KEY_FILE "/home/chy-cpabe/tmp/second/sign.key"
    20. #define ENCODE_CERT_FILE "/home/chy-cpabe/tmp/second/encrypt.pem"
    21. #define ENCODE_KEY_FILE "/home/chy-cpabe/tmp/second/encrypt.key"
    22. void ShowCerts(SSL * ssl)
    23. {
    24. X509 *cert;
    25. char *line;
    26. cert = SSL_get_peer_certificate(ssl);
    27. // SSL_get_verify_result()是重点,SSL_CTX_set_verify()只是配置启不启用并没有执行认证,调用该函数才会真证进行证书认证
    28. // 如果验证不通过,那么程序抛出异常中止连接
    29. if(SSL_get_verify_result(ssl) == X509_V_OK){
    30. printf("证书验证通过\n");
    31. }
    32. if (cert != nullptr) {
    33. printf("数字证书信息:\n");
    34. line = X509_NAME_oneline(X509_get_subject_name(cert), nullptr, 0);
    35. printf("证书: %s\n", line);
    36. free(line);
    37. line = X509_NAME_oneline(X509_get_issuer_name(cert), nullptr, 0);
    38. printf("颁发者: %s\n", line);
    39. free(line);
    40. X509_free(cert);
    41. } else
    42. printf("无证书信息!\n");
    43. }
    44. int main(int argc, char **argv) {
    45. int listen_fd = -1; /* TCP监听套接字 */
    46. int accept_fd = -1; /* 已连接TCP套接字 */
    47. struct sockaddr_in server_addr, client_addr;
    48. bzero(&server_addr, sizeof(server_addr));
    49. SSL_CTX *ctx = nullptr; /* SSL会话环境 */
    50. SSL *ssl = nullptr; /* SSL安全套接字 */
    51. socklen_t len;
    52. char buf[MAXBUF]={0}; /* 服务器接收数据buffer */
    53. if( 3!=argc )
    54. {
    55. printf("argcment wrong:ip port\n");
    56. }
    57. SSL_library_init(); /* SSL 库初始化 */
    58. SSLeay_add_ssl_algorithms();
    59. OpenSSL_add_all_algorithms(); /* 载入所有 SSL 算法 */
    60. SSL_load_error_strings(); /* 载入所有 SSL 错误消息 */
    61. // ERR_load_BIO_strings();
    62. //TCP服务器:创建、绑定、监听
    63. if ((listen_fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
    64. perror("socket create wrong\n");
    65. exit(1);
    66. } else
    67. printf("socket created\n");
    68. server_addr.sin_family = PF_INET;
    69. server_addr.sin_port = htons(atoi(argv[2]));
    70. server_addr.sin_addr.s_addr = inet_addr(argv[1]);;
    71. if (bind(listen_fd, (struct sockaddr *) &server_addr, sizeof(struct sockaddr))
    72. == -1) {
    73. perror("bind wrong\n");
    74. exit(1);
    75. } else
    76. printf("binded success\n");
    77. int lisnum = 2;
    78. do{
    79. //使用SSL_CTX_new()创建会话环境,建立连接时要使用协议由TLS_server_method()来定。如果这一步出错,需要查看错误栈来查看原因
    80. if(nullptr == (ctx = SSL_CTX_new( GMTLS_server_method()))) //using sm3, TLSv1_2_method
    81. {
    82. ERR_print_errors_fp(stderr);
    83. break;
    84. }
    85. // SSL_CTX_set_security_level(ctx,0);
    86. // 双向验证
    87. // SSL_VERIFY_PEER---要求对证书进行认证,没有证书也会放行
    88. // SSL_VERIFY_FAIL_IF_NO_PEER_CERT---要求客户端需要提供证书,但验证发现单独使用没有证书也会放行
    89. SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
    90. // 设置信任根证书
    91. if(SSL_CTX_load_verify_locations(ctx, CA_CERT_FILE, nullptr) != 1)
    92. {
    93. printf("SSL_CTX_load_verify_locations error\n");
    94. ERR_print_errors_fp(stderr);
    95. break;
    96. }
    97. // 签名证书和对应私钥
    98. if( 0>=SSL_CTX_use_certificate_file(ctx, SIGN_CERT_FILE, SSL_FILETYPE_PEM/*SSL_FILETYPE_ASN1*/) ) /* 为SSL会话加载用户证书 */
    99. {
    100. printf("SSL_CTX_use_certificate_file error!\n");
    101. ERR_print_errors_fp(stderr);
    102. break;
    103. }
    104. if( 0>=SSL_CTX_use_PrivateKey_file(ctx, SIGN_KEY_FILE, SSL_FILETYPE_PEM/*SSL_FILETYPE_ASN1*/) ) /* 为SSL会话加载用户私钥 */
    105. {
    106. printf("SSL_CTX_use_PrivateKey_file error!\n");
    107. ERR_print_errors_fp(stderr);
    108. break;
    109. }
    110. // 加密证书和对应私钥
    111. if(SSL_CTX_use_certificate_file(ctx, ENCODE_CERT_FILE, SSL_FILETYPE_PEM) <= 0)
    112. {
    113. printf("SSL_CTX_use_certificate_file error!\n");
    114. ERR_print_errors_fp(stderr);
    115. return -1;
    116. }
    117. if(SSL_CTX_use_PrivateKey_file(ctx, ENCODE_KEY_FILE, SSL_FILETYPE_PEM) <= 0)
    118. {
    119. printf("SSL_CTX_use_PrivateKey_file error!\n");
    120. ERR_print_errors_fp(stderr);
    121. return -1;
    122. }
    123. /* 检查用户私钥是否正确 */
    124. if(!SSL_CTX_check_private_key(ctx)) /* 验证私钥和证书是否相符 */
    125. {
    126. printf("SSL_CTX_check_private_key error!\n");
    127. ERR_print_errors_fp(stderr);
    128. break;
    129. }
    130. if (listen(listen_fd, lisnum) == -1) {
    131. perror("listen wrong\n");
    132. exit(1);
    133. } else
    134. printf("begin listen\n");
    135. len = sizeof(struct sockaddr);
    136. /* 等待客户端连上来 */
    137. if ((accept_fd = accept(listen_fd, (struct sockaddr *) &client_addr, &len))
    138. == -1) {
    139. perror("accept wrong\n");
    140. exit(errno);
    141. } else{
    142. printf("server: got connection from %s, port %d, socket %d\n",
    143. inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port),
    144. accept_fd);
    145. }
    146. ssl = SSL_new(ctx); /* 基于 ctx 产生一个新的 SSL */
    147. SSL_set_fd(ssl, accept_fd); /* 将连接用户的 socket 加入到 SSL */
    148. /* 建立 SSL 连接 */
    149. if (SSL_accept(ssl) == -1) {
    150. perror("accept wrong\n");
    151. SSL_shutdown(ssl);
    152. SSL_free(ssl);
    153. ssl= nullptr;
    154. close(accept_fd);
    155. accept_fd=-1;
    156. break;
    157. }
    158. ShowCerts(ssl);
    159. /* 开始处理每个新连接上的数据收发 */
    160. bzero(buf, MAXBUF + 1);
    161. strcpy(buf, "server->client");
    162. /* 发消息给客户端 */
    163. len = SSL_write(ssl, buf, strlen(buf));
    164. if (len <= 0) {
    165. printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buf, errno,
    166. strerror(errno));
    167. goto finish;
    168. } else
    169. printf("消息'%s'发送成功,共发送了%d个字节!\n", buf, len);
    170. bzero(buf, MAXBUF + 1);
    171. /* 接收客户端的消息 */
    172. len = SSL_read(ssl, buf, MAXBUF);
    173. if (len > 0)
    174. printf("接收消息成功:'%s',共%d个字节的数据\n", buf, len);
    175. else
    176. printf("消息接收失败!错误代码是%d,错误信息是'%s'\n",
    177. errno, strerror(errno));
    178. /* 处理每个新连接上的数据收发结束 */
    179. finish:
    180. /* 关闭 SSL 连接 */
    181. SSL_shutdown(ssl);
    182. /* 释放 SSL */
    183. SSL_free(ssl);
    184. ssl = nullptr;
    185. /* 关闭 socket */
    186. close(accept_fd);
    187. accept_fd = -1;
    188. }while(1);
    189. /* 关闭监听的 socket */
    190. close(listen_fd);
    191. listen_fd = -1;
    192. /* 释放 CTX */
    193. SSL_CTX_free(ctx);
    194. ctx = nullptr;
    195. return 0;
    196. }

    客户端代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #define MAXBUF 1024
    12. //#define CA_CERT_FILE "/home/chy-cpabe/GMSSL_certificate/sm2Certs/CA.cert.pem"
    13. //#define CS_CERT_FILE "/home/chy-cpabe/GMSSL_certificate/sm2Certs/CS.cert.pem"
    14. //#define CS_KEY_FILE "/home/chy-cpabe/GMSSL_certificate/sm2Certs/CS.key.pem"
    15. //#define CE_CERT_FILE "/home/chy-cpabe/GMSSL_certificate/sm2Certs/CE.cert.pem"
    16. //#define CE_KEY_FILE "/home/chy-cpabe/GMSSL_certificate/sm2Certs/CE.key.pem"
    17. #define CA_CERT_FILE "/home/chy-cpabe/tmp/first/rootcert.pem"
    18. #define CS_CERT_FILE "/home/chy-cpabe/tmp/first/sign.pem"
    19. #define CS_KEY_FILE "/home/chy-cpabe/tmp/first/sign.key"
    20. #define CE_CERT_FILE "/home/chy-cpabe/tmp/first/encrypt.pem"
    21. #define CE_KEY_FILE "/home/chy-cpabe/tmp/first/encrypt.key"
    22. void ShowCerts(SSL * ssl)
    23. {
    24. X509 *cert;
    25. char *line;
    26. cert = SSL_get_peer_certificate(ssl);
    27. // SSL_get_verify_result()是重点,SSL_CTX_set_verify()只是配置启不启用并没有执行认证,调用该函数才会真证进行证书认证
    28. // 如果验证不通过,那么程序抛出异常中止连接
    29. if(SSL_get_verify_result(ssl) == X509_V_OK){
    30. printf("证书验证通过\n");
    31. }
    32. if (cert != nullptr) {
    33. printf("数字证书信息:\n");
    34. line = X509_NAME_oneline(X509_get_subject_name(cert), nullptr, 0);
    35. printf("证书: %s\n", line);
    36. free(line);
    37. line = X509_NAME_oneline(X509_get_issuer_name(cert), nullptr, 0);
    38. printf("颁发者: %s\n", line);
    39. free(line);
    40. X509_free(cert);
    41. } else
    42. printf("无证书信息!\n");
    43. }
    44. static void PrintData(char *p, char *buf,int len,char *filename)
    45. {
    46. char *name=p;
    47. printf("%s[%d]:\n",p,len);
    48. for (p=buf; p && p++-buf
    49. printf("%02x%c",(unsigned char)p[-1],(!((p-buf)%16) || p-buf==len)?'\n':' ');
    50. // if (filename) FileWrite(name,buf,len,filename);
    51. }
    52. int main(int argc, char **argv)
    53. {
    54. int sock_fd = -1; /* TCP套接字 */
    55. int len = 0; /* SSL会话环境 */
    56. SSL *ssl = nullptr; /* SSL安全套接字 */
    57. struct sockaddr_in ser_addr; /* 服务器地址 */
    58. bzero(&ser_addr, sizeof(ser_addr));
    59. SSL_CTX *ctx = nullptr;
    60. char buffer[MAXBUF + 1];
    61. if( argc != 3 )
    62. {
    63. printf("argcment wrong:ip port content\n");
    64. exit(0);
    65. }
    66. /* SSL 库初始化,参看 ssl-server.c 代码 */
    67. SSL_library_init();
    68. SSLeay_add_ssl_algorithms();
    69. OpenSSL_add_all_algorithms();
    70. SSL_load_error_strings();
    71. // ERR_load_BIO_strings();
    72. do{
    73. /* 申请SSL会话环境 */
    74. if( nullptr==(ctx=SSL_CTX_new(GMTLS_client_method())) ) //使用SSL_CTX_new()创建会话环境,建立连接时要使用协议由TLS_client_method()来定,服务器由对应的TLS_server_method()来定。如果这一步出错,需要查看错误栈来查看原因
    75. {
    76. printf("SSL_CTX_new error!\n");
    77. ERR_print_errors_fp(stderr);
    78. break;
    79. }
    80. // 双向验证
    81. // SSL_VERIFY_PEER---要求对证书进行认证,没有证书也会放行
    82. // SSL_VERIFY_FAIL_IF_NO_PEER_CERT---要求客户端需要提供证书,但验证发现单独使用没有证书也会放行
    83. SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
    84. // if(SSL_CTX_set_cipher_list(ctx, "ECC-SM2-WITH-SM4-SM3") <= 0){
    85. // printf("SSL_CTX_set_cipher_list error!\n");
    86. // ERR_print_errors_fp(stderr);
    87. // exit(1);
    88. // }
    89. // 设置信任根证书
    90. if(SSL_CTX_load_verify_locations(ctx, CA_CERT_FILE, nullptr) != 1)
    91. {
    92. printf("SSL_CTX_load_verify_locations error!\n");
    93. ERR_print_errors_fp(stderr);
    94. exit(1);
    95. }
    96. // 签名证书和对应私钥
    97. if (SSL_CTX_use_certificate_file(ctx, CS_CERT_FILE, SSL_FILETYPE_PEM) <= 0)
    98. {
    99. printf("SSL_CTX_use_certificate_file error!\n");
    100. ERR_print_errors_fp(stderr);
    101. exit(1);
    102. }
    103. if (SSL_CTX_use_PrivateKey_file(ctx, CS_KEY_FILE, SSL_FILETYPE_PEM) <= 0)
    104. {
    105. printf("SSL_CTX_use_PrivateKey_file error!\n");
    106. ERR_print_errors_fp(stderr);
    107. exit(1);
    108. }
    109. // 加密证书和对应私钥
    110. if(SSL_CTX_use_certificate_file(ctx, CE_CERT_FILE, SSL_FILETYPE_PEM) <= 0)
    111. {
    112. printf("SSL_CTX_use_certificate_file error!\n");
    113. ERR_print_errors_fp(stderr);
    114. return -1;
    115. }
    116. if(SSL_CTX_use_PrivateKey_file(ctx, CE_KEY_FILE, SSL_FILETYPE_PEM) <= 0)
    117. {
    118. printf("SSL_CTX_use_PrivateKey_file error!\n");
    119. ERR_print_errors_fp(stderr);
    120. return -1;
    121. }
    122. //判定私钥是否正确
    123. if (!SSL_CTX_check_private_key(ctx)) {
    124. printf("SSL_CTX_check_private_key error!\n");
    125. ERR_print_errors_fp(stderr);
    126. exit(1);
    127. }
    128. // SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
    129. /* 创建一个 socket 用于 tcp 通信 */
    130. if(-1==(sock_fd=socket(AF_INET, SOCK_STREAM, 0)) )
    131. {
    132. printf("creat socket wrong\n");
    133. break;
    134. }
    135. printf("socket created\n");
    136. /* 初始化服务器端(对方)的地址和端口信息 */
    137. ser_addr.sin_family = AF_INET;
    138. ser_addr.sin_port = htons(atoi(argv[2]));
    139. ser_addr.sin_addr.s_addr = inet_addr(argv[1]);
    140. printf("address created\n");
    141. //建立连接
    142. if( -1==(connect(sock_fd, (struct sockaddr *)&ser_addr, sizeof(ser_addr))) )
    143. {
    144. printf("connect wrong\n");
    145. break;
    146. }
    147. printf("server connected\n");
    148. /* 基于 ctx 产生一个新的 SSL */
    149. ssl = SSL_new(ctx);
    150. SSL_set_fd(ssl, sock_fd);
    151. /* 建立 SSL 连接 */
    152. if (SSL_connect(ssl) == -1)
    153. ERR_print_errors_fp(stderr);
    154. else {
    155. printf("The relevant information is as follows:\n");
    156. printf("-->ssl version %s\n",SSL_get_version(ssl));
    157. printf("-->ssleay version %s\n",SSLeay_version(0));
    158. printf("-->Connected with %s encryption\n", SSL_get_cipher(ssl));
    159. ShowCerts(ssl);
    160. }
    161. //导出key和salt
    162. unsigned char buf[16];
    163. int err = -1;
    164. err = SSL_export_keying_material(ssl, buf, 16, nullptr,0, nullptr, 0, 1);
    165. if(err != 1){
    166. printf("SSL_export_keying_material error,err=%d\n",err);
    167. }else{
    168. PrintData("SSL_export_keying_material", (char*)buf, 16, nullptr);
    169. }
    170. /* 接收对方发过来的消息,最多接收 MAXBUF 个字节 */
    171. bzero(buffer, MAXBUF + 1);
    172. /* 接收服务器来的消息 */
    173. len = SSL_read(ssl, buffer, MAXBUF);
    174. if (len > 0)
    175. printf("接收消息成功:'%s',共%d个字节的数据\n",
    176. buffer, len);
    177. else {
    178. printf
    179. ("消息接收失败!错误代码是%d,错误信息是'%s'\n",
    180. errno, strerror(errno));
    181. goto finish;
    182. }
    183. bzero(buffer, MAXBUF + 1);
    184. strcpy(buffer, "from client->server");
    185. /* 发消息给服务器 */
    186. len = SSL_write(ssl, buffer, strlen(buffer));
    187. if (len < 0)
    188. printf
    189. ("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n",
    190. buffer, errno, strerror(errno));
    191. else
    192. printf("消息'%s'发送成功,共发送了%d个字节!\n",
    193. buffer, len);
    194. /* 处理每个新连接上的数据收发结束 */
    195. finish:
    196. /* 关闭 SSL 连接 */
    197. SSL_shutdown(ssl);
    198. /* 释放 SSL */
    199. SSL_free(ssl);
    200. ssl = nullptr;
    201. }while(0);
    202. /* 关闭socket */
    203. close(sock_fd);
    204. sock_fd = -1;
    205. /* 释放 CTX */
    206. SSL_CTX_free(ctx);
    207. ctx = nullptr;
    208. return 0;
    209. }

    注意事项

  • 相关阅读:
    【方案分享】抖音运营攻略:平台规则、爆款涨粉、运营技巧、内容变现.pdf(附下载链接)...
    SQL Server查询优化
    Java基础(第一期):IDEA的下载和安装(步骤图) && 项目结构的介绍 && 项目、模块、类的创建。第一个代码的实现
    干货|数据资产评估的基本方法和选择方法
    我把微信群聊机器人项目开源
    交换机的工作原理以及搭建局域网划分VLAN
    敏捷开发的实施要素和实现敏捷的实际改进
    AJAX【AJAX实现省市联动 、AJAX跨域问题、AJAX实现搜索联想 自动补全、 附录:HTTP状态信息】
    Windows端通过Vscode或PowerShell连接linux服务器,打开图形界面的程序
    微信公众号运营的那些实用技巧,你了解多少?
  • 原文地址:https://blog.csdn.net/CHYabc123456hh/article/details/126352458