服务器客户端证书,客户端如何验证HTTPS服务端证书信息
通过一个例子说明客户端如何验证HTTPS服务端的证书信息。
类型浏览器如何验证WEB服务器的证书信息。
生成服务器端证书,以及CA证书
# generate ca certificate
$ openssl genrsa -out ca-key.pem 2048
$ openssl req -new -x509 -days 365 -key ca-key.pem -out ca-cert.pem -subj "/CN=ca"
# generate server certificate
$ openssl genrsa -out server-key.pem 2048
$ openssl req -new -key server-key.pem -out server-csr.pem -subj "/CN=localhost"
$ openssl x509 -req -days 3650 -in server-csr.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem
生成服务端证书server-cert.pem,(注意证书的common name是localhost),这个证书是通过CA证书ca-cert.pem签名的。
服务器端代码
$ cat server.go
package main
import (
"fmt"
"log"
"flag"
"net/http"
"crypto/tls"
"encoding/json"
"github.com/gorilla/mux"
)
var (
port int
hostname string
keyfile string
signcert string
)
func init() {
flag.IntVar(&port, "port", 8080, "The host port on which the REST server will listen")
flag.StringVar(&hostname, "hostname", "0.0.0.0", "The host name on which the REST server will listen")
flag.StringVar(&keyfile, "key", "", "Path to file containing PEM-encoded key file for service")
flag.StringVar(&signcert, "signcert", "", "Path to file containing PEM-encoded sign certificate for service")
}
func startHTTPSServer(address string, keyfile string, signcert string, router *mux.Router) {
s := &http.Server{
Addr: address,
Handler: router,
TLSConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
},
}
err := s.ListenAndServeTLS(signcert, keyfile)
if err != nil {
log.Fatalln("ListenAndServeTLS err:", err)
}
}
func SayHello(w http.ResponseWriter, r *http.Request) {
log.Println("Entry SayHello")
res := map[string]string {"hello": "world"}
b, err := json.Marshal(res)
if err == nil {
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json")
w.Write(b)
}
log.Println("Exit SayHello")
}
func main() {
flag.Parse()
router := mux.NewRouter().StrictSlash(true)
router.HandleFunc("/service/hello", SayHello).Methods("GET")
var address = fmt.Sprintf("%s:%d", hostname, port)
fmt.Println("Server listen on", address)
startHTTPSServer(address, keyfile, signcert, router)
fmt.Println("Exit main")
}
编译运行
$ go build
$ ./server -port 8080 -signcert ./server-cert.pem -key ./server-key.pem
运行服务器在端口8080,这个服务器提供验证的证书是server-cert.pem,客户端(浏览器将验证这个证书的有效性)。
客户端代码
$ cat client.js
fs = require('fs');
https = require('https');
options = {
hostname: 'localhost',
port : 8080,
path : '/service/hello',
method : 'GET',
ca : fs.readFileSync('ca-cert.pem')
};
req = https.request(options, (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
});
req.on('error', (e) => {
console.error(e);
});
req.end();
运行
$ node client.js
{"hello":"world"}
完整的访问地址格式就是 https://localhost:8080/service/hello
这里客户端必须提供CA证书ca-cert.pem,用他来验证服务端的证书server-cert.pem是有效的。
另外这里客户端访问的地址是localhost,这个值和服务器证书server-cert.pem的common name域是一样的,否则验证就会失败。
例如,我们修改客户端请求中hostname值真实到机器名(假定机器名为saturn)。
options = {
hostname: 'saturn',
port : 8080,
path : '/service/hello',
method : 'GET',
ca : fs.readFileSync('ca-cert.pem')
};
$ node client.js
{ Error: Hostname/IP doesn't match certificate's altnames: "Host: saturn. is not cert's CN: localhost"
at Object.checkServerIdentity (tls.js:199:17)
at TLSSocket. (_tls_wrap.js:1098:29)
at emitNone (events.js:86:13)
at TLSSocket.emit (events.js:185:7)
at TLSSocket._finishInit (_tls_wrap.js:610:8)
at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:440:38)
这说明client使用URL的主机名和证书的Common Name域进行比较,作为证书是否有效的一个证据。
另外Common Name可以是一个短名(saturn),也可以长域名(saturn.yourcomp.com.cn),但不管短名还是长名都必须是URL请求中的主机名一样。即
SAN证书
SAN是另一种解决证书和URL主机名匹配的办法。
SAN = subjectAltName = Subject Alternative Name
具体用法步骤:
修改openssl.cnf
[ req ]
req_extensions = v3_req
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = saturn
DNS.2 = saturn.yourcomp.com.cn
生成证书
# generate ca certificate
openssl genrsa -out ca-key.pem 2048
openssl req -new -x509 -days 365 -key ca-key.pem -out ca-cert.pem -subj "/CN=ca"
# generate server certificate
openssl genrsa -out server-key.pem 2048
openssl req -new -key server-key.pem -out server-csr.pem -subj "/CN=localhost"
openssl x509 -req -days 3650 -in server-csr.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extensions v3_req -extfile openssl.cnf
对比和前面不使用SAN的差别。其实就是在使用CA根证书对服务器证书签名的时候,指定extensions属性。
运行客户端
options = {
hostname: 'localhost',
port : 8080,
path : '/service/hello',
method : 'GET',
ca : fs.readFileSync('ca-cert.pem')
};
$ node client.js
{ Error: Hostname/IP doesn't match certificate's altnames: "Host: localhost. is not in the cert's altnames: DNS:saturn"
看到了吗?localhost已经验证不过了,尽管他在common name的值没有变化,但是由于使用了SAN,证书验证的时候就使用SAN的值,而忽略common name的值。
使用客户端saturn
options = {
hostname: 'saturn',
port : 8080,
path : '/service/hello',
method : 'GET',
ca : fs.readFileSync('ca-cert.pem')
};
$ node client.js
{"hello":"world"}
使用saturn就通过了。当然使用saturn.yourcomp.com.cn也能通过。
总结
客户端验证服务端证书分两种情况:
不使用SAN,那么验证证书的common name和URL的主机名一致。
主机名是否是common name中的一个。
使用SAN,那么验证证书的SAN值和URL的主机名一致。
主机名是否就是SAN值中的一个。
服务器客户端证书,客户端如何验证HTTPS服务端证书信息相关推荐
- HTTPS|SSL笔记-SSL双向认证失败(客户端证书信任库不含服务端证书)握手过程(含wireshark分析)
这里我把客户端证书信任库里面清空,及没放服务端证书,Java报错不一样,但抓包是一样的,在此记录下过程. 1. 前3个包是TCP三次握手,在此不解析,对应的包如下: 2. 握手成功后,客户端发送自己支 ...
- HTTPS|SSL笔记-SSL双向认证失败(服务端证书信任库不含客户端证书)握手过程(含wireshark分析)
这里我把服务端信任库添加了其他证书,不含客户端的证书,这时SSL认证失败报错如下.下面来分析下: 1. 首先是TCP三次握手,对应的包如下: 2. 握手成功后,客户端发送自己支持的加密套,和随机数给服 ...
- 微软服务器搭建ngrok,ngrok搭建(Windows服务端+Windows客户端)
1.go环境搭建(需要Linux系统) 1)下载源码,可以在http://www.golangtc.com/download 2)将其解压到/usr/local目录下: tar -C /usr/loc ...
- 自制CA证书,自制客户端,服务端证书
自制CA证书,客户端.服务端证书 参考资料:HTTPS证书生成原理和部署细节 废话不多讲,我们直入正题. 首先我假设你的系统已经安装了openssl.使用openssl version -a即可查看当 ...
- Java IOS客户端上传多张图片到服务端
Java IOS客户端上传多张图片到服务端 业务场景:用户相册需要上传多张图片到服务器,上限为12张.本文主要介绍Java服务端的文件和流的处理. 下图为iOS端和服务端最终结果一览. iOS端 : ...
- 客户端、前端、后端、服务端的区别分别是什么?
客户端.前端.后端.服务端的区别分别是什么? 客户端是指开发面向客户的程序,分很多平台,比如Windows 安卓 苹果,还有游戏客户端也算一类. 前端指的是通过浏览器和用户交互的那部分. 后端是在服务 ...
- Asp.net webApi 通过WebSocket推送消息给客户端,搭建一个即是服务端又是客户端的服务
Asp.net webApi 通过WebSocket推送消息给客户端,搭建一个即是服务端又是客户端的服务_IT_ziliang的博客-CSDN博客 WebSocket是一种在单个TCP连接上进行全双工 ...
- java 网络编程(二) tcp传输实现客户端和服务端进行信息交流
1.使用Tcp从一台电脑往另一台电脑上发送文本数据 客户端: import java.io.*; import java.net.*; /**** 客户端,* 通过查阅socket对象,发现在该对象建 ...
- 浅析客户端渲染(CSR)与服务端渲染(SSR)
最近刚好公司有项目需要用到服务端渲染,于是花了些时间了整理了关于服务端渲染与客户端渲染的知识,现在记录下来,希望能帮助大家提升对浏览器渲染,服务端渲染的理解,在项目选型上做出正确的决策. 本文会涉及这 ...
最新文章
- JavaScript 复习之 Array 对象
- matlab 设计 18db,基于混沌理论的微弱MPSK信号解调方案设计
- 学生信息管理系统中遇到的问题解析
- 简单快速的用SpringBoot访问静态资源(图片、html)
- svn 服务器的搭建以及客户端的使用
- URL Safe base64 与 base64相互转换
- SQL*Plus 系统变量之32 - NEWP[AGE]
- MySQL Workbench中PK,NN,UQ,BIN,UN,ZF,AI,G字段类型标识说明
- RDIFramework.NET ━ .NET快速信息化系统开发框架 V2.8 版本━新增岗位管理-WinForm部分
- bootstrap, boosting, bagging
- HBuilderX 开发工具
- ENVI App Store
- C语言 统计元音字母个数
- Linux kernel Panic后自动重启机器的设置
- Python标准库:内置函数divmod(a, b)
- 车载以太网协议:SOME/IP (layer5-7)简介
- 怎么渗透验证 mysql_mysql-渗透测试
- AD中PCB布局与布线的一般原则
- 用海伦公式计算三角形面积
- Voyager下的关系模型
热门文章
- SAP标准功能重复制造计划编制表实现生产排产初步分析
- 解决win10学习汇编工具的烦恼——汇编Debug的下载和使用(包含可用下载链接)
- 视频压缩编码和解码(转)
- 计算机修改users用户名,笔记本电脑更改用户名_笔记本电脑更改user
- 主成分分析时,如果矩阵秩亏,会发生什么后果?
- matplotlib 入门之Sample plots in Matplotlib
- 线下沙龙 | EOS入门及最新技术解读
- matplotlib的Text、FontProperties对象、字体(font)属性|中文字体的设置|图像标题、label字体的设置
- 20165334 学习基础与c语言学习心得
- POS 打印机编程控制