转载自: http://blog.csdn.net/marujunyy/article/details/8477854
考虑到数据传输的安全及保密,决定采用TLS(SSL)协议,既节省了设计安全协议的时间,也容易与外部系统协同工作。作为工业标准的TLS(SSL)协议已经有许多成熟的解决方案,故不打算自行开发,而是使用开源社区中广泛使用的OpenSSL。
由于TLS(SSL)是基于非对称的加密体系,所以在开发前需要准备用于加密解密及验证的私钥及数字证书。这里分别为CA、服务器、客户端分别准备1套密钥及证书。
CA机构的数字证书是整个TLS(SSL)协议的根证书,用于给服务器及客户端证书签名及验证其真伪。由于不作商业用途,不打算使用权威CA机构的数字证书,而且是使用自签名的CA证书。生成方法如下:
openssl genrsa -out ca-key.pem -des 1024 openssl req -new -key ca-key.pem -out ca-csr.pem openssl x509 -req -days 3650 -in ca-csr.pem -signkey ca-key.pem -out ca-cert.pem
执行上述3个命令之后,得到3个文件,其中“ca-key.pem”为CA的私钥,“ca-cert.pem”为CA的自签名证书。有了CA证书和私钥之后就可以使用它来签发服务器及客户端的证书了。如果想查看生成证书的详细信息,可以使用以下命令查看:
openssl x509 -noout -text -in ca-cert.pem
在TLS(SSL)协议中,客户端在与服务器连接时,除需要使用CA证书来验证服务器证书的真伪之外,还需要验证服务器证书是否与服务器域名或IP地址相匹配。但由于服务器可能有多个IP地址及多个DNS服务器,所以在生成证书前需要对其进行设置,这里将设置写入一个文件中,方便之后生成证书的工作,配置内容文件如下:
[req] distinguished_name = req_distinguished_name req_extensions = v3_req [req_distinguished_name] countryName = Country Name (2 letter code) countryName_default = CN stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = BeiJing localityName = Locality Name (eg, city) localityName_default = YaYunCun organizationalUnitName = Organizational Unit Name (eg, section) organizationalUnitName_default = Domain Control Validated commonName = Internet Widgits Ltd commonName_max = 64 [ v3_req ] # Extensions to add to a certificate request basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @alt_names [alt_names] DNS.1 = ns1.dns.com DNS.2 = ns2.dns.com DNS.3 = ns3.dns.com IP.1 = 192.168.1.84 IP.2 = 127.0.0.1 IP.3 = 127.0.0.2
“req_distinguished_name”部分的内容就是证书的主体内容,包括证书持有者的相关信息。重点是“alt_name”部分的内容,其中的“DNS.1”所指定的是使用该证书的主机所使用的DNS,还有“IP.1”所指定的是使用该证书的主机的IP地址,这里可以指定多个DNS和IP,方便有多DNS和多IP的主机能够使用同一个该证书来完成验证。
假设上述配置文件为“openssl.cnf”,则生成服务器私钥及证书的方法如下:
openssl genrsa -out server-key.pem 1024 openssl req -new -key server-key.pem -config openssl.cnf -out server-csr.pem openssl x509 -req -days 730 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -in server-csr.pem -out server-cert.pem -extensions v3_req -extfile openssl.cnf
如果查看刚才生成的服务器证书,可以看到设置的DNS及IP信息。还可以将服务器私钥、证书以及CA证书打包成一个单独的.pfx或.p12文件:
openssl pkcs12 -export -in server-cert.pem -inkey server-key.pem -certfile ca-cert.pem -out server.pfx openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem -certfile ca-cert.pem -out client.p12
这样携带和使用都更加方便。最后就是生成客户端证书:
openssl genrsa -out client-key.pem openssl req -new -key client-key.pem -out client-csr.pem openssl x509 -req -days 365 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -in client-csr.pem -out client-cert.pem
上面所生成的证书中,CA证书的有效期是10年,服务器证书有效期是2年,客户端证书有效期是1年。
测试:
openssl s_client -connect 127.0.0.1:8000 -cert client-cert.pem -key client-key.pem -tls1 -CAfile ca-cert.pem -state -showcerts
TLS(SSL)方式
tls服务器程序:
var tls = require('tls'); var fs = require('fs'); var options = { key: fs.readFileSync('../key/server-key.pem'), cert: fs.readFileSync('../key/server-cert.pem'), // This is necessary only if using the client certificate authentication. requestCert: true, rejectUnauthorized: true, // passphrase:'test', // This is necessary only if the client uses the self-signed certificate. ca: [ fs.readFileSync('../key/ca-cert.pem') ] }; var server = tls.createServer(options, function(cleartextStream) { console.log('server connected', cleartextStream.authorized ? 'authorized' : 'unauthorized'); cleartextStream.write('this message is come from server!'); cleartextStream.setEncoding('utf8'); cleartextStream.pipe(cleartextStream); cleartextStream.on('data', function(data) { console.log(data); }); }); server.listen(8000, function() { console.log('server bound'); });
tls客户端程序:
var tls = require('tls'); var fs = require('fs'); var options = { // These are necessary only if using the client certificate authentication key: fs.readFileSync('../key/client-key.pem'), cert: fs.readFileSync('../key/client-cert.pem'), rejectUnauthorized: true, // This is necessary only if the server uses the self-signed certificate ca: [ fs.readFileSync('../key/ca-cert.pem') ] }; var cleartextStream = tls.connect(8000, '127.0.0.1', options, function() { console.log('client connected', cleartextStream.authorized ? 'authorized' : 'unauthorized'); cleartextStream.setEncoding('utf8'); if(!cleartextStream.authorized){ console.log('cert auth error: ', cleartextStream.authorizationError); } // console.log(cleartextStream.getPeerCertificate()); }); cleartextStream.setEncoding('utf8'); cleartextStream.on('data', function(data) { console.log(data); cleartextStream.write('Hello,this message is come from client!'); cleartextStream.end(); }); cleartextStream.on('end', function() { console.log('disconnected'); }); cleartextStream.on('error', function(exception) { console.log(exception); });
先运行服务器,再运行客户端,就可以看到相互发送的信息对方的控制台上显示出来,表明连接成功。由于服务器和客户端程序中都指定了“rejectUnauthorized: true”,即如果证书验证失败则拒绝连接。所以如果服务器能收到客户端的信息,而客户端又能收到服务器的信息,则表明双向验证成功。
使用https方式
https服务器端程序(express.js):
var express = require('express') ,fs=require('fs'); var options = { key: fs.readFileSync('../key/server-key.pem'), cert: fs.readFileSync('../key/server-cert.pem'), ca: [ fs.readFileSync('../key/ca-cert.pem') ], requestCert: true, rejectUnauthorized: false }; var app = module.exports = express.createServer(options); // Configuration app.configure(function(){ app.use(app.router); }); app.configure('development', function(){ app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); }); app.configure('production', function(){ app.use(express.errorHandler()); }); // Routes app.all('/', function(req, res){ if (req.client.authorized) { res.writeHead(200, {"Content-Type":"application/json"}); res.end('{"status":"authorized"}'); // console.log(req.client); console.log("Authorized Client ", req.client.socket.remoteAddress); } else { res.writeHead(401, {"Content-Type":"application/json"}); res.end('{"status":"denied"}'); console.log("Denied Client " , req.client.socket.remoteAddress); } }); app.listen(5558); console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env); //curl -v -s -k --key key/client-key.pem --cert key/client-cert.pem https://localhost:5558
参考:http://www.hacksparrow.com/express-js-https-server-client-example.html
https客户端程序:(client.js)
var https = require('https'); var fs = require('fs'); var options = { host: '192.168.1.84', port: 5558, path: '/', method: 'GET', // These are necessary only if using the client certificate authentication key: fs.readFileSync('../key/client-key.pem'), cert: fs.readFileSync('../key/client-cert.pem'), rejectUnauthorized: true, // This is necessary only if the server uses the self-signed certificate ca: [ fs.readFileSync('../key/ca-cert.pem') ], agent: false }; var req = https.request(options, function(res) { console.log('server authorize status: '+res.connection.authorized); res.on('data', function(d) { console.log('client authorize status: '+ d); }); }); req.end(); req.on('error', function(e) { console.error(e); });
注意:agent: false 这个属性一定要加上,不然证书不起作用
相关推荐
C# TLS SSL TCP双向认证 X509Store SslStream Certificate Visual Studio 2017 命令提示 键入: makecert -r -pe -n “CN=TestServer” -ss Root -sky exchange 等待来自客户端的连接... 显示安全等级 密钥套件: Aes...
Node.js是一个非常具有极客精神的技术社区(我更想强调它本身代表的是一个社区,相比之前的一些大语言分支 c/c++/java什么的,那些大语言在针对某一些应用都有很固定的范式去遵循,javascript/node.js还是一个比较...
HTTPS 2048位RSA TLS / SSL证书示例 这是针对使用io.js / node.js的人员的,但是就生成和测试证书而言,这些是与您在任何语言中都使用过的openssl命令完全相同的命令。 ScreenCast 参见 请参阅的完整文章。 零配置...
ARM.mbedTLS.1.6.0.pack 是基于平台(cortex-m3)stm32 MDK-keil 使用的加密软件包。贴在这里方便大家使用。
win10下cygwin编译的redis tls 7.0.0版本编译安装
ARM.mbedTLS.1.8.0.pack
keil的ARM.mbedTLS.1.6.1.pack包,由于网络的原因,官网可能下不了,我这里有,哈哈哈,大家可以直接下载了
最低 TLS 版本允许您轻松地为 node.js 和 io.js 指定 TLS/SSL 版本。 所有早于最低版本的 TLS/SSL 版本都将被禁用。 TLS/SSL 版本的完整列表如下。用法只需加载模块: var minimumTLSVersion = require('minimum-tls...
HTTPS, TLS(SSL), and securing your server 72 Creating a self-signed certificate for development 72 Installing a real SSL certificate 73 The request object 73 The URL module 74 The Querystring module ...
本文实现了OpenSSL的CA跟证书的制作、服务器和客户端证书的制作,并使用node.js实现了服务器和客户端代码,也实现了java代码,同时验证了SSL/TLS单向和双向认证。
一个netty建立的SSL双向加密的服务器和客户端的简单示例。工程是IDEA创建的,直接导入即可,注意需要依赖的pom文件中的包。需要的证书文件示例也在压缩包内。
TLS.js JavaScript 中的 TLS 协议实现。安装 npm install tls . js用法 var tls = require ( 'tls.js' ) ;tls . createHTTPServer ( { key : fs . readFileSync ( __dirname + '/test/keys/key.pem' ) , cert : fs ....
SSL and TLS Theory and Practice.pdf SSL and TLS Theory and Practice.pdf SSL and TLS Theory and Practice.pdf SSL and TLS Theory and Practice.pdf SSL and TLS Theory and Practice.pdf SSL and TLS Theory ...
最新版本的TLS(Transport Layer Security,传输层安全协议)是IETF(Internet Engineering Task Force,Internet工程任务组)制定的一种新的协议,它建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本。在TLS与SSL...
压缩包里有客户端源码和服务器端源码,支持TCP的双向认证,也支持WEBSOCKET的双向认证,内附测试 wss的测试例子, 需要生成PKCS12的证书,导入浏览器才可以测试。
MDK 中使用的 MbedTLS 包,可以直接安装到MDK,用作算法加密
ARM.mbedTLS.1.7.0.pack
Node.js v6.10.2 文档 关于本文档 用法与例子 Assert (断言) Buffer C/C++ 插件 Child Processes (子进程) Cluster (集群) CLI (命令行选项) Console (控制台) Crypto (加密) Debugger (调试器) DNS (域名服务器) ...
Adafruit IO TLS / SSL隧道一个Node.js TLS / SSL隧道,用于将HTTP和MQTT客户端安全地连接到[io.adafruit.com] [1]。安装该项目旨在在Raspberry Pi上作为服务运行。 如果您想连接到无头Raspberry Pi以设置WiFi接入,...
官方开源的gSOAP不支持SSL/TLS,生成onvif框架时会报【Cannot connect to https site: SSL/TLS support not enabled in this version. Visit ...