基于X.509证书和SSL协议的身份认证过程实现

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介:

上周帮一个童鞋做一个数字认证的实验,要求是编程实现一个基于X.509证书认证的过程,唉!可怜我那点薄弱的计算机网络安全的知识啊!只得恶补一下了。

首先来看看什么是X.509。所谓X.509其实是一种非常通用的证书,什么是证书?唉!这么说吧!当两个人需要进行远程通信而又不想让第三个人知 道时就必须建立一种安全措施,因为看不到对方的脸,又不能通过电话直接询问对方,就得想点别的办法,比如我设计一个密码,让后发短信告诉你,这样当我们在 网上交流之前就可以对一下密码,暗号之类的。确认后就可以证明你的身份了。这个证书就相当于这里的密码,只是确实比密码要复杂一些,想了解的朋友可以 google之~~

那么什么是SSL呢?SSL是一种网络通信的安全协议,在传输层对网络连接进行加密,简单点说就是提过一种方法使我们通过网络进行通信的安全性得到提高。而X.509证书认证的过程就可以通过这个协议来实现。

好了,知道了这些就然我们来开始写这个程序吧!慢着,如果实现这个SSL和X.509呢?我们貌似还是不知道啊!好吧,既然是一种加密通信过程肯定 和加密分不开吧,随便查了一下,SSL涉及到的加密方法就不下数十种,而且极其艰深复杂,难道我要自己实现这个过程?自己构建X.509证书?当然不会, 互联网就是好啊!让我发现了存在OpenSSL这么个东西,让我们感谢Eric A. Young和Tim J. Hudson这两个人吧!因为他们在1995年就开始做我上面想做的事情了,而且写出了OpenSSL这个没有太多限制的开放源代码的软件包。有了这玩意 什么事都好办了。

我先从网上下了openssl-0.9.8的压缩包,然后琢磨了两个多小时终于明白如何安装这么个软件包了。我把自己的安装心得记录下来大家一起分享。

在使用这个软件包之前需要安装PERL组件——ActivePerl-5.8.0.806-MSWin32-x86(PERL和OpenSSL网上 有很多免费下载的,这里我就不给出下载地址了),这个安装倒很简单,直接使用安装包就行了。判断perl是否安装成功的方法是通过命令行进入到perl安 装目录下的\eg目录里,执行perl example.pl命令,如果显示“Hello from ActivePerl!”,则说明Perl安装成功。然后我们开始安装OpenSSL。

1、将openssl.0.9.8.tar.gz解压到d:盘下。

2、打开命令行窗口进入d: \openssl-0.9.8目录下键入以下命令:perl Configure VC-WIN32。

clip_image001

3、然后键入ms\do_ms命令。

clip_image001[6]

4、然后键入nmake –f ms\ntdll.mak会成功编译很多c文件,如果不成功的话一般就是提示“cl”无法找到之类的错误,这时就需要在系统环境变量PATH里加入VC的bin路径,这样才能找到“cl”命令。

5、接着键入mkdir c:\caroot,这样就会在C盘根目录下生成一个caroot文件夹。

6、然后需要在系统环境变量PATH路径中加入openssl-0.9.8\out32dll路径,并在VC(我使用的是VC编译器)中把 include路径增加一个:D:\openssl-0.9.8\include,把library路径增加一个:D:\openssl-0.9.8 \out32dll,将D:\openssl-0.9.8\apps下的openssl.cnf文件拷贝到c:\caroot目录下。

到这里可以说我们的安装已经完成了,下面我们需要生成几个证书和密钥,密钥是用来加密的,证书是用来认证的。比如服务器证书、密钥,客户端证书、密 钥。但这里我们漏了一个最重要的证书和密钥,就是CA证书和密钥。CA是个什么东东呢?这个解释起来很麻烦,他就像一个中间证明人,证明两方的身份都是真 实可信的,这样双方拿着证书才能相互信任,详细解释可以参看这里:http://baike.baidu.com/view/23691.htm#7,维基百科的解释更加详细,不过是英文的我觉得喜欢英文的朋友可以看看:http://en.wikipedia.org/wiki/Certificate_authority

好吧,让我们把这些该死的证书密钥都生成然后开始编码吧:

