1、前言

   最近工作涉及到https,需要修改nginx的openssl模块,引入keyless方案。关于keyless可以参考CloudFlare的官方博客:

https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/?utm_source=tuicool&utm_medium=referral

在openssl的基础上修改私钥校验过程,因此需要对openssl的认证认证流程需要熟悉一下。SSL中涉及到很多概念,开始都不清楚,例如CA,数字签名、数字证书等,本文主要是总结SSL认证的基础知识,openssl的单向和双向认证流程,并写代码测试。

2、基础知识

  SSL:Secure Socket Layer,安全套接字层,它位于TCP层与Application层之间。提供对Application数据的加密保护(密文),完整性保护(不被篡改)等安全服务,它缺省工作在TCP 443 端口,一般对HTTP加密,即俗称的HTTPS。

  TLS:Transport Layer Secure,更关注的是提供安全的传输服务,它很灵活,如果可能,它可以工作在TCP,也可以UDP (DTLS),也可以工作在数据链路层,比如802.1x EAP-TLS。

关于SSL/TSL可以参考:http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html

  公钥:大家公用的,可以通过电子邮件发布,通过网站让别人下载,公钥其用来加密和验章。

  私钥:就是自己的私有的,必须非常小心保存,最好加上 密码,私钥是用来解密和签章。

  数字签名:将报文按双方约定的HASH算法计算得到一个固定位数的报文摘要。在数学上保证:只要改动报文中任何一位,重新计算出的报文摘要值就会与原先的值不相符。这样就保证了报文的不可更改性。将该报文摘要值用发送者的私人密钥加密,然后连同原报文一起发送给接收者,而产生的报文即称数字签名。关于数字签名参考:http://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature.htmlhttp://www.youdzone.com/signature.html

  数字证书:数字证书就是互联网通讯中标志通讯各方身份信息的一系列数据,提供了一种在Internet上验证您身份的方式,其作用类似于司机的驾驶执照或日常生活中的身份证。它是由一个由权威机构-----CA机构,又称为证书授权(Certificate Authority)中心发行的,人们可以在网上用它来识别对方的身份。数字证书是一个经证书授权中心数字签名的包含公开密钥拥有者信息以及公开密钥的文件。最简单的证书包含一个公开密钥、名称以及证书授权中心的数字签名。

参考:http://blog.csdn.net/oscar999/article/details/9364101

CA:Certificate Authority,证书授权中心。是一个单位,来管理发放数字证书的。由它发放的证书就叫 CA 证书,以区别于个人使用工具随意生成的数字证书,查看 CA 证书,里面有两项重要内容,一个是颂发给谁,另一个是由谁颂发的。

参考:http://blog.csdn.net/mostone/article/details/22302035

SSL/TLS协议的基本思路是采用公钥加密法,也就是说,客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。

3、认证流程

单向认证:只需要验证SSL服务器身份,不需要验证SSL客户端身份。

双向认证:要求服务器和客户端双方都有证书,客户端需要校验服务端,服务端也需要校验客户端。

SSL双向认证和SSL单向认证的区别

  双向认证 SSL 协议要求服务器和用户双方都有证书。单向认证 SSL 协议不需要客户拥有CA证书,具体的过程相对于上面的步骤,只需将服务器端验证客户证书的过程去掉,以及在协商对称密码方案,对称通话密钥时,服务器发送给客户的是没有加过密的(这并不影响 SSL 过程的安全性)密码方案。这样,双方具体的通讯内容,就是加过密的数据,如果有第三方攻击,获得的只是加密的数据,第三方要获得有用的信息,就需要对加密的数据进行解密,这时候的安全就依赖于密码方案的安全。而幸运的是,目前所用的密码方案,只要通讯密钥长度足够的长,就足够的安全。这也是我们强调要求使用128位加密通讯的原因。

  一般Web应用都是采用SSL单向认证的,原因很简单,用户数目广泛,且无需在通讯层对用户身份进行验证,一般都在应用逻辑层来保证用户的合法登入。但如果是企业应用对接,情况就不一样,可能会要求对客户端(相对而言)做身份验证。这时就需要做SSL双向认证。

