参考资料:
更多参数及详细内容,可查阅命令手册:man openssl
,命令是按字母顺序排序的。
The gendsa command generates a DSA private key from a DSA parameter file (typically generated by the openssl dsaparam command). DSA key generation is little more than random number generation so it is much quicker than, for example, RSA key generation.
openssl genrsa [-3 | -f4] [-aes128 | -aes192 | -aes256 | -des | -des3] [-out file] [-passout arg] [numbits]
The req command primarily creates and processes certificate requests in PKCS#10 format. It can additionally create self-signed certificates, for use as root CAs, for example.
openssl req [-asn1-kludge] [-batch] [-config file] [-days n] [-extensions section] [-in file] [-inform der | pem] [-key keyfile] [-keyform der | pem] [-keyout file] [-md4 | -md5 | -sha1] [-modulus] [-nameopt
option] [-new] [-newhdr] [-newkey arg] [-no-asn1-kludge] [-nodes] [-noout] [-out file] [-outform der | pem] [-passin arg] [-passout arg] [-pubkey] [-reqexts section] [-reqopt option] [-set_serial n] [-subj arg]
[-subject] [-text] [-utf8] [-verbose] [-verify] [-x509]
The x509 command is a multi-purpose certificate utility. It can be used to display certificate information, convert certificates to various forms, sign certificate requests like a "mini CA", or edit certificate trust settings.
openssl x509 [-C] [-addreject arg] [-addtrust arg] [-alias] [-CA file] [-CAcreateserial] [-CAform der | pem] [-CAkey file] [-CAkeyform der | pem] [-CAserial file] [-cert
opt option] [-checkend arg] [-clrext]
[-clrreject] [-clrtrust] [-dates] [-days arg] [-email] [-enddate] [-extensions section] [-extfile file] [-fingerprint] [-hash] [-in file] [-inform der | net | pem] [-iss
uer] [-issuer_hash] [-issuer_hash_old]
[-keyform der | pem] [-md5 | -sha1] [-modulus] [-nameopt option] [-noout] [-ocsp_uri] [-ocspid] [-out file] [-outform der | net | pem] [-passin arg] [-pubkey] [-purpose]
[-req] [-serial] [-set_serial n]
[-setalias arg] [-signkey file] [-startdate] [-subject] [-subject_hash] [-subject_hash_old] [-text] [-trustout] [-x509toreq]
openssl genrsa -out ca.pri 2048
openssl rsa -in ca.pri -pubout -out ca.pub
openssl req -new -key ca.pri -out ca.csr
openssl x509 -req -signkey ca.pri -days 365 -in ca.csr -out ca.crt
openssl genrsa -out server.pri 2048
openssl rsa -in server.pri -pubout -out server.pub
openssl req -new -key server.pri -out server.csr
openssl x509 -req -CA ca.crt -CAcreateserial -CAkey ca.pri -in server.csr -out server.crt
openssl genrsa -out client.pri 2048
openssl rsa -in client.pri -pubout -out client.pub
openssl req -new -key client.pri -out client.csr
openssl x509 -req -CA ca.crt -CAcreateserial -CAkey ca.pri -in client.csr -out client.crt
基于 express 框架
文件名 : www
,在express项目的bin文件夹下
#!/usr/bin/env node
/**
* Module dependencies.
*/
const app = require('../app');
const debug = require('debug')('https-demo:server');
const http = require('http');
const path = require('path');
const https = require('https');
const fs = require('fs');
///---------------------https 部分---------------
//根据项目的路径导入生成的证书文件
const keys_dir = 'keys'
const privateKey = fs.readFileSync(path.resolve(__dirname, keys_dir,'server.pri'), 'utf8');
const certificate = fs.readFileSync(path.resolve(__dirname, keys_dir,'server.crt'), 'utf8');
const ca = fs.readFileSync(path.resolve(__dirname, keys_dir,'ca.crt'), 'utf8');
const credentials = {
key: privateKey,
cert: certificate,
ca: ca,
// 使用客户端证书验证;This is necessary only if using client certificate authentication.
requestCert: true,
// true :如果没有请求到客户端来自信任CA颁发的证书,拒绝客户端的连接
rejectUnauthorized: true
};
const httpsServer = https.createServer(credentials, app);
//创建https服务器
const https_port = 8001;
httpsServer.listen(https_port, function () {
console.log('HTTPS Server is running on: https://localhost:%s', https_port);
});
///---------------------https 部分---------------
//可以根据请求判断是http还是https
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
文件名:一个测试文件,名字随意。
const https = require('https');
const fs = require('fs');
var path = require('path');
const tls = require('tls');
const crypto = require('crypto');
function sha256(s) {
return crypto.createHash('sha256').update(s).digest('base64');
}
let keys = "keys";
let public_key = ""//可以用来加密通信
const options = {
// hostname: '127.0.0.1',
hostname: 'localhost',//与证中的一致
port: 8001,
path: '/',
method: 'GET',
// 客户端私钥
key: fs.readFileSync(path.resolve(__dirname, keys,'client.pri')),
// 客户端证书
cert: fs.readFileSync(path.join(__dirname,keys, 'client.crt')),
// client 端到 CA 签名
ca: [fs.readFileSync(path.join(__dirname, keys,'ca.crt'))],
agent: false,
// 开启双向认证
rejectUnauthorized: true,
checkServerIdentity: function (host, cert) {
// 确保将证书颁发给所连接的主机。
const err = tls.checkServerIdentity(host, cert);
if (err) {
return err;
}
// 固定公钥,类似于固定的 HPKP pin-sha25。
const pubkey256 = 'TuOGwr8LevvniS5mUxDnINYO6FmoRFCdS3tkAM8f7GA=';
//服务器的公钥
let pubkey_server_base64 = cert.pubkey.toString('base64');
public_key = pubkey_server_base64
const pubkey_sha256 = sha256(pubkey_server_base64)
if (pubkey_sha256 !== pubkey256) {
const msg = '证书验证错误: ' +
`'${cert.subject.CN}' 的公钥` +
'与固定的指纹不符';
return new Error(msg);
}
// 固定确切的证书,而不是公钥。证书的指纹,可以从证书上看到
const cert256 = '4D:54:E7:EC:D8:D7:0C:67:9C:E1:27:3C:92:F6:26:E7:08:51:E1:14:02:4A:D9:2B:E2:B7:F9:D5:A3:74:11:F6';
if (cert.fingerprint256 !== cert256) {
const msg = '证书验证错误: ' +
`'${cert.subject.CN}' 的证书` +
'与固定的指纹不符';
return new Error(msg);
}
// 此循环仅供参考。
// 打印链条中所有证书的证书与公钥指纹。
// 通常,将发行人的公钥固定在公共互联网上,同时将服务的公钥固定在私密的环境中。
do {
console.log('主体的常用名称:', cert.subject.CN);
console.log(' 证书的 SHA256 指纹:', cert.fingerprint256);
console.log(' 服务器公钥:', cert.pubkey.toString('base64'));
hash = crypto.createHash('sha256');
console.log(' 公钥的 ping-sha256:', sha256(cert.pubkey));
lastprint256 = cert.fingerprint256;
cert = cert.issuerCertificate;
} while (cert.fingerprint256 !== lastprint256);
},
};
// console.log(options.cert.toString())
options.agent = new https.Agent(options);
const req = https.request(options, ( res) => {
console.log('client connected', res.connection.authorized ? 'authorized' : 'unauthorized');
console.log('状态码:', res.statusCode);
res.setEncoding('utf-8');
res.on('data', (d) => {
process.stdout.write(d);
});
});
req.on('error', (e) => {
console.error(e);
});
req.end();
使用对称加密和非对称加密来实现通信。这一步只需要在项目的具体业务中使用node提供的加解密模块对数据操作即可。
接受方收到消息,先用RSA解密得到AES的秘钥,在使用AES解密出明文内容。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。