在上面C:\caroot目录下(其实可以不在这目录下)输入如下:

#产生CA自签名证书

openssl.exe genrsa -out private\ca.key -rand private\.rnd -des 2048

openssl.exe req -new -x509 -days 3650 -key private\ca.key -out private\ca.crt -config openssl.cnf

openssl.exe x509 -in private\ca.crt -noout -text

 

#产生server的证书过程

openssl.exe genrsa -out private\server.key 1024

openssl.exe req -new -key private\server.key -out newcerts\server.csr -config openssl.cnf

openssl.exe ca -in newcerts\server.csr -cert private\ca.crt -keyfile private\ca.key

-config openssl.cnf -policy policy_anything -out certs\server.crt

openssl.exe x509 -in certs\server.crt -noout -text

 

#产生proxy的证书过程

openssl.exe genrsa -out private\proxy.key 1024

openssl.exe req -new -key private\proxy.key -out newcerts\proxy.csr -config openssl.cnf

openssl.exe ca -in newcerts\proxy.csr -cert private\ca.crt -keyfile private\ca.key -config openssl.cnf -policy policy_anything -out certs\proxy.crt

openssl.exe x509 -in certs\proxy.crt -noout -text

 

#产生client的证书过程

openssl.exe genrsa -out private\client.key 1024

openssl.exe req -new -key private\client.key -out newcerts\client.csr -config openssl.cnf

openssl.exe ca -in newcerts\client.csr -cert private\ca.crt -keyfile private\ca.key -config openssl.cnf -policy policy_anything -out certs\client.crt

openssl.exe x509 -in certs\client.crt -noout -text

 

上面的命令中会给出提示让用户输入一些证书的信息,只要正常输入就可以了。执行上述操作后C:\caroot目录如下:

image

private目录如下:

image

 

 

newcerts目录如下:

image

certs目录如下:

image

其中证书:

ca.crt为自签名证书;

server.crt,server.key为服务器端的证书和私钥文件;

proxy.crt,proxy.key为代理服务器端的证书和私钥文件;

client.crt,client.key为客户端的证书和私钥文件。

乱七八糟的事情终于做完了,下面总算可以开始编码了。看了一下实验要求,要编写简单的Client程序和Server程序,实现Client程序与Server程序之间基于X509证书和SSL协议身份认证和通信加密,服务器能够接收并且显示客户端发送来的文字消息。

看来需要两个程序,一个服务端的,一个客户端的。

具体编程大家直接看代码就行了,涉及到socket通信,其实相当简单,懂一点点就行了,我这里就不要王婆卖瓜了,直接上代码吧。

