HTTPS过程以及详细案例
1.HTTPS的过程
1.客户端向服务端发送请求,客户端主要向服务器提供以下信息:
- 支持的协议版本,比如TLS 1.0版。
- 一个客户端生成的随机数,稍后用于生成"对话密钥"。
- 支持的加密方法,比如RSA公钥加密。
- 支持的压缩方法。
2.服务器端收到请求后,向客户端做出回应,回应的内容包括:
- 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信。
- 一个服务器生成的随机数,稍后用于生成"对话密钥"。
- 确认使用的加密方法,比如RSA公钥加密。
- 服务器证书。
3.客户端收到服务器回应以后,首先验证服务器证书。
如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,如下
如果证书没有问题,客户端就会从证书中取出服务器的公钥。然后,向服务器发送下面三项信息:
- 一个随机数。该随机数用服务器公钥加密,防止被窃听。
- 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
- 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验
证书的验证过程如下:
CA机构在签发证书的时候,都会使用自己的私钥对证书进行签名,如果我们使用的是购买的证书,那么很有可能,颁发这个证书的CA机构的公钥已经预置在操作系统中。这样浏览器就可以使用CA机构的公钥对服务器的证书进行验签,验签之后得到的是CA机构使用sha256得到的证书摘要,客户端就会对服务器发送过来的证书使用sha256进行哈希计算得到一份摘要,然后对比之前由CA得出来的摘要,就可以知道这个证书是不是正确的,是否被修改过。
4. 服务端回应
服务器收到客户端的第三个随机数之后,计算生成本次会话所用的"会话密钥"。然后,向客户端最后发送下面信息:
- 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
- 服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供客户端校验。
会话秘钥是根据前面几次对话过程中产生的三个随机数以及一些其他算法产生的,后面服务器与客户端的交互都是通过这对话秘钥进行加密解密处理的,其他的都和HTTP协议一样。
2.HTTPS中自签名证书的生成
需要注意的是接下来几种文件的类型:
- key是服务器上的私钥文件,用于对发送给客户端数据的加密,以及对从客户端接收到数据的解密
- csr是证书签名请求文件(公钥),用于提交给证书颁发机构(CA)对证书签名
- crt是由证书颁发机构(CA)签名后的证书,或者是开发者自签名的证书,包含证书持有人的信息,持有人的公钥,以及签署者的签名等信息
- keystore 包含证书的文件,可以自己去导入证书
- PEM 文件格式存储证书和密钥,用于导出,导入证书时候的证书的格式,有证书开头,结尾的格式。
还有就是X.509是一个标准,规范了公开秘钥认证、证书吊销列表、授权凭证、凭证路径验证算法等。
a. 服务器端用户证书的生成过程:
1. 生成私钥(.key)文件
- # private key
- $openssl genrsa -des3 -out server.key 1024
2. 生成证书请求(.csr)文件(公钥)
- # generate csr
- $openssl req -new -key server.key -out server.csr
Country Name (2 letter code) [XX]:CN----------------------------------- 证书持有者所在国家
State or Province Name (full name) []:BJ------------------------------- 证书持有者所在州或省份(可省略不填)
Locality Name (eg, city) []:BJ----------------------------------------- 证书持有者所在城市(可省略不填)
Organization Name (eg, company) []:NH---------------------------------- 证书持有者所属组织或公司
Organizational Unit Name (eg, section) []:.---------------------------- 证书持有者所属部门(可省略不填)
Common Name (eg, your name or your server's hostname) []:www.hellobcdb.com----- 必须要填写域名或者ip地址
Email Address []:------------------------------------------------------ 邮箱(可省略不填)
challenge password:............................................................自定义密码
An optional company name:.............................................(可选)公司名称
3. 自签名的证书文件
- openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
4.本案例需要用到pem格式的证书,可以用以下方式合并证书文件(crt)和私钥文件(key)来生成
- cat server.crt server.key > server.pem
b. 客户端证书文件的生成
这里采用的是自签名的方式,所以客户端需要有一个导入服务端证书的文件,以供客户端去验证服务段的证书过程。
1.生成.keystore文件
- keytool -genkey -validity 36000 -alias www.hellobcdb.com -keyalg RSA -keystore client.keystore
2.导入服务端证书
- keytool -import -alias serverkey -file server.crt -keystore client.keystore
3.HTTPS案例
环境及工具:ubuntu16.04,QtCreator,mongoose(cesanta),java环境。
服务端代码:
- #include "mongoose.h"
- static const char *s_http_port = "8443";
- static const char *s_ssl_cert = "/home/gqx/workplace/TestHttps/server.pem";
- static const char *s_ssl_key = "/home/gqx/workplace/TestHttps/server.key";
- static struct mg_serve_http_opts s_http_server_opts;
- static void ev_handler(struct mg_connection *nc, int ev, void *p) {
- if (ev == MG_EV_HTTP_REQUEST) {
- mg_serve_http(nc, (struct http_message *) p, s_http_server_opts);
- }
- }
- int main(void) {
- struct mg_mgr mgr;
- struct mg_connection *nc;
- struct mg_bind_opts bind_opts;
- const char *err;
- mg_mgr_init(&mgr, NULL);
- memset(&bind_opts, 0, sizeof(bind_opts));
- bind_opts.ssl_cert = s_ssl_cert;
- bind_opts.ssl_key = s_ssl_key;
- bind_opts.error_string = &err;
- printf("Starting SSL= server on port %s, cert from %s, key from %s\n",
- s_http_port, bind_opts.ssl_cert, bind_opts.ssl_key);
- nc = mg_bind_opt(&mgr, s_http_port, ev_handler, bind_opts);
- if (nc == NULL) {
- printf("Failed to create listener: %s\n", err);
- return 1;
- }
- // Set up HTTP server parameters
- mg_set_protocol_http_websocket(nc);
- s_http_server_opts.document_root = "."; // Serve current directory
- s_http_server_opts.enable_directory_listing = "yes";
- for (;;) {
- mg_mgr_poll(&mgr, 1000);
- }
- mg_mgr_free(&mgr);
- return 0;
- }
QT中C++项目的pro文件内容如下,注意要添加相应的库:
- TEMPLATE = app
- CONFIG += console c++11
- CONFIG -= app_bundle
- CONFIG -= qt
- LIBS += -lpthread
- LIBS += -lssl -lcrypto
- LIBS += -L /usr/local/bin -lcryptopp -ldl -lz
- SOURCES += main.cpp \
- mongoose.cpp
- HEADERS += \
- mongoose.h
java客户端代码(也可以直接在浏览器端直接访问,不过会出现证书不安全的警告提示)
HttpsClient类
- package com.gqx.test;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.net.Socket;
- import java.net.UnknownHostException;
- import java.security.KeyManagementException;
- import java.security.KeyStore;
- import java.security.KeyStoreException;
- import java.security.NoSuchAlgorithmException;
- import java.security.UnrecoverableKeyException;
- import java.security.cert.CertificateException;
- import java.security.cert.X509Certificate;
- import javax.net.ssl.SSLContext;
- import javax.net.ssl.TrustManager;
- import javax.net.ssl.X509TrustManager;
- import org.apache.http.HttpVersion;
- import org.apache.http.client.HttpClient;
- import org.apache.http.conn.ClientConnectionManager;
- import org.apache.http.conn.scheme.PlainSocketFactory;
- import org.apache.http.conn.scheme.Scheme;
- import org.apache.http.conn.scheme.SchemeRegistry;
- import org.apache.http.conn.ssl.SSLSocketFactory;
- import org.apache.http.impl.client.DefaultHttpClient;
- import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
- import org.apache.http.params.BasicHttpParams;
- import org.apache.http.params.HttpConnectionParams;
- import org.apache.http.params.HttpParams;
- import org.apache.http.params.HttpProtocolParams;
- import org.apache.http.protocol.HTTP;
- public class HttpsClient {
- private static final int SET_CONNECTION_TIMEOUT = 5 * 1000;
- private static final int SET_SOCKET_TIMEOUT = 20 * 1000;
- public static HttpClient getNewHttpClient() {
- try {
- FileInputStream fis = new FileInputStream("/home/gqx/文档/oscar/client.keystore");
- String storepass = "starchain";
- KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
- trustStore.load(fis, storepass.toCharArray());
- SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
- sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
- HttpParams params = new BasicHttpParams();
- HttpConnectionParams.setConnectionTimeout(params, 10000);
- HttpConnectionParams.setSoTimeout(params, 10000);
- HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
- HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
- SchemeRegistry registry = new SchemeRegistry();
- registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
- registry.register(new Scheme("https", sf, 443));
- ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
- HttpConnectionParams.setConnectionTimeout(params, SET_CONNECTION_TIMEOUT);
- HttpConnectionParams.setSoTimeout(params, SET_SOCKET_TIMEOUT);
- DefaultHttpClient client = new DefaultHttpClient(ccm, params);
- return client;
- } catch (Exception e) {
- return new DefaultHttpClient();
- }
- }
- private static class MySSLSocketFactory extends SSLSocketFactory {
- SSLContext sslContext = SSLContext.getInstance("TLS");
- public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException,
- KeyManagementException, KeyStoreException, UnrecoverableKeyException {
- super(truststore);
- TrustManager tm = new X509TrustManager() {
- public void checkClientTrusted(X509Certificate[] chain, String authType)
- throws CertificateException {
- }
- public void checkServerTrusted(X509Certificate[] chain, String authType)
- throws CertificateException {
- }
- public X509Certificate[] getAcceptedIssuers() {
- return null;
- }
- };
- sslContext.init(null, new TrustManager[] { tm }, null);
- }
- @Override
- public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
- throws IOException, UnknownHostException {
- return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
- }
- @Override
- public Socket createSocket() throws IOException {
- return sslContext.getSocketFactory().createSocket();
- }
- }
- }
测试类,post请求
- package com.gqx.test;
- import java.io.BufferedReader;
- import java.io.InputStreamReader;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.Set;
- import java.util.stream.Collectors;
- import org.apache.http.HttpEntity;
- import org.apache.http.HttpResponse;
- import org.apache.http.client.HttpClient;
- import org.apache.http.client.entity.UrlEncodedFormEntity;
- import org.apache.http.client.methods.HttpPost;
- import org.apache.http.message.BasicNameValuePair;
- public class TestMain {
- public static void main(String[] args) {
- String urlStr = "https://www.hellobcdb.com:7999/fff";
- Map<String,String> params = new HashMap<>();
- params.put("value", "publish.1666,'Database','computer science','Alice'");
- params.put("name", "gqx");
- params.put("password", "111");
- try {
- //DefaultHttpClient client = new DefaultHttpClient();
- HttpClient client = HttpsClient.getNewHttpClient();
- HttpPost httpPost = new HttpPost(urlStr);
- HttpEntity entity;
- ArrayList<BasicNameValuePair> pairs = new ArrayList<BasicNameValuePair>();
- if(params != null){
- Set<String> keys = params.keySet();
- for(Iterator<String> i = keys.iterator(); i.hasNext();) {
- String key = (String)i.next();
- pairs.add(new BasicNameValuePair(key, params.get(key)));
- }
- }
- entity = new UrlEncodedFormEntity(pairs, "utf-8");
- httpPost.setEntity(entity);
- //Log.i(TAG, "post总字节数:"+entity.getContentLength());
- HttpResponse response = client.execute(httpPost);
- try {
- // 获取响应实体
- HttpEntity entitys = response.getEntity();
- System.out.println("--------------------------------------");
- // 打印响应状态
- System.out.println(response.getStatusLine());
- if (entitys != null) {
- // 打印响应内容长度
- String result = new BufferedReader(new InputStreamReader(entitys.getContent()))
- .lines().collect(Collectors.joining(System.lineSeparator()));
- System.out.println(result);
- }
- System.out.println("------------------------------------");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }catch(Exception e){
- e.printStackTrace();
- }
- }
- }
参考资料
HTTPS过程以及详细案例的更多相关文章
- https和server-status配置案例
https和server-status配置案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.https协议 我们知道http协议是明文的,所以,你的数据发送不管是请求报文(r ...
- 鸿蒙内核源码分析(编译过程篇) | 简单案例窥视GCC编译全过程 | 百篇博客分析OpenHarmony源码| v57.01
百篇博客系列篇.本篇为: v57.xx 鸿蒙内核源码分析(编译过程篇) | 简单案例窥视编译全过程 | 51.c.h.o 编译构建相关篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙 ...
- $.ajax()方法详解 ajax之async属性 【原创】详细案例解剖——浅谈Redis缓存的常用5种方式(String,Hash,List,set,SetSorted )
$.ajax()方法详解 jquery中的ajax方法参数总是记不住,这里记录一下. 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为Str ...
- SecureCRT的下载、安装( 过程非常详细!!值得查看)
SecureCRT的下载.安装( 过程非常详细!!值得查看) 简单介绍下SecureCRT 一.SecureCRT的下载 二.SecureCRT的安装 简单介绍下SecureCRT SecureCRT ...
- USB枚举过程的详细流程
USB枚举过程的详细流程 用户将一个USB设备插入USB端口,主机为端口供电,设备此时处于上电状态.主机检测设备.1>Hub使用中断通道将事件报告给Host.2>Host发送Get_Por ...
- Mysql中主从复制的原理、配置过程以及实际案例
Mysql中主从复制的原理.配置过程以及实际案例1.什么是主从复制?原理:主从分离,什么意思呢?我们不妨画个图看看.如图1所示: 2.准备工作:预备两台服务器,我这里使用虚拟机安装了两个Centos6 ...
- SecureCRT的安装与破解(过程很详细!!!)
SecureCRT的安装与破解(过程很详细!!!) 使用SecureCRT可以方便用户在windows环境下对linux主机进行管理,这里为大家讲一下SecureCRT的破解方法,仅供大家参考学习: ...
- VMware Ubuntu安装详细过程(详细图解)
说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 一.下载Ubuntu镜像文件 下载地址:http://mirrors.aliyun.com/ubuntu-releases/16. ...
- charles抓取HTTPS设置,详细踩坑版
写这篇文章的背景就是,每次我在一台新电脑上用charles抓包时,总是因为各种原因无法抓到https请求,每个百度出来的回答又不是那么详细,需要通过几篇回答才能解决过程中的各种问题,所以把自己的安装经 ...
随机推荐
- Unity2018 VS2017打开CS脚本,提示全红及无法加载工程等问题解决
VS2017用的比较老的版本,因为当时下载了离线文件,所以可以离线安装,现在看来是没有必要的,占硬盘空间不说,不更新VS IDE,Unity高版本还有问题. 主要问题在于,我之前一直用Unity201 ...
- 非交互式一句话添加root用户
useradd -p `openssl passwd -1 -salt ‘lsof’ admin123` -u 0 -o -g root -G root -s /bin/bash -d /usr/bi ...
- 在windows上传一个新的项目到GitHub上
不多说,直接上步骤 1,新建GitHub的账号密码. 2,新建一个项目 点击new repository 3,选择自己项目,填写格式 点击创建 create repository,这时候一个雏形 ...
- 数据库 的几种链接 join
直接demo,懒的同学可以看看效果 两个表的数据 join和inner join一样 full join报错,可有大神知道原因?
- .net HttpListener 很慢
使用 HttpListener 做的webserver ,撒逻辑没有,内网跨机器访问,都要200ms 替换方案 EvHttpSharp.dll 使用了 libevent_core,libevent ...
- linux根目录介绍
1. /bin binary二进制 存放系统许多可执行程序文件 执行的相关指令,例如ls pwd whoami,后台的支持文件目录 2. /sbin super binary超级的二进制 存放系统许多 ...
- Codeforces Round #425 (Div. 2)
A 题意:给你n根棍子,两个人每次拿m根你,你先拿,如果该谁拿的时候棍子数<m,这人就输,对手就赢,问你第一个拿的人能赢吗 代码: #include<stdio.h>#define ...
- 关于Nginx设置端口号,在Asp.net 获取不到的,解决办法
不知道你有没有遇到过这样的问题,网站访客多起来后,心里很是高兴,加上了Nginx反向代理,出问题了 原来是这么写的: Request.Url.ToString() 输出是这样的: http://www ...
- 凌华Express CVC D2550 Win7 64-bit无法正常关机的解决办法
[问题现象]: 在Windows点击shutdown按钮后,显示器一直停在“正在关闭...”的界面上: 此时硬盘已经停止工作了: CPU没有发送S5信号,因此,主板上的电没有被切断: [解决办法]: ...
- TIME_WAIT状态过多的排查
一.概述 (一)现象 服务器有两个现象,第一是tcp连接数不多,不超过10个,但是time_wait状态的2000.第二个按照以往的性质,在很少用户访问的情况下,服务器的资源几乎没有使用,比如CPU, ...