参考:

http://blog.csdn.net/duanbokan/article/details/50847612

http://blog.csdn.net/it_man/article/details/24698093

4、测试代码

证书生成过程:

(1)自签CA证书

#生成根证书私钥(pem文件)
openssl genrsa -out cakey.pem
#生成根证书签发申请文件(csr文件)
openssl req -new -key cakey.pem -out ca.csr -subj "/C=CN/ST=myprovince/L=mycity/O=myorganization/OU=mygroup/CN=myCA"
#自签发根证书(cer文件)
openssl x509 -req -days -sha1 -extensions v3_ca -signkey cakey.pem -in ca.csr -out cacert.pem

(2)服务端私钥和证书

#生成服务端私钥
openssl genrsa -out key.pem
#生成证书请求文件
openssl req -new -key key.pem -out server.csr -subj "/C=CN/ST=myprovince/L=mycity/O=myorganization/OU=mygroup/CN=myServer"
#使用根证书签发服务端证书
openssl x509 -req -days -sha1 -extensions v3_req -CA ../CA/cacert.pem -CAkey ../CA/cakey.pem -CAserial ca.srl -CAcreateserial -in server.csr -out cert.pem
#使用CA证书验证server端证书
openssl verify -CAfile ../CA/cacert.pem cert.pem

(3)客户端私钥和证书

#生成客户端私钥
openssl genrsa -out key.pem
#生成证书请求文件
openssl req -new -key key.pem -out client.csr -subj "/C=CN/ST=myprovince/L=mycity/O=myorganization/OU=mygroup/CN=myClient"
#使用根证书签发客户端证书
openssl x509 -req -days -sha1 -extensions v3_req -CA ../CA/cacert.pem -CAkey ../CA/cakey.pem -CAserial ../server-cert/ca.srl -in client.csr -out cert.pem
#使用CA证书验证客户端证书
openssl verify -CAfile ../CA/cacert.pem cert.pem

验证CA证书出现错误处理:

http://stackoverflow.com/questions/19726138/openssl-error-18-at-0-depth-lookupself-signed-certificate

单向认证:

客户端代码:不需要配置证书和私钥

 #include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <openssl/ssl.h>
#include <openssl/err.h> #define MAXBUF 1024 void ShowCerts(SSL * ssl)
{
X509 *cert;
char *line;
cert = SSL_get_peer_certificate(ssl);
if (cert != NULL) {
printf("数字证书信息:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), , );
printf("证书: %s\n", line);
free(line);
line = X509_NAME_oneline(X509_get_issuer_name(cert), , );
printf("颁发者: %s\n", line);
free(line);
X509_free(cert);
} else {
printf("无证书信息!\n");
}
} int main(int argc, char **argv)
{
int sockfd, len;
struct sockaddr_in dest;
char buffer[MAXBUF + ];
SSL_CTX *ctx;
SSL *ssl; if (argc != ) {
printf("参数格式错误!正确用法如下:\n\t\t%s IP地址 端口\n\t比如:\t%s 127.0.0.1 80\n此程序用来从某个"
"IP 地址的服务器某个端口接收最多 %d 个字节的消息.\n", argv[], argv[], MAXBUF);
exit();
} /*SSL初始化*/
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ctx = SSL_CTX_new(SSLv3_client_method()); if ((sockfd = socket(AF_INET, SOCK_STREAM, )) < ) {
perror("Socket");
exit(errno);
} bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(atoi(argv[]));
if (inet_aton(argv[], (struct in_addr *) &dest.sin_addr.s_addr) == ) {
perror(argv[]);
exit(errno);
} if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != ) {
perror("Connect ");
exit(errno);
}
printf("connectd server successly\n"); ssl = SSL_new(ctx);
SSL_set_fd(ssl, sockfd);
if (SSL_connect(ssl) == -) {
ERR_print_errors_fp(stderr);
} else {
printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
ShowCerts(ssl);
} bzero(buffer, MAXBUF + );
len = SSL_read(ssl, buffer, MAXBUF);
if (len > ) {
printf("接收消息成功:'%s',共%d个字节的数据\n", buffer, len);
} else {
printf("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno));
goto finish;
}
bzero(buffer, MAXBUF + );
strcpy(buffer, "from client->server"); len = SSL_write(ssl, buffer, strlen(buffer));
if (len < ) {
printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buffer, errno, strerror(errno));
} else {
printf("消息'%s'发送成功,共发送了%d个字节!\n", buffer, len);
} finish:
SSL_shutdown(ssl);
SSL_free(ssl);
close(sockfd);
SSL_CTX_free(ctx);
return ;
}

