1 Star 0 Fork 0

binny1024 / node-https-demo

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

参考资料:

openssl 相关命令罗列

更多参数及详细内容,可查阅命令手册:man openssl ,命令是按字母顺序排序的。

genrsa

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]

req

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]

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]

生成CA证书

  • 生成CA私钥 ca.pri
openssl genrsa -out ca.pri 2048
  • 生成CA公钥
openssl rsa -in ca.pri -pubout -out ca.pub
  • 生成签名请求文件ca. csr
openssl req -new -key ca.pri -out  ca.csr
  • 生成自签名证书
openssl x509  -req -signkey ca.pri -days 365 -in ca.csr -out ca.crt

生成server证书

  • 生成server私钥 server.pri
openssl genrsa -out server.pri 2048
  • 生成server公钥
openssl rsa -in server.pri -pubout -out server.pub
  • 生成签名请求文件server. csr
openssl req -new -key server.pri -out  server.csr
  • CA签名
openssl x509 -req -CA ca.crt -CAcreateserial -CAkey ca.pri  -in server.csr -out server.crt 

生成client证书

  • 生成server私钥 client.pri
openssl genrsa -out client.pri 2048
  • 生成client公钥
openssl rsa -in client.pri -pubout -out client.pub
  • 生成签名请求文件client. csr
openssl req -new -key client.pri -out  client.csr
  • CA签名
openssl x509 -req -CA ca.crt -CAcreateserial -CAkey ca.pri  -in client.csr -out client.crt 

https服务搭建

基于 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);
}

https客户端

文件名:一个测试文件,名字随意。

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提供的加解密模块对数据操作即可。

  • 明文使用对称加密,如AES算法,效率高些
  • AES的秘钥使用非对称加密,如RSA加密,安全性高

接受方收到消息,先用RSA解密得到AES的秘钥,在使用AES解密出明文内容。

空文件

简介

暂无描述 展开 收起
NodeJS 等 4 种语言
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
NodeJS
1
https://gitee.com/binny1024/node-https-demo.git
git@gitee.com:binny1024/node-https-demo.git
binny1024
node-https-demo
node-https-demo
master

搜索帮助