客户端程序代码:


  
  
  1. //client  
  2. #include <winsock2.h>  
  3. #include <conio.h>  
  4. #include <stdio.h>  
  5. #include "openssl/x509.h"  
  6. #include "openssl/ssl.h"  
  7. #include "openssl/err.h"  
  8. #include "openssl/rand.h" 
  9.  
  10. #define PORT       1111  
  11. #define SERVER     "127.0.0.1"  
  12. #define CACERT     "ca.crt"  
  13. #define MYCERTF    "yuliding.crt"  
  14. #define MYKEYF     "yuliding.key"  
  15. #define MSGLENGTH  1024 
  16.  
  17. int main()  
  18. {  
  19.     WSADATA wsadata;  
  20.     WSAStartup(MAKEWORD(2,2), &wsadata);  
  21.     sockaddr_in sin;  
  22.     int seed_int[100]; /*存放随机序列*/ 
  23.  
  24.     SSL*ssl;  
  25.     SSL_METHOD *meth;  
  26.     SSL_CTX *ctx; 
  27.  
  28.     //SSL初始化  
  29.     OpenSSL_add_ssl_algorithms();  
  30.     //SSL错误信息初始化  
  31.     SSL_load_error_strings(); 
  32.  
  33.     //创建本次会话所使用的协议  
  34.     meth = TLSv1_client_method();  
  35.     //申请SSL会话的环境  
  36.     ctx = SSL_CTX_new(meth);  
  37.     if (NULL == ctx)  
  38.         exit(1); 
  39.  
  40.     //设置会话的握手方式并加载CA证书  
  41.     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);  
  42.     SSL_CTX_load_verify_locations(ctx, CACERT, NULL);  
  43.     //加载自己的证书  
  44.     if (0 &gt;= SSL_CTX_use_certificate_file(ctx, MYCERTF, SSL_FILETYPE_PEM)) {  
  45.         ERR_print_errors_fp(stderr);  
  46.         exit(1);  
  47.     }  
  48.     //加载自己的私钥  
  49.     if (0 &gt;= SSL_CTX_use_PrivateKey_file(ctx, MYKEYF, SSL_FILETYPE_PEM)) {  
  50.         ERR_print_errors_fp(stderr);  
  51.         exit(1);  
  52.     }  
  53.     //检查自己的证书和私钥是否匹配  
  54.     if (!SSL_CTX_check_private_key(ctx)) {  
  55.         printf("Private key does not match the certificate public key\n");  
  56.         exit(1);  
  57.     }  
  58.     /*构建随机数生成机制,WIN32平台必需*/  
  59.     srand((unsigned)time(NULL));  
  60.     for (int i = 0; i < 100; i++)  
  61.         seed_int[i] = rand();  
  62.     RAND_seed(seed_int, sizeof(seed_int)); 
  63.  
  64.     //加密方式  
  65.     SSL_CTX_set_cipher_list(ctx, "RC4-MD5");  
  66.     //处理握手多次  
  67.     SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); 
  68.  
  69.     /*以下是正常的TCP socket建立过程 .............................. */  
  70.     SOCKET sock;  
  71.     printf("Begin tcp socket...\n");  
  72.     sock = socket(AF_INET, SOCK_STREAM, 0);  
  73.     if (sock == INVALID_SOCKET) {  
  74.         printf("SOCKET有问题. \n");  
  75.     } 
  76.  
  77.     memset(&sin, '\0'sizeof(sin));  
  78.     sin.sin_family = AF_INET;  
  79.     sin.sin_addr.s_addr = inet_addr(SERVER); /* Server IP */  
  80.     sin.sin_port = htons(PORT); /* Server Port number */ 
  81.  
  82.     int icnn = connect(sock, (sockaddr *)&sin, sizeof(sin));  
  83.     if (icnn == SOCKET_ERROR) {  
  84.         printf("连不上服务器\n", GetLastError());  
  85.         exit(1);  
  86.     } 
  87.  
  88.     /* TCP 链接已建立.开始 SSL 握手过程.......................... */  
  89.     //绑定套接字  
  90.     ssl = SSL_new(ctx);  
  91.     if (NULL == ssl)  
  92.         exit(1);  
  93.     if (0 >= SSL_set_fd(ssl, sock)) {  
  94.         printf("Attach to Line fail!\n");  
  95.         exit(1);  
  96.     }  
  97.     //SSL握手  
  98.     //SSL_connect(ssl);  
  99.     int k = SSL_connect(ssl);  
  100.     if (0 &gt;= k) {  
  101.         printf("%d\n", k);  
  102.         printf("SSL connect fail!\n");  
  103.         exit(1);  
  104.     }  
  105.     printf("连接服务器成功\n"); 
  106.  
  107.     char sendmsg[MSGLENGTH] = "\0";  
  108.     char revmsg[MSGLENGTH] = "\0"
  109.  
  110.     int err = SSL_read(ssl, revmsg, sizeof(revmsg));  
  111.     revmsg[err] = '\0';  
  112.     printf("%s\n", revmsg); 
  113.  
  114.     while (1) {  
  115.         printf("请输入所要发送的数据:\n");  
  116.         scanf("%s", sendmsg);  
  117.         SSL_write(ssl, sendmsg, strlen(sendmsg));  
  118.         printf("发送消息“ %s ”成功!\n", sendmsg);  
  119.     } 
  120.  
  121.     //关闭套接字  
  122.     SSL_shutdown(ssl);  
  123.     SSL_free(ssl);  
  124.     SSL_CTX_free(ctx);  
  125.     closesocket(sock);  
  126.     WSACleanup();  
  127.     getch();  
  128.     return 0;  