服务端代码:

 #include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h> #define MAXBUF 1024
#define SERVER_CERT "/home/waf/test/cert/server-cert/cert.pem"
#define SERVER_KEY "/home/waf/test/cert/server-cert/key.pem" int main(int argc, char **argv)
{
int sockfd, new_fd;
int reuse = ;
socklen_t len;
struct sockaddr_in my_addr, their_addr;
unsigned int myport, lisnum;
char buf[MAXBUF + ];
SSL_CTX *ctx; if (argv[]) {
myport = atoi(argv[]);
} else {
myport = ;
} if (argv[]) {
lisnum = atoi(argv[]);
} else {
lisnum = ;
} SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ctx = SSL_CTX_new(SSLv3_server_method());
if (ctx == NULL) {
ERR_print_errors_fp(stdout);
exit();
} /*加载公钥证书*/
if (SSL_CTX_use_certificate_file(ctx, SERVER_CERT, SSL_FILETYPE_PEM) <= ) {
ERR_print_errors_fp(stdout);
exit();
} /*设置私钥*/
if (SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY, SSL_FILETYPE_PEM) <= ) {
printf("use private key fail.\n");
ERR_print_errors_fp(stdout);
exit();
} if (!SSL_CTX_check_private_key(ctx)) {
ERR_print_errors_fp(stdout);
exit();
}
if ((sockfd = socket(PF_INET, SOCK_STREAM, )) == -) {
perror("socket");
exit();
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < ){
printf("setsockopet error\n");
return -;
}
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = PF_INET;
my_addr.sin_port = htons(myport);
my_addr.sin_addr.s_addr = INADDR_ANY; if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -) {
perror("bind");
exit();
} else {
printf("binded\n");
} if (listen(sockfd, lisnum) == -) {
perror("listen");
exit();
} else {
printf("begin listen\n");
} while () {
SSL *ssl;
len = sizeof(struct sockaddr); if ((new_fd = accept(sockfd, (struct sockaddr *) &their_addr, &len)) == -) {
perror("accept");
exit(errno);
}
printf("server: got connection from %s, port %d, socket %d\n",inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd); ssl = SSL_new(ctx);
SSL_set_fd(ssl, new_fd);
if (SSL_accept(ssl) == -) {
perror("accept");
close(new_fd);
break;
} bzero(buf, MAXBUF + );
strcpy(buf, "server->client");
len = SSL_write(ssl, buf, strlen(buf));
if (len <= ) {
printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buf, errno, strerror(errno));
goto finish;
}
printf("消息'%s'发送成功,共发送了%d个字节!\n", buf, len); bzero(buf, MAXBUF + );
len = SSL_read(ssl, buf, MAXBUF);
if (len > ) {
printf("接收消息成功:'%s',共%d个字节的数据\n", buf, len);
} else {
printf("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno));
}
finish:
SSL_shutdown(ssl);
SSL_free(ssl);
close(new_fd);
} close(sockfd);
SSL_CTX_free(ctx);
return ;
}

测试结果:

双向认证:

客户端代码:需要设置CA证书,客户端证书和私钥,校验服务器。

服务端代码:

 #include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <openssl/ssl.h>
