node.js-v0.8API解读(5)- Crypto(补完)

2012-09-03 08:04

node.js-v0.8API解读(5)- Crypto(补完)

by snoopyxdy

at 2012-09-03 00:04:50

original http://snoopyxdy.blog.163.com/blog/static/6011744020128211113692

前一篇详细介绍了node的crypto模块的一些常用api,本文对此进行补完,主要介绍“迪菲-赫尔曼密钥交换”(Diffie–Hellman key exchange),它可以让双方在完全没有对方任何预先信息的条件下通过不安全信道创建起一个密钥。这个密钥可以在后续的通讯中作为对称密钥来加密通讯内容。(具体对称密钥的作用请参阅我上篇文章:node.js-v0.8API解读(5)- Crypto

crypto.createDiffieHellman(prime_length)
crypto.createDiffieHellman(prime, [encoding])
用来创建DiffieHellman实例,可以传递一个素数的bit长度来生成或者传递另外一个素数来生成。

注意:以下DiffieHellman 简称dh(不是恶魔猎手哦!)

1、diffieHellman.getPrime([encoding]) 和 diffieHellman.getGenerator([encoding])
获得这个dh实例的素数,以参数encoding的形式, 'binary', 'hex', 或 'base64'. 默认是 'binary'。

2、diffieHellman.generateKeys([encoding])
生成dh的私有key和公有key,此方法根据指定的encoding返回公有key,公有key会传递给另外一方,用来生成对称密钥

3、diffieHellman.getPrivateKey([encoding]) 和 diffieHellman.getPublicKey([encoding])
顾名思义,返回私有key和公有key

4、diffieHellman.setPublicKey(public_key, [encoding]) 和 diffieHellman.setPrivateKey(public_key, [encoding])
顾名思义,设置公有key和私有key,这里nodeapi写错了。

5、diffieHellman.computeSecret(other_public_key, [input_encoding], [output_encoding])
根据 对方的公有 key 算出对称密钥,第二个参数是对方密钥输入的encoding,第三个是对称密钥输出的格式

6、crypto.getDiffieHellman(group_name)
生成一个预定义的dh交换key对象,支持如下几种:'modp1', 'modp2', 'modp5' (defined in RFC 2412) and 'modp14', 'modp15', 'modp16', 'modp17', 'modp18' (defined in RFC 3526)。
返回的对象就像dh实例一样,但是不允许去改变它的私有key和公有key。使用它的优点是通常就是直接使用它不用交换生成key,只需要在握手前使用一样的group系数即可,节约了大家的处理时间和握手时间。
看如下代码示例:

var crypto = require('crypto');
var alice = crypto.getDiffieHellman('modp5');
var bob = crypto.getDiffieHellman('modp5');

alice.generateKeys();
bob.generateKeys();

var alice_secret = alice.computeSecret(bob.getPublicKey(), 'binary', 'hex');
var bob_secret = bob.computeSecret(alice.getPublicKey(), 'binary', 'hex');

/* alice_secret and bob_secret should be the same */
console.log(alice_secret == bob_secret);


我们看下完整的一个Diffie–Hellman key exchange的示例:

var crypto = require("crypto");
var assert = require("assert");

var diffieHellman1 = crypto.createDiffieHellman(256);
var prime1 = diffieHellman1.getPrime('base64');
var diffieHellman2 = crypto.createDiffieHellman(prime1, 'base64');
var key1 = diffieHellman1.generateKeys();
var key2 = diffieHellman2.generateKeys('hex');
var secret1 = diffieHellman1.computeSecret(key2, 'hex', 'base64');
var secret2 = diffieHellman2.computeSecret(key1, 'binary', 'base64');

assert.equal(secret1, secret2);


crypto.randomBytes(size, [callback])
生成加密用的伪随机码,支持2种方法,当传递cb的话就是异步方法,不传cb就是同步方法:

// async
crypto.randomBytes(256, function(ex, buf) {
if (ex) throw ex;
console.log('Have %d bytes of random data: %s', buf.length, buf);
});

// sync
try {
var buf = crypto.randomBytes(256);
console.log('Have %d bytes of random data: %s', buf.length, buf);
} catch (ex) {
// handle error
}


crypto.pbkdf2(password, salt, iterations, keylen, callback)
异步的方法,通过伪随机码来加密迭代数次,利用sha1算法生成一个更加强壮的加密串。我们结合上面的 crypto.randomBytes 来生成一个强壮的加密串。
代码如下:

crypto.randomBytes(128, function (err, salt) {
if (err) { throw err;}
salt = new Buffer(salt).toString('hex');
crypto.pbkdf2('123456', salt, 7000, 256, function (err,hash) {
if (err) { throw err; }
hash = new Buffer(hash).toString('hex');
console.log(hash);
})
})


每个人运行上面的代码输出都不一样。(本例子源自node-cookbook,真是本好书)

相关阅读:
博客原文:node.js-v0.8API解读(5)- Crypto
cnode社区:浅谈nodejs中的Crypto模块