服务端程序代码:


  
  
  1. //server  
  2. #include <winsock2.h>  
  3. #include <conio.h>  
  4. #include <stdio.h>  
  5. #include <winsock.h>  
  6. #include "openssl/x509.h"  
  7. #include "openssl/ssl.h"  
  8. #include "openssl/err.h" 
  9.  
  10. #define MSGLENGTH      1024  
  11. #define PORT           1111  
  12. #define CACERT         "ca.crt"  
  13. #define SVRCERTF       "server.crt"  
  14. #define SVRKEYF        "server.key" 
  15.  
  16. int main()  
  17. {  
  18.     WSADATA wsaData;  
  19.     WSAStartup(MAKEWORD(2,2), &wsaData);  
  20.     SOCKET sock;  
  21.     SSL_METHOD *meth;  
  22.     SSL_CTX* ctx;  
  23.     SSL* ssl;  
  24.     //SSL初始化  
  25.     OpenSSL_add_ssl_algorithms();  
  26.     //SSL错误信息初始化  
  27.     SSL_load_error_strings(); 
  28.  
  29.     //创建本次会话所使用的协议  
  30.     meth = TLSv1_server_method();  
  31.     //申请SSL会话的环境  
  32.     ctx = SSL_CTX_new(meth);  
  33.     if (NULL == ctx)  
  34.         exit(1); 
  35.  
  36.     //设置会话的握手方式并加载CA证书  
  37.     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);  
  38.     SSL_CTX_load_verify_locations(ctx, CACERT, NULL);  
  39.     //加载服务器端的证书  
  40.     if (0 &gt;= SSL_CTX_use_certificate_file(ctx, SVRCERTF, SSL_FILETYPE_PEM)) {  
  41.         ERR_print_errors_fp(stderr);  
  42.         exit(1);  
  43.     }  
  44.     //加载服务器端的私钥  
  45.     if (0 &gt;= SSL_CTX_use_PrivateKey_file(ctx, SVRKEYF, SSL_FILETYPE_PEM)) {  
  46.         ERR_print_errors_fp(stderr);  
  47.         exit(1);  
  48.     }  
  49.     //检查服务器端的证书和私钥是否匹配  
  50.     if (!SSL_CTX_check_private_key(ctx)) {  
  51.         printf("Private key does not match the certificate public key\n");  
  52.         exit(1);  
  53.     } 
  54.  
  55.     //加密方式  
  56.     SSL_CTX_set_cipher_list(ctx, "RC4-MD5");  
  57.     //处理握手多次  
  58.     SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); 
  59.  
  60.     /*以下是正常的TCP socket建立过程 .............................. */  
  61.     printf("Begin tcp socket...\n");  
  62.     sock = socket(AF_INET, SOCK_STREAM, 0);  
  63.     if (sock == INVALID_SOCKET) {  
  64.         printf("SOCKET有问题. \n");  
  65.         return 0;  
  66.     } 
  67.  
  68.     sockaddr_in addr;  
  69.     memset(&addr, '\0'sizeof(addr));  
  70.     addr.sin_family = AF_INET;  
  71.     addr.sin_port = htons(PORT); /* Server Port number */  
  72.     addr.sin_addr.s_addr = INADDR_ANY; 
  73.  
  74.     //绑定sock  
  75.     int nResult = bind(sock, (sockaddr *)&addr, sizeof(addr));  
  76.     if (nResult == SOCKET_ERROR) {  
  77.         printf("绑定SOCKET有问题. \n");  
  78.         return 0;  
  79.     }  
  80.     printf("服务器启动成功,端口:%d\n正在等待连接\n", PORT); 
  81.  
  82.     /*接受TCP链接*/  
  83.     sockaddr_in sa_cli;  
  84.     int err = listen(sock, 5);  
  85.     if (-1 == err)  
  86.         exit(1);  
  87.     int client_len = sizeof(sa_cli);  
  88.     int ss = accept(sock, (struct sockaddr *) &sa_cli, &client_len);  
  89.     if (ss == -1) {  
  90.         exit(1);  
  91.     }  
  92.     closesocket(sock);  
  93.     printf("Connection from %d, port %d\n", sa_cli.sin_addr.s_addr, sa_cli.sin_port); 
  94.  
  95.     /* TCP 链接已建立.开始 SSL 握手过程.......................... */  
  96.     //绑定套接字  
  97.     ssl = SSL_new(ctx);  
  98.     if (NULL == ssl)  
  99.         exit(1);  
  100.     if (0 &gt;= SSL_set_fd(ssl, ss)) {  
  101.         printf("Attach to Line fail!\n");  
  102.         exit(1);  
  103.     }  
  104.     //SSL握手  
  105.     //SSL_accept(ssl);  
  106.     int k = SSL_accept(ssl);  
  107.     if (0 &gt;= k) {  
  108.         printf("%d\n", k);  
  109.         printf("SSL connect fail!\n");  
  110.         exit(1);  
  111.     }  
  112.     //进行信息验证  
  113.     X509 *client_cert;  
  114.     client_cert = SSL_get_peer_certificate(ssl); 
  115.  
  116.     printf("发现客户端尝试连接\n");  
  117.     if (client_cert != NULL) {  
  118.         printf ("Client certificate:\n"); 
  119.  
  120.         //读取证书subject名并显示  
  121.         char *str = X509_NAME_oneline(X509_get_subject_name(client_cert), 0, 0);  
  122.         if (NULL == str) {  
  123.             printf("认证出错!\n");  
  124.             exit(1);  
  125.         }  
  126.         printf("subject: %s\n", str);  
  127.         //读取证书的issuer名并显示  
  128.         str = X509_NAME_oneline(X509_get_issuer_name(client_cert), 0, 0);  
  129.         if (NULL == str) {  
  130.             printf("证书名为空\n");  
  131.             exit(1);  
  132.         }  
  133.         printf("issuer: %s\n", str);  
  134.         printf("连接成功\n"); 
  135.  
  136.         X509_free (client_cert);/*如不再需要,需将证书释放 */  
  137.         OPENSSL_free(str);  
  138.     }  
  139.     else {  
  140.         printf("找不到客户端的认证证书\n");  
  141.         exit(1);  
  142.     } 
  143.  
  144.     char buf[MSGLENGTH];  
  145.     SSL_write(ssl, "Server is connect to you!\n", strlen("Server is connect to you!\n"));  
  146.     printf("Listen to the client: \n");  
  147.     while (1) {  
  148.         err = SSL_read(ssl, buf, sizeof(buf));  
  149.         buf[err] = '\0';  
  150.         printf("%s\n", buf);  
  151.     } 
  152.  
  153.     //关闭套接字  
  154.     SSL_shutdown(ssl);  
  155.     SSL_free(ssl);  
  156.     SSL_CTX_free(ctx);  
  157.     WSACleanup();  
  158.     getch();  
  159.     return 0;  