#include <openssl/err.h> #define MAXBUF 1024 #define CA_FILE "/home/waf/keyless/test/cert/CA/cacert.pem"
#define CLIENT_KEY "/home/waf/keyless/test/cert/client-cert/key.pem"
#define CLIENT_CERT "/home/waf/keyless/test/cert/client-cert/cert.pem" void ShowCerts(SSL * ssl)
{
X509 *cert;
char *line;
cert = SSL_get_peer_certificate(ssl);
if (cert != NULL) {
printf("数字证书信息:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), , );
printf("证书: %s\n", line);
free(line);
line = X509_NAME_oneline(X509_get_issuer_name(cert), , );
printf("颁发者: %s\n", line);
free(line);
X509_free(cert);
} else {
printf("无证书信息!\n");
}
} int main(int argc, char **argv)
{
int sockfd, len;
struct sockaddr_in dest;
char buffer[MAXBUF + ];
SSL_CTX *ctx;
SSL *ssl;
const SSL_METHOD *method; if (argc != ) {
printf("参数格式错误!正确用法如下:\n\t\t%s IP地址 端口\n\t比如:\t%s 127.0.0.1 80\n此程序用来从某个"
"IP 地址的服务器某个端口接收最多 MAXBUF 个字节的消息", argv[], argv[]);
exit();
} SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
method = TLSv1_2_client_method();
ctx = SSL_CTX_new(method); if (!ctx) {
printf("create ctx is failed.\n");
} #if 0
const char * cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH";
if (SSL_CTX_set_cipher_list(ctx, cipher_list) == ) {
SSL_CTX_free(ctx);
printf("Failed to set cipher list: %s", cipher_list);
}
#endif /*设置会话的握手方式*/
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ); /*加载CA FILE*/
if (SSL_CTX_load_verify_locations(ctx, CA_FILE, ) != ) {
SSL_CTX_free(ctx);
printf("Failed to load CA file %s", CA_FILE);
}
if (SSL_CTX_set_default_verify_paths(ctx) != ) {
SSL_CTX_free(ctx);
printf("Call to SSL_CTX_set_default_verify_paths failed");
}
/*加载客户端证书*/
if (SSL_CTX_use_certificate_file(ctx, CLIENT_CERT, SSL_FILETYPE_PEM) != ) {
SSL_CTX_free(ctx);
printf("Failed to load client certificate from %s", CLIENT_KEY);
}
/*加载客户端私钥*/
if (SSL_CTX_use_PrivateKey_file(ctx, CLIENT_KEY, SSL_FILETYPE_PEM) != ) {
SSL_CTX_free(ctx);
printf("Failed to load client private key from %s", CLIENT_KEY);
}
/*验证私钥*/
if (SSL_CTX_check_private_key(ctx) != ) {
SSL_CTX_free(ctx);
printf("SSL_CTX_check_private_key failed");
}
/*处理握手多次*/
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); if ((sockfd = socket(AF_INET, SOCK_STREAM, )) < ) {
perror("Socket");
exit(errno);
} bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(atoi(argv[]));
if (inet_aton(argv[], (struct in_addr *) &dest.sin_addr.s_addr) == ) {
perror(argv[]);
exit(errno);
} if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != ) {
perror("Connect ");
exit(errno);
} /*创建SSL*/
ssl = SSL_new(ctx);
if (ssl == NULL) {
printf("SSL_new error.\n");
}
/*将fd添加到ssl层*/
SSL_set_fd(ssl, sockfd);
if (SSL_connect(ssl) == -) {
printf("SSL_connect fail.\n");
ERR_print_errors_fp(stderr);
} else {
printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
ShowCerts(ssl);
} bzero(buffer, MAXBUF + );
len = SSL_read(ssl, buffer, MAXBUF);
if (len > ) {
printf("接收消息成功:'%s',共%d个字节的数据\n", buffer, len);
} else {
printf("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno));
goto finish;
}
bzero(buffer, MAXBUF + );
strcpy(buffer, "from client->server"); len = SSL_write(ssl, buffer, strlen(buffer));
if (len < ) {
printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buffer, errno, strerror(errno));
} else {
printf("消息'%s'发送成功,共发送了%d个字节!\n", buffer, len);
} finish: SSL_shutdown(ssl);
SSL_free(ssl);
close(sockfd);
SSL_CTX_free(ctx);
return ;
}

服务端代码:

 #include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h> #define MAXBUF 1024 #define CA_FILE "/home/waf/keyless/test/cert/CA/cacert.pem"
