求逆袭之逆袭星途闪耀百度云 47 48 百度云

(转)nodejs和java中的des/3des加密解密 - Qson.Xu - ITeye技术网站
博客分类:
Java和nodejs中des加解密数据互操作,直接上代码(仅供参考):
var assert = require('assert');
var crypto = require('crypto');
function test_des(param) {
var key = new Buffer(param.key);
var iv = new Buffer(param.iv ? param.iv : 0)
var plaintext = param.plaintext
var alg = param.alg
var autoPad = param.autoPad
var cipher = crypto.createCipheriv(alg, key, iv);
cipher.setAutoPadding(autoPad) //default true
var ciph = cipher.update(plaintext, 'utf8', 'hex');
ciph += cipher.final('hex');
console.log(alg, ciph)
var decipher = crypto.createDecipheriv(alg, key, iv);
cipher.setAutoPadding(autoPad)
var txt = decipher.update(ciph, 'hex', 'utf8');
txt += decipher.final('utf8');
assert.equal(txt, plaintext, 'fail');
test_des({
alg: 'des-ecb',
autoPad: true,
plaintext: '5678',
test_des({
alg: 'des-cbc',
autoPad: true,
plaintext: '5678',
test_des({
alg: 'des-ede3', //3des-ecb
autoPad: true,
key: 'abcd',
plaintext: '5678',
test_des({
alg: 'des-ede3-cbc', //3des-cbc
autoPad: true,
key: 'abcd',
plaintext: '5678',
import javax.crypto.C
import javax.crypto.SecretK
import javax.crypto.spec.IvParameterS
import javax.crypto.spec.SecretKeyS
import mons.codec.binary.H
import org.junit.T
public void encrypt_3des_ecb() throws Exception {
byte[] key = "abcd".getBytes();
byte[] plainText = "5678".getBytes();
KeySpec myKeySpec = new DESedeKeySpec(key);
SecretKeyFactory mySecretKeyFactory = SecretKeyFactory.getInstance("DESede");
SecretKey secretKey = mySecretKeyFactory.generateSecret(myKeySpec);
SecretKey secretKey = new SecretKeySpec(key, "DESede");
Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptedData = cipher.doFinal(plainText);
System.out.println("encrypt_3des_ecb: " + Hex.encodeHexString(encryptedData));
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decryptPlainText = cipher.doFinal(encryptedData);
org.junit.Assert.assertArrayEquals(decryptPlainText, plainText);
public void encrypt_3des_cbc() throws Exception {
byte[] key = "abcd".getBytes();
byte[] plainText = "5678".getBytes();
IvParameterSpec iv = new IvParameterSpec("".getBytes());
SecretKey secretKey = new SecretKeySpec(key, "DESede");
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
byte[] encryptedData = cipher.doFinal(plainText);
System.out.println("encrypt_3des_cbc: " + Hex.encodeHexString(encryptedData));
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
byte[] decryptPlainText = cipher.doFinal(encryptedData);
org.junit.Assert.assertArrayEquals(decryptPlainText, plainText);
public void encrypt_des_ecb() throws Exception {
byte[] key = "".getBytes();
byte[] plainText = "5678".getBytes();
SecretKey secretKey = new SecretKeySpec(key, "DES");
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptedData = cipher.doFinal(plainText);
System.out.println("encrypt_des_ecb: " + Hex.encodeHexString(encryptedData));
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decryptPlainText = cipher.doFinal(encryptedData);
org.junit.Assert.assertArrayEquals(decryptPlainText, plainText);
public void encrypt_des_cbc() throws Exception {
byte[] key = "".getBytes();
byte[] plainText = "5678".getBytes();
IvParameterSpec iv = new IvParameterSpec("".getBytes());
SecretKey secretKey = new SecretKeySpec(key, "DES");
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
byte[] encryptedData = cipher.doFinal(plainText);
System.out.println("encrypt_des_cbc: " + Hex.encodeHexString(encryptedData));
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
byte[] decryptPlainText = cipher.doFinal(encryptedData);
org.junit.Assert.assertArrayEquals(decryptPlainText, plainText);
结果:
nodejs 输出结果
des-ecb cb22e0c49a73e0e0cb22e0c49a73e0e008bb5db6b37c06d7
des-cbc 388d44f8b0f709c0915e14abc8ebd96110ab0d
des-ede3 0a5f769c1a6ebc1a6eb5713bba29a037c699da
des-ede3-cbc eabe3e95acedda66abb82b44b5f8f62
java输出结果
encrypt_des_ecb: cb22e0c49a73e0e0cb22e0c49a73e0e008bb5db6b37c06d7
encrypt_des_cbc: 388d44f8b0f709c0915e14abc8ebd96110ab0d
encrypt_3des_ecb: 0a5f769c1a6ebc1a6eb5713bba29a037c699da
encrypt_3des_cbc: eabe3e95acedda66abb82b44b5f8f62
浏览: 76981 次
来自: 广州
一笑而过就好了,反正我不赶铁路nodejs常用4中加密方式详解
* @加密模块
* @md5可以被彩虹表破解,这里就不用啦
//导入模块
var crypto = require('crypto');
* @aes192加密模块
* @param str string 要加密的字符串
* @param secret string 要使用的加密密钥(要记住,不然就解不了密啦)
* @retrun string 加密后的字符串
exports.getEncAse192 = function(str, secret) {
var cipher = crypto.createCipher(&aes192&, secret);
var enc = cipher.update(str, &utf8&, &hex&);
enc += cipher.final(&hex&);
* @aes192解密模块 * @param str string 要解密的字符串
* @param secret string 要使用的解密密钥(要和密码的加密密钥对应,不然就解不了密啦) * @retrun string 解密后的字符串
exports.getDecAse192 = function(str, secret) {
var decipher = crypto.createDecipher(&aes192&, secret);
var dec = decipher.update(str, &hex&, &utf8&);
dec += decipher.final(&utf8&);
/** * @Hmac-sha1加密模块 (每次加密随机,不可逆)
* @param str string 要加密的字符串
* @param secret string 要使用的加密密钥
* @retrun string 加密后的字符串
exports.getHmac = function(str, secret) {
var buf = crypto.randomBytes(16);
secret = buf.toString(&hex&);
var Signture = crypto.createHmac(&sha1&, secret);
Signture.update(str);
var miwen=Signture.digest().toString(&base64&);
* @sha1加密模块 (加密固定,不可逆)
* @param str string 要加密的字符串
* @retrun string 加密后的字符串
exports.getSha1 = function(str) {
var sha1 = crypto.createHash(&sha1&);
sha1.update(str);
var res = sha1.digest(&hex&);
标签(Tag):
------分隔线----------------------------
------分隔线----------------------------《Nodejs开发加密货币》之十:三张图让你全面掌握加密解密技术
《Nodejs开发加密货币》,是一个加密货币产品的详细开发文档,涉及到使用Nodejs开发产品的方方面面,从前端到后台、从服务器到客户端、从PC到移动、加密解密等各个环节。代码完全开源、文章免费分享。 相关资源见
加密解密技术,涉及面很广,这里,把前人的研究成果汇总起来,通过图表的形式来帮助记忆和筛选,方便日后使用。内容主要包括两个方面,一个是场景与算法,一个是Nodejs的相关模块或组件。共三张脑图,具体请看:
1.加密解密纵览
下面这张图,是在 《密码学一小时必知》(见参考)基础上完成的,原作者是Colin Percival,密码学方面的专家,FreeBSD项目的安全长官,Tarsnap在线备份服务的创始人,scrypt密钥衍生算法的作者,非常值得参考学习。译者是
,翻译贡献这样的好文,包括下面有关论述场景与算法的实践指南,值得去为他点赞。
这张图,可以告诉你密码学中的概念,目的,案例,以及最佳的实践经验。
2.场景与算法
这张图,是基于 《现代密码学实践指南(2015年)》(见参考) 完成的。可以说,在上一张图的基础上,更加具体,特别是对于场景的描述,让码农可以更加方便的作出正确的选择,值得拥有。其中,标注序号的,是有优先级的。
3.Nodejs中的的加密和解密、签名与认证
这张图,主要参考了官方文档及其他一些文档(见参考),按照我个人的理解画得。如果你使用Nodejs,基本上拿来看看图解,就能直接用了。特别是,默认选择了ed255519组件,如果你看了上面两篇实践,就知道这是签名与认证最好的选择,因此这里可以肯定的说,Crypto模块的签名与认证还是暂时不要用吧。Ebookcoin就是这么实践的,具体见下一篇介绍。另一个是Natrium组件,也可以用于签名和认证,但主要是用来非对称加密和解密的。这张脑图里的三个组合,按照上面的实践经验来说,应该是当前Nodejs加解密应用领域的最佳组合方案。
4.趣味实践
还是用在《》里的的例子吧,设定角色,男生叫Bob,他的女友叫Alice。
Bob想向女友表达埋藏已久的心声“I love you!”,但碍于男人的颜面(男人都这样吗?),不好意思当面说出口,只好加密传输。这里基于一个可行的假设,就是他们已经拥有彼此的公钥,或者可以简单获得。
加密:不能让别人看到信息;
解密:女友可以恢复并查看;
签名:Bob可以签名信息,确保不被篡改;
认证:女友收到信息,可以验明正身,确认是Bob所发,而不是别人的恶作剧。
利用以上三张图,我们可以很快拿出技术方案。
加密与解密技术:第二张图显示说,这种加密之后又解密原文的场景非常少见。技术上,最好使用NaCl,其次是libsodium(背后仍然是NaCl),但是搜索了一下github,Nodejs社区还没有相关NaCl稳定的封装包,libsodium倒是有一个Natrium(但是,写作本文时,连安装都没有成功,有验证成功的,请告诉我一声)。因此,只能选择使用Crypto简单加密和解密。
签名与验证技术:当然最好的选择是ed25519了。
新建一个简单的Nodejs工程, 代码在这里:
(1)生成密钥对
Bob没有使用随机字符串,而是使用一个密码,并采取SHA256算法生成密钥对,请看思维导图,有关hash的部分。
var crypto = require('crypto');
var ed25519 = require('ed25519');
var bobsPassword = 'This is my password, you don`t guess it!';
var hash = crypto.createHash('sha256').update(bobsPassword).digest();
var bobKeypair = ed25519.MakeKeypair(hash);
(2)给信息加密和签名
通常是先加密后签名。
这里使用Crypto给信息进行了简单加密,把Bob的公钥作为加密键值(但是既然是公钥,谁会不知道呢,除非Bob只把公钥给了Alice),可能还得Bob告诉Alice使用什么算法来解密。
var message = 'Hi Alice, I love you!';
var msgCiphered = cipher('aes192', bobKeypair.publicKey, message);
var signature = ed25519.Sign(new Buffer(msgCiphered, 'utf8'), bobKeypair.privateKey);
(3)给Alice发送签名信息
这个就各显神通了。
(4)Alice验证并解密
通常是先验证后解密。
作为Bob的好朋友,Alice有他的公钥。
if (ed25519.Verify(new Buffer(msgCiphered, 'utf8'), signature, bobKeypair.publicKey)) {
var msg = decipher('aes192', bobKeypair.publicKey, msgCiphered);
console.log('签名合法,信息来自Bob!');
console.log('Bob said: ', msg);
console.log('签名不合法!');
(5)补充代码
上面用到的Crypto的加密解密方法:
function (algorithm, key, buffer){
var encrypted = "";
var cip = crypto.createCipher(algorithm, key);
encrypted += cip.update(buffer, 'utf8', 'hex');
encrypted += cip.final('hex');
function decipher(algorithm, key, encrypted){
var decrypted = "";
var decipher = crypto.createDecipher(algorithm, key);
decrypted += decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
(6)运行实例
使用下面的命令,可以运行上述代码:
$ git clone https:///imfly/nodejs-practice
$ cd nodejs-practice
$ npm install
$ node crypto/
输出结果:
签名合法,信息来自Bob!
Hi Alice, I love you!
本系列文章即时更新,若有兴趣,可通过Star收藏,^-^
本源文地址:
电子书阅读:
看过本文的人也看了:
我要留言技术领域:
收藏提示你已经自动关注本知识库了哦!
取消收藏确定要取消收藏吗?
删除图谱提示你保存在该图谱下的知识内容也会被删除,建议你先将内容移到其他图谱中。你确定要删除知识图谱及其内容吗?
删除节点提示无法删除该知识节点,因该节点下仍保存有相关知识内容!
删除节点提示你确定要删除该知识节点吗?Node.js 服务器的加密技术 - 简书
<div class="fixed-btn note-fixed-download" data-toggle="popover" data-placement="left" data-html="true" data-trigger="hover" data-content=''>
写了46797字,被216人关注,获得了422个喜欢
Node.js 服务器的加密技术
!!!!!! 你们这些旱鸭子比我想象得要厉害多了,看来我要认真一些了 !!!
现在来聊聊服务器的加密,这文章会覆盖整个 Node.js 加密的前因后果,所以会比较长,内容分为:
在此之前呢,先回答一下混乱的问题。
什么是 SSL ?
Secure Sockets Layer,这是其全名,他的作用是协议,定义了用来对网络发出的数据进行加密的格式和规则。
服务器 | data | -- SSL 加密 --& 发送 --& 接收 -- SSL 解密 -- | data | 客户端
服务器 | data | -- SSL 解密 --& 接收 &-- 发送 -- SSL 加密 -- | data | 客户端
1994年,Mozilla 前身 NetScape 公司制定出 1.0 版本。1995年,NetScape 正式发布 SSL,版本是 2.0。1996年,NetScape 发布 3.0,获得广泛应用。1999年,ISOC 接管 SSL,制定世界标准同时升级 SSL 版本,改称 TLS,版本 1.0。2001年,ISOC 的较新版本 TLS 1.2。
注:TLS 1.0 等同于 SSL 3.1,TLS 1.1 等同于 SSL 3.2,TLS 1.2 等同于 SSL 3.3。
什么是协议?
你应该听说过 IP 协议,TCP 协议。所谓协议,是程序员在编程时,大家对发送的数据格式采用的一种共同结构,也就是标准数据结构。
比如, HTTP 请求头的协议采用
GET /demo HTTP/1.1\n
Connection: keep-alive\n
这样的格式,每一个厂商在开发的网络软件都遵循这一标准。这样在另一个接受端,可以采用相同的解析代码来编程。
什么是 OpenSSL?
OpenSSL 是在程序上对 SSL 标准的一个实现,提供了:
通用加密库
libssl TLS/SSL 的实现
openssl 命令行工具
程序员可以通过免费开源的 OpenSSL 库来对自己的应用程序提供 SSL 加密。OpenSSL 由 Eric A. Young 和 Tim J. Hudson 在 1995 年提出。1998年,OpenSSL 项目组接管,并制定标准规范。
什么是 SSH?
你可能应该听说过 telnet,一个不安全的通过命令行进行服务器客户端通信的工具。SSH 是使用 OpenSSL 加密的这样的通信工具,提供了更多安全功能。
服务器安装 $ sudo aptitude install openssh-server
服务器启动 $ sudo service ssh start
客户端连接 $ ssh xiaoming@192.168.1.101
Now, let's go.
从 OpenSSL 开始
首先,Node.js 是完全采用 OpenSSL 进行加密的,其相关的 TLS HTTPS 服务器模块和 Crypto 加密模块都是通过 C++ 在底层调用 OpenSSL 。
OpenSSL --& crypto --& tls --& https
OpenSSL 实现了对称加密:
AES(128) | DES(64) | Blowfish(64) | CAST(64) | IDEA(64) | RC2(64) | RC5(64)
非对称加密:
DH | RSA | DSA | EC
以及一些信息摘要:
MD2 | MD5 | MDC2 | SHA | RIPEMD | DSS
其中信息摘要是一些采用哈希算法的加密方式,也意味着这种加密是单向的,不能反向解密。这种方式的加密大多是用于保护安全口令,比如登录密码。这里面我们最长用的是 MD5 和 SHA (建议采用更稳定的 SHA1)。
安装很简单,从
$ ./configure
$ make install
或者你也可以简单的通过
$ apt-get install openssl
$ aptitude install openssl
另外,你可能需要安装一些依赖包:
$ aptitude install libssl-dev
前面说了,OpenSSL 提供了加密库和一个命令行工具用来管理加密,我们现在来看一下 OpenSSL 的一些常用命令:
$ openssl s_client -connect 127.0.0.1:8000
// 连接服务器
$ openssl version -a
// 显示版本和编译参数
$ openssl ?
// 显示支持的子命令
$ openssl ciphers
// 显示 SSL 密码组合列表
$ openssl speed [name]
// 测试算法速度
$ openssl enc -e -rc4 -in ./file1 -out ./file2
// 加密文件
$ openssl enc -d -rc4 -in ./file2 -out ./file1
// 解密文件
$ openssl sha1 & ./file1
// 计算 hash 值
$ openssl genrsa -out ./a.key 1024
// 生成 RSA 密钥对
$ openssl rsa
./a.key -pubout -out ./a.pub
// 从密钥中提取公钥
密钥位数 : 1024 | 2048 | 4096
openssl genrsa 是常用的生成密钥公钥的命令,-out 文件路径 是输出的文件路径。
TLS HTTPS 服务器
想要建立一个 Node.js TLS 服务器,需要使用 tls 模块:
var Tls = require('tls');
在开始搭建服务器之前,我们还有些重要的工作要做,那就是证书,签名证书。
基于 SSL 加密的服务器,在与客户端开始建立连接时,会发送一个签名证书。客户端在自己的内部存储了一些公认的权威证书认证机构,即 CA。客户端通过在自己的 CA 表中查找,来匹配服务器发送的证书上的签名机构,以此来判断面对的服务器是不是一个可信的服务器。
如果这个服务器发送的证书,上面的签名机构不在客户端的 CA 列表中,那么这个服务器很有可能是伪造的,你应该听说过“中间人攻击”。
+------------+
| 真正的服务器 |
选择权:连接?不连接?
+------------+
+------------------ | 客户端 |
+--------------+
| 拦截通信包
| 破坏者的服务器 | ----------+
+--------------+
证书是伪造的
如果你使用 $ openssl s_client -connect ,会发现屏幕上为你显示 self signed certificate。
如果你以前使用 firefox 浏览器造访过著名的 12306,会收到一个“不信任的连接,是否仍然连接”的页面,来给你提供一个安全提示的选择。
OO,有些东西就是很逗,不是么!
存在即是合理的!
让我们嘲笑这个逗比一样的话,有时候存在是因为愚昧无知,而不是合理。
兔子不吃窝边草.近水楼台先得月.
这种自我矛盾的蠢话多的是呀!不要当真!
看到这里,你也应该明白为什么最近 Google 和 Mozilla 一直在推进 HTTPS 和 HTTP 2.0。
让我们来伪造证书
基于测试的目的,我们现在表演一下整个制造证书的过程。构建 TLS HTTPS 服务器,需要:
证书签发申请
权威机构对证书签发申请签名后的证书
第3个需要每年缴纳几千元人民币,以维持安全证书的认证费用。从程序员角度来讲,我们可以自己签名,从而创建一个不受信任的证书。(仅限于研究使用,如果你用在自己的服务器上,你的服务器就会有被别人冒充的风险)
所有这些需要使用 OpenSSL 来实现:
1) 生成密钥
$ openssl genrsa -out ./ca-key.pem 1024
这条命令为你生成一个 1024 位长度的加密密钥,放在你的当前目录中的 ca-key.pem 文件中。这个文件的内容是类似这样的,每行以一个 '\n' 换行符:
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDEw2LYED8+AgLHOtrwXLCXCm2okHOh6Wx7FJ5GVlsdMysJRD8r
dTfTr3kRo/wKssZgGBydIrUPxk6Nvywdcp0V2yp5NjlruvgIkTFL/tkecJumuLc3
XtQ1J2GwLCqkUjpnll9MzKENCpNeX1BDSJNJ6QRkXRk/13nY4HArdrHdEQIDAQAB
AoGAGnNRlE4K0mEe0n189Rbgvk0ulJxmjvt8E8efx0DQmspIHMTJ4SOuz4wlMFPl
C+Mge8aCAjWqNWapJLDwUz0XFJ6yd/nvF7Ludc97NB95uSDeuY/nFVQnAbSAd9sS
uD/cCJLLZ+8XmeUktUSP9cCR6zGgkvPEPOXreFg3xqVDjIkCQQDolDRT14UvaxMC
f6JyjHZ8bj7FDQyqBj+hQFAB4WVA2q4pZ+WGUJpqwTb4WvfW27tX/DnHZkVSuFGa
j2z8mc67AkEA2JPd5DYIqIu3m5D0YaWdIIYi5FyL5ecRuXEKv5GexIlhePBZqT2l
zXt9yI6YUOQjeOusOy2kRSqm9IMnDhv0owJBAMdpYuBMFo6MkNUAmEj8tA6F+926
DZSuHNpmKPMjzUvo85De2wXpkCxeE4KnhH49EgkjYmrb/i4piRYrSTffrEcCQQCx
I8gyVyufx58mY1ou38lzh6LUSwm1wdgSZ+4Vn+JO99q8k0GSljSdq6rGtjLIvsBw
r7oQMRWR6P/jL75q4NynAkBYQKBDWPiSCGmu0vr0uf3qLhtZjMenBZ2Z9qWdBGKW
CNGxpKgdFeM05XpUg/cJOS/fcvMV2GcMldI62k3JwoBF
-----END RSA PRIVATE KEY-----
2) 生成证书签发申请
$ openssl req -new
./ca-key.pem
./ca-csr.pem
这条命令,通过对方刚才生成的密钥 ca-key.pem,生成一个证书签发申请 ca-csr.pem,然后你应该把这个发送给认证机构为你签名,并缴纳费用,获得一个权威的认证证书。
这个文件的内容类似这样:
-----BEGIN CERTIFICATE REQUEST-----
MIIBhDCB7gIBADBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEh
MB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEB
AQUAA4GNADCBiQKBgQDEw2LYED8+AgLHOtrwXLCXCm2okHOh6Wx7FJ5GVlsdMysJ
RD8rdTfTr3kRo/wKssZgGBydIrUPxk6Nvywdcp0V2yp5NjlruvgIkTFL/tkecJum
uLc3XtQ1J2GwLCqkUjpnll9MzKENCpNeX1BDSJNJ6QRkXRk/13nY4HArdrHdEQID
AQABoAAwDQYJKoZIhvcNAQEFBQADgYEAMs/iPk5wyhpp6LUib4d93d8Yv5/5hIt+
EiPTU0KQRIhJtt+mGAipgsPC5KWgIPii+/cQbx0M/1/QJLnlW2DiNKc7sOQiJza3
7BoO9VtJl+ufZ7B1CjEfTWNHHOvA2vYhCKcBPOQXf+E9MbjWznAPwTmjmCznHtWo
RVQ8R4sSCKo=
-----END CERTIFICATE REQUEST-----
3) 对证书签发申请进行签名,生成签名证书
这里,我们来制造一个自签名的证书,这是一个不受信任的证书,实际服务器中你不应该使用。
$ openssl x509 -req
-signkey ./ca-key.pem
./ca-csr.pem
./ca-cert.pem
使用前面生成的密钥、证书签发申请,生成 ca-cert.pem 文件。这个文件的内容类似这样:
-----BEGIN CERTIFICATE-----
MIICATCCAWoCCQCphVNXJELjIjANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB
VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
cyBQdHkgTHRkMB4XDTE1MDcxMTAxMTg1OVoXDTQyMTEyNTAxMTg1OVowRTELMAkG
A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxMNi
2BA/PgICxzra8FywlwptqJBzoelsexSeRlZbHTMrCUQ/K3U30695EaP8CrLGYBgc
nSK1D8ZOjb8sHXKdFdsqeTY5a7r4CJExS/7ZHnCbpri3N17UNSdhsCwqpFI6Z5Zf
TMyhDQqTXl9QQ0iTSekEZF0ZP9d52OBwK3ax3RECAwEAATANBgkqhkiG9w0BAQUF
AAOBgQAjNF0fWyI/XLegpj2dnk+RQXJTljRtcBuJ+qU2IGknTT5NpqiRaCxWyH52
rD4ZEV8GVPJ8BqarKuYPubqumd7KXa2Ulyf73dGHyvaykgqxi8Vm+B9G2Sfukdt8
vLQ1fy39qF5ZnTVMR/4KaYbFa7jXHSxdJak395D1OUNJBv3rqA==
-----END CERTIFICATE-----
4) 验证证书的签名
  如果你想实验的话,可以使用 OpenSSL 对证书签名进行验证:
$ openssl verify -CAfile ca-cert.pem ca-cert.pem
这是对两个签名证书核对,一个是服务端发送的证书,一个是客户端自己的证书,实际过程中更像是这样:
$ openssl verify -CAfile server-cert.pem client-cert.pem
浏览器内部会为你完成这个过程。如果你有使用过淘宝安全证书的话,会对此有一些理解。
Node.js TLS HTTPS 服务器也会在内部完成这一过程。
TLS 服务器 HTTPS 服务器
构建 TLS 服务器非常简单,而且是基于 epoll kqueue 这样的高 IO 模型。
var Tls = require('tls');
= require('fs');
var server = Tls.createServer({
: Fs.readFileSync('./ca-key.pem'),
// 服务器密钥
: Fs.readFileSync('./ca-cert.pem'),
// 服务器签名证书
handshakeTimeout
// 握手超时时间,default=120s
// 有效证书认证机构
passphrase
: '123456',
// 服务器密钥解析密码
requestCert
// 客户端需要发送签名证书
rejectUnauthorized : true
// 客户端发送的证书必须是有效认证机构签名
// ciphers
// 加密组件
// ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL
// secureProtocol : secureProtocol,
// 强制使用版本的安全协议
// secureOptions
: secureOptions
// 安全方法配置
server.listen(10010);
server.on('secureConnection', function (socket) {
console.log('Authorized: ',
socket.authorized);
// 客户端签名证书是 CA 签名?
console.log('AuthorizationError: ', socket.authorizationError);
// 验证错误原因
console.log('Certificate: ',
socket.getPeerCertificate());
// 客户端签名证书信息
console.log('Cipher: ',
socket.getCipher());
// 当前加密组件的信息
socket.setEncoding('utf8');
socket.on('data', function (data) {
console.log('Data: %j', data);
socket.on('end', function () {
console.log('End');
process.stdin.pipe(socket);
process.stdin.resume();
server.on('newSession', function (sessionId, sessionData) {
console.log('SessionId',
sessionId);
console.log('SessionData',
sessionData);
如果愿意的话,你可以自己写一个 SSH!
TLS.Server 模块继承自 Net.Server,为其扩充了 SSL 内容,所有的其他操作跟 Net.Server 一模一样。
Tls.createServer(options, [listener]) 其中的 options 提供了 SSL 配置。
ca 是一个权威认证机构的列表,用于服务器查找客户端的签名证书是不是伪造的
key 你的密钥字符串或者 Buffer,只需要 readFileSync() 你的密钥文件即可
cert 你的证书字符串或者 Buffer,只需要 readFileSync() 你的证书文件即可
handshakeTimeout 服务器客户端连接认证会进行加密算法操作,如果时间过长,就断开连接。如果你不想自己配置这一项,那么默认是 120 秒
passphrase 当生成密钥时,会请你为文件输入一个解析密码,也可以输入空,这一项就是为服务器提供解析文件的密码
requestCert 要求客户端必须发送证书,不然就断开连接
rejectUnauthorized 要求客户端的证书必须是 CA 认证的,不然就断开连接,当测试的时候应该设置为 false,当用于生产时,应该设为 true
ciphers 使用的 OpenSSL 加密组件,这个可以不设置,采用系统默认的。除非遇到重大漏洞需要修改的时候
需要重要考虑的配置项大体是以上内容。
'secureConnection' 是 TLS 服务器特有的事件,当安全认证成功的时候触发。
你可以使用 OpenSSL 来测试下你的 TLS 服务器:
$ openssl s_client -connect 127.0.0.1:10010
对于 HTTPS 服务器,更简单了,他是 TLS 服务器的继承,
var Https = require('https');
https.createServer(options);
其中的 options 跟 TLS 服务器一模一样,其余的操作跟 http.Server 是一样的。
net.socket --& net.Server --& http.Server
net.socket --& tls.TLSSocket + net.Server --& tls.Server + http.Server --& https.Server
TLS HTTPS 客户端
编写 TLS 客户端,相比 TCP 客户端,也仅限于 options 上的变化:
var Tls = require('tls');
= require('fs');
var socket = Tls.connect({
: Fs.readFileSync('./ca-key.pem'),
// 客户端密钥
: Fs.readFileSync('./ca-cert.pem'),
// 客户端签名证书
// 有效证书认证机构
passphrase
: '123456',
// 客户端密钥解析密码
rejectUnauthorized : true
// 服务器发送的证书必须是有效认证机构签名
// secureProtocol
// 安全协议
}, function() {
console.log('client connected', socket.authorized ? 'authorized' : 'unauthorized');
process.stdin.pipe(socket);
process.stdin.resume();
socket.setEncoding('utf8');
socket.on('data', function (data) {
console.log('Data: %j', data);
socket.on('end', function () {
console.log('End');
socket.end();
socket.on('error', function (err) {
console.log('Error: ', err);
Crypto 加密解密
Node.js 中的 TLS HTTPS 服务器的加密操作都来自 crypto 模块,而 crypto 则是对 OpenSSL 库的调用。重要的细节不再讨论了,只给出实际的使用方法,具体参数可以参考官方文档。
哈希加密 (单向)
Hash 普通哈希加密
Hmac 带有密钥的哈希加密
Hash 加密:
= Crypto.createHash('sha1');
var result = hash.update('a')
.update('a')
.digest('hex');
输出 e0cfc65c41454cec9c4d2611bfb37 这样使用 sha1 算法的16进制字符串。
你会看到 update() 调用两次,实际上这个方法可以不停调用,上边的
.update('a')
.update('a')
.update('aa')
Hmac 加密:
= Crypto.createHmac('sha1', '123456');
var result = hmac.update('a')
.update('a')
.digest('hex');
输出 bac0fa754acdabeb79。这个加密提供了 '123456' 这样的可以设置密钥,你可以为其设置上面通过 OpenSSL 生成的密钥字符串,这样的加密级别更高。
加密解密 (双向)
Cipher 和 Decipher 分别是 Node.js 提供的可操作的加密和解密抽象。使用方式如下:
Cipher 加密 abc010:
var cipher = Crypto.createCipher('aes192', '123456');
cipher.update('abc',
cipher.update('010', 'binary');
var result = cipher.final('hex');
输出 a16a2e4e1b22f3c824f159d3b5800c06。一个使用 aes192 算法加密过的字符串。
Decipher 解密 a16a2e4e1b22f3c824f159d3b5800c06:
var decipher = Crypto.createDecipher('aes192', '123456');
decipher.update('a16a2e4e1b22f3c824f159d3b5800c06', 'hex');
var result
= decipher.final('utf8');
输出 abc010,原始的数据。
签名和认证
Sign 和 Verify 是对 OpenSSL 签名认证的封装。
Sign 签名:
= Crypto.createSign('RSA-SHA256');
var result = sign.update('abc')
.update('010')
`-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQClyE/ApYk91LDdnhM8qIyukbl1p1Ek3z/5bAKq7bCyfevtw3DI
JIwJIyHpGjnosR6/4phApcOqTpLNVJ/Nc0AKWwZcEFlRO7Uty3EFBU8EbTTiCV2N
NKYJIvGnxV+43ubyuYla/RjwylOktUyTVHvMz4o3mVohW4FLaEiRu6rEIQIDAQAB
AoGBAJGdLE/uFmn005UVL5hsA4WiAeBRonhcj3ipYn54YGenKv+gVwO09jtgXHy+
yHaWfIfWpBzEfOSuN0ubNPHkdS45cEtgWtvX6OYuMWNr64YRW6YevxDr4Ui7bGdh
a+Zk0fkmchjvrgycD8MDLbqTFIyFkMAd6VUOY7YVRNlxMq8xAkEA0HcxdeUCrruS
JkXmGMt5g1HkJXrqpbRuQ4vPwQM+q6QuT5fk44MGj0U42feqFWfwMnPGAh6dkN0E
nS3kC6UyuwJBAMuVkRmeAM0HkB883e9rCdnsIzfqLdCFiOKKmdrBlxqfHlEqp8bD
2DgMYTS3s+3yQqQuBjkRxNQ5/Fw7E+lInNMCQC+PghFLtlj3IljpCZ4OjiKPxGVo
rbAwgheXBkca3ml6g7ZVCTt+4Tg+qsHP51YK6JoaH8rMAVbTlgHmPmkJv5ECQGmz
l2nQkqPheF/vr19+mNfP9h0y9mSc4IyW3/knqHfHA+uqlP/rcVjwfIvtkXtK3HT3
/H0nD6YNEU0l01m9PMcCQQCGtxn5szckko+6ketDhuJpNlUxU4gux0TidgDRkDQp
iF8QnAVbE6kDLlw/M1/Kf5mXS4+EssVzy1pUx0fZpgAw
-----END RSA PRIVATE KEY-----`,
// 签名编码
如你所看到的,这些方法需要一个使用 OpenSSL 生成的密钥,然后为其生成一个不受信任的签名。生成一个字符串:
53e8f22eb539be7d37a2c1d2dc5c0d7c1fdee
b7afb004e7dbecc4d68
dbc3f22f69bc3bc431de9f54
e1af7e5f697a2e4d3b9a344
5f7c76251f88ddd48fbf53be444f6d817f1e7ef2784d67
556e5f5ddef2dfc
Verify 认证证书:
var verify = Crypto.createVerify('RSA-SHA256');
var result = verify.update('abc')
.update('010')
`-----BEGIN CERTIFICATE-----
MIICWDCCAcGgAwIBAgIJAO5P5yii8BuLMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTUwNzA5MTAzNDI3WhcNMTUwODA4MTAzNDI3WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
gQClyE/ApYk91LDdnhM8qIyukbl1p1Ek3z/5bAKq7bCyfevtw3DIJIwJIyHpGjno
sR6/4phApcOqTpLNVJ/Nc0AKWwZcEFlRO7Uty3EFBU8EbTTiCV2NNKYJIvGnxV+4
3ubyuYla/RjwylOktUyTVHvMz4o3mVohW4FLaEiRu6rEIQIDAQABo1AwTjAdBgNV
HQ4EFgQUGsVvaLFUxW+hMc/jVpvQXH5hzL0wHwYDVR0jBBgwFoAUGsVvaLFUxW+h
Mc/jVpvQXH5hzL0wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAXS8da
q3Ybw3+KvIZz/tAGLkPshv4J7jwIKNvlZeMX0dGZsd1faZJyrCmzZ7Go43L24zqg
rAwXOlfz+pjoGEaQSyTXOJX23ZozCGEzI2OgmLxLuk2Wfn3OUiQK8RqjrOzXosTR
3RcofenE7hTk17gjs50aDHc/hu363U3gklxnWA==
-----END CERTIFICATE-----`,
'53e8f22eb539be7d37a2c1d2dc5c0d7c1fdee' +
'b7afb004e7dbecc4d68' +
'dbc3f22f69bc3bc431de9f54' +
'e1af7e5f697a2e4d3b9a344' +
'5f7c76251f88ddd48fbf53be444f6d817f1e7ef2784d67' +
'556e5f5ddef2dfc',
// 签名编码
输入双方认可的公钥,对方的签名,然后输出 true 或者 false 表示双方的证书是否一致。
That's all!
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
被以下专题收入,发现更多相似内容:
如果你是程序员,或者有一颗喜欢写程序的心,喜欢分享技术干货、项目经验、程序员日常囧事等等,欢迎投稿《程序员》专题。
专题主编:小...
· 258640人关注
干货技术文。
· 3776人关注
Linux Nginx NodeJS MongoDB 闲谈,聊聊好用的Nodejs和优雅前卫的javascript.
· 1335人关注
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
选择支付方式:

我要回帖

更多关于 逆袭之星途闪耀 的文章

 

随机推荐