编写完后后首先运行服务端程序,然后运行客户端程序,效果如下:

连接成功后服务端的状态如下:

clip_image002[7]

红色部分为我在生成证书文件时输入的一些信息,具体的你可以通过我上面讲解建立证书时试验一下。这里我通过代码把这些证书信息打印出来是为了判断获取的证书是否正确。

 

连接成功后客户端的状态:

clip_image004

 

这样,就可以实现通过客户端向服务端发送信息,如下:

clip_image006

clip_image008

细心的朋友可以发现上面我显示Connection from后面貌似是一串乱码,其实不然,那是一串IP地址,只不过是反序排列的,我曾经在做SIP TRUNK项目时也遇到过这个问题,感兴趣的朋友可以自己写个转义程序把他转成IP地址试试看。

最后提醒一点,因为我的代码中把证书和密钥文件的目录设为当前目录了,所以想要程序正确运行必须把证书文件和密钥文件拷贝到当前工程的目录下,如下:

image

客户端是一样的。或者你可以把目录改到你生成证书和密钥的目录下。

可以看见,上面的程序有众多漏洞和缺陷,如果有朋友想使用的话请一定仔细debug一下,把很多判断的条件加上,这里我就偷下懒罗~~分享快乐~~










本文转自 h2appy  51CTO博客,原文链接:http://blog.51cto.com/h2appy/1181234,如需转载请自行联系原作者
目录
相关文章
|
21天前
|
算法 安全 网络安全
阿里云SSL证书双11精选,WoSign SSL国产证书优惠
2024阿里云11.11金秋云创季活动火热进行中,活动月期间(2024年11月01日至11月30日)通过折扣、叠加优惠券等多种方式,阿里云WoSign SSL证书实现优惠价格新低,DV SSL证书220元/年起,助力中小企业轻松实现HTTPS加密,保障数据传输安全。
561 3
阿里云SSL证书双11精选,WoSign SSL国产证书优惠
|
27天前
|
算法 安全 数据建模
阿里云SSL证书限时优惠,WoSign DV证书220元/年起
2024年11月01日至11月30日,阿里云SSL证书限时优惠,部分证书产品新老同享75折起;阿里云用户通过完成个人或企业实名认证,还可领取不同额度的满减优惠券!通过优惠折扣、叠加满减优惠券等多种方式,阿里云WoSign SSL证书将实现优惠价格新低,DV SSL证书220元/年起!
607 5
阿里云SSL证书限时优惠,WoSign DV证书220元/年起
|
2月前
|
负载均衡 算法 网络安全
阿里云WoSign SSL证书申请指南_沃通SSL技术文档
阿里云平台WoSign品牌SSL证书是由阿里云合作伙伴沃通CA提供,上线阿里云平台以来,成为阿里云平台热销的国产品牌证书产品,用户在阿里云平台https://www.aliyun.com/product/cas 可直接下单购买WoSign SSL证书,快捷部署到阿里云产品中。
2256 8
阿里云WoSign SSL证书申请指南_沃通SSL技术文档
|
14天前
|
网络安全
给网站免费申请SSL证书
为网站申请免费SSL证书是提升安全性的关键步骤。本文简要介绍如何通过JoySSL申请并部署免费SSL证书,包括选择证书类型、提交申请、验证域名、下载及安装证书等步骤,同时提醒注意备份证书、定期检查状态和更新服务器配置。
|
18天前
|
存储 安全 网络安全
SSL网络安全证书,守护您的数字世界
SSL证书的应用场景广泛,它是保护网络通信安全的重要手段。无论是个人用户还是企业组织,都应该认识到SSL证书的重要性,并采取适当的措施来部署和使用SSL证书,以保护自己的数据和隐私不受侵害。
|
25天前
|
算法 数据建模 网络安全
阿里云SSL证书2024双11优惠,WoSign DV证书220元/年起
2024阿里云11.11金秋云创季火热进行中,活动月期间(2024年11月01日至11月30日),阿里云SSL证书限时优惠,部分证书产品新老同享75折起;通过优惠折扣、叠加满减优惠券等多种方式,阿里云WoSign SSL证书将实现优惠价格新低,DV SSL证书220元/年起。
585 5
|
24天前
|
网络协议 应用服务中间件 网络安全
2024阿里云免费版SSL证书申请流程,跟着教程一步步,非常简单!
2024年最新阿里云免费SSL证书申请流程,品牌为Digicert,每个阿里云账号可免费申请20张单域名证书,免费时长为3个月。申请流程包括登录数字证书管理服务控制台、创建证书、域名验证和下载证书。详情请参考阿里云官方页面。
291 2
|
2月前
|
数据建模 网络安全
阿里云申请SSL证书价格多少钱一年?免费版和付费版价格手动整理
阿里云SSL证书提供多种类型和品牌的证书选择,包括免费和付费选项。付费证书如WoSign单域名SSL证书238元/年,DigiCert通配符DV证书1500元/年,GlobalSign企业型1864元/年。免费证书由Digicert提供,有效期3个月,适用于单域名。更多详情见阿里云官网。
453 1
|
2月前
|
算法 小程序 网络安全
阿里云WoSign SSL证书,RSA和国密有什么区别?_沃通SSL技术文档
阿里云WoSign品牌SSL证书为用户提供国密合规SM2算法SSL证书、全球信任RSA算法SSL证书,全球信任、国密合规,能够满足阿里云平台用户不同的SSL证书应用需求。那么阿里云WoSign SSL证书分别提供的RSA算法和国密算法,有什么区别呢?
613 6
|
1月前
|
算法 安全 数据建模
2024阿里云金秋云创季,WoSign SSL证书限时大促
2024阿里云金秋云创季正式拉开活动序幕,活动月期间(2024年11月01日至11月30日)通过折扣、叠加优惠券等多种方式,阿里云WoSign SSL证书将实现优惠价格新低,DV SSL证书220元/年起,助力中小企业轻松实现HTTPS加密,保障数据传输安全。
765 0