#define SERVER_KEY "/home/waf/keyless/test/cert/server-cert/key.pem"
#define SERVER_CERT "/home/waf/keyless/test/cert/server-cert/cert.pem" int main(int argc, char **argv)
{
int sockfd, new_fd;
int reuse = ;
socklen_t len;
struct sockaddr_in my_addr, their_addr;
unsigned int myport, lisnum;
char buf[MAXBUF + ];
SSL_CTX *ctx;
const SSL_METHOD *method; if (argv[]) {
myport = atoi(argv[]);
} else {
myport = ;
} if (argv[]) {
lisnum = atoi(argv[]);
} else {
lisnum = ;
} SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings(); method = TLSv1_2_server_method();
ctx = SSL_CTX_new(method);
if (ctx == NULL) {
ERR_print_errors_fp(stdout);
exit();
} #if 0
const char *cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384";
if (SSL_CTX_set_cipher_list(ctx, cipher_list) == ) {
SSL_CTX_free(ctx);
printf("Failed to set cipher list %s", cipher_list);
}
#endif SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, );
/*加载CA FILE*/
if (SSL_CTX_load_verify_locations(ctx, CA_FILE, ) != ) {
SSL_CTX_free(ctx);
printf("Failed to load CA file %s", CA_FILE);
}
/*加载服务端证书*/
if (SSL_CTX_use_certificate_file(ctx, SERVER_CERT, SSL_FILETYPE_PEM) <= ) {
ERR_print_errors_fp(stdout);
exit();
}
/*加载服务端私钥*/
if (SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY, SSL_FILETYPE_PEM) <= ) {
printf("use private key fail.\n");
ERR_print_errors_fp(stdout);
exit();
}
/*验证私钥*/
if (!SSL_CTX_check_private_key(ctx)) {
ERR_print_errors_fp(stdout);
exit();
}
//处理握手多次
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); if ((sockfd = socket(PF_INET, SOCK_STREAM, )) == -) {
perror("socket");
exit();
} else {
printf("socket created\n");
} if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < ){
printf("setsockopet error\n");
return -;
} bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = PF_INET;
my_addr.sin_port = htons(myport);
my_addr.sin_addr.s_addr = INADDR_ANY; if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -) {
perror("bind");
exit();
}
printf("Server bind success.\n"); if (listen(sockfd, lisnum) == -) {
perror("listen");
exit();
}
printf("Server begin to listen\n"); while () {
SSL *ssl;
len = sizeof(struct sockaddr); if ((new_fd = accept(sockfd, (struct sockaddr *) &their_addr, &len)) == -) {
perror("accept");
exit(errno);
} printf("Server: receive a connection from %s, port %d, socket %d\n", inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd); ssl = SSL_new(ctx);
if (ssl == NULL) {
printf("SSL_new error.\n");
} SSL_set_fd(ssl, new_fd); if (SSL_accept(ssl) == -) {
perror("accept");
ERR_print_errors_fp(stderr);
close(new_fd);
break;
}
printf("Server with %s encryption\n", SSL_get_cipher(ssl)); bzero(buf, MAXBUF + );
strcpy(buf, "server->client");
len = SSL_write(ssl, buf, strlen(buf));
if (len <= ) {
printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buf, errno, strerror(errno));
goto finish;
} else {
printf("消息'%s'发送成功,共发送了%d个字节!\n", buf, len);
} bzero(buf, MAXBUF + );
len = SSL_read(ssl, buf, MAXBUF);
if (len > ) {
printf("接收消息成功:'%s',共%d个字节的数据\n", buf, len);
} else {
printf("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno));
}
finish:
SSL_shutdown(ssl);
SSL_free(ssl);
close(new_fd);
} close(sockfd);
SSL_CTX_free(ctx);
return ;
}

测试结果:

基于openssl的单向和双向认证的更多相关文章

  1. m.Tomcat使用openssl走APR通道配置单向和双向认证

    引用自: http://blog.csdn.net/gtuu0123/article/details/5827800(Tomcat的SSL单向认证)  http://blog.csdn.net/gtu ...

  2. PAP认证(单向、双向)

    实验要求:掌握PAP单向.双向认证 拓扑如下: 单向验证 R1(认证方)enable 进入特权模式configure terminal 进入全局模式hostname R1 设置主机名interface ...

  3. 基于mosquitto的MQTT服务器---SSL/TLS 单向认证+双向认证

    基于mosquitto的MQTT服务器---SSL/TLS 单向认证+双向认证 摘自:https://blog.csdn.net/ty1121466568/article/details/811184 ...

  4. linux下Tomcat+OpenSSL配置单向&双向认证(自制证书)

    背景 由于ios将在2017年1月1日起强制实施ATS安全策略,所有通讯必须使用https传输,本文只针对自制证书,但目前尚不确定自制证书是否能通过appstore审核. 1.必须支持传输层安全(TL ...

  5. Https、OpenSSL自建CA证书及签发证书、nginx单向认证、双向认证及使用Java访问

    0.环境 本文的相关源码位于 https://github.com/dreamingodd/CA-generation-demo 必须安装nginx,必须安装openssl,(用apt-get upd ...

  6. 搭建私有CA并基于OpenSSL实现双向身份认证

    0x00 前言 互联网上的Web应用由于用户数目广泛,都是采用单向身份认证的,只需要客户端验证服务端的身份.但如果是企业内部的应用对接,客户端数量有限,可能就会要求对客户端也做身份验证,这时就需要一个 ...

  7. SSL双向认证和SSL单向认证的流程和区别

    refs: SSL双向认证和SSL单向认证的区别https://www.jianshu.com/p/fb5fe0165ef2 图解 https 单向认证和双向认证!https://cloud.tenc ...

  8. ssl介绍以及双向认证和单向认证原理

    SSL安全证书可以自己生成,也可以通过第三方的CA(Certification Authority)认证中心付费申请颁发. SSL安全证书包括: 1.       CA证书,也叫根证书或中间级证书.单 ...

  9. ssl双向认证和单向认证原理

    有朋友在搞一个项目,周末有聊到一些安全性的东西,很自然会想起https,但https究竟如何实施,其原理又是什么? 基于ssl,一般的应用都是单向认证,如果应用场景要求对客户来源做验证也可以实现成双向 ...

随机推荐

  1. Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法

    一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...

  2. Bilateral Filtering(双边滤波) for SSAO(转)

    原文链接:http://blog.csdn.net/bugrunner/article/details/7170471 另外一篇相似的英文资料:http://homepages.inf.ed.ac.u ...

  3. mssql 获取表空间大小

    create table #Data(name varchar(100),row varchar(100),reserved varchar(100),data varchar(100),index_ ...

  4. json字符串转成 Map/List

    package jsonToMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import n ...

  5. MiniDao普通项目集成方案

    1.导入必要的jar包: 2.spring配置文件增加如下配置: <!-- Hibernate工具栏配置--> <bean id="miniDaoHiberCommonDa ...

  6. AngularJS Eclipse——新手入门【翻译+整理】

    原文地址 本文介绍如何安装和配置 AngularJS Eclipse.AngularJS Eclipse 插件是基于强大的 JavaScript 推断引擎(javascript inference e ...

  7. 七牛CEO许式伟:移动游戏资源存贮的大趋势

    (国内知名Android开发论坛eoe开发者社区推荐:http://www.eoeandroid.com/) 9月14日,eoe移动开发者大会正式在北京国家会议中心召开,七牛云储存CEO许式伟先生做了 ...

  8. 最近的shell脚本(updating)

    1.批量替换 sed -i 's/class="table"/class="table table-hover"/g' `grep 'class="t ...

  9. 第一部分:IBM量子体验

    (一)量子世界    今天的计算机使用标准的(或用物理学家的话来说,“经典的”)计算模型来执行计算与处理信息,此计算模型要追溯到图灵(Turing)和冯・诺伊曼(Von Neumann)时期.在此模型 ...

  10. [Lua]50行代码的解释器,用来演示lambda calculus

    嗯,来写写经过: 在知乎上看见用Belleve牛用javascript写了一个精简的lisp解释器 => 我也想写一个,用lua写,能多简单呢? => 写了一个阉割的scheme解释器,包 ...