在上一篇文章里讨论了crypto模块里的一些常用方法。在0.6系列以后,crypto模块的改动非常大,增添了DiffieHellman、pbkdf2、randomByes三大块。这三个也是非常有趣的东西,在这里和大家分享一下。
DiffieHellman
看着名字很恐怖,不过却是很有趣的东西。有没有想过,大家彼此不告诉对方敏感信息,确能够共同知道一个密钥?DiffieHellman算法就可以实现这一点。
The Diffie–Hellman key exchange method allows two parties that have no prior knowledge of each other to jointly establish a shared secret key over an insecure communications channel.
亮点在加粗的部分,密钥交换方法,而且不需要走https或者其他专用链接。wiki文章已经对该算法做了很详细的解释,我也仿造这里面的说明,做了一个简单的实现,希望能阐明其工作方式。NodeJS的实现有如下特点:
- 算法中的初始根(Primitive Root)始终是2
- 算法中可以帮你选择Private Integer和Private Key,详见generateKEys方法
- 如果不指明,生成的密钥、公钥全都是binary格式
- 我本想实现wiki中的那个例子,可是node的实现似乎不允许使用那么小的prime;手工计算A、B的合法性、可能性似乎也值的怀疑
var crypto = require("crypto"),
Buffer = require("buffer").Buffer;
var alice, bob, A, a, B, b, p, s1, s2;
alice = crypto.createDiffieHellman(8);//using a 8 bits length prime
A = alice.generateKeys("hex");
a = alice.getPrivateKey("hex");//this is secret
p = alice.getPrime("hex");
console.log("Public Key of alcie: ", alice.getPublicKey("hex"), A);
console.log("Private Key of alice: ", a);
console.log("Prime: ", p);
//sending p and A to Bob
bob = crypto.createDiffieHellman(p, "hex");//Bob should use the same prime
B = bob.generateKeys("hex");
b = bob.getPrivateKey("hex");
console.log("Public Key of bob", bob.getPublicKey("hex"), B);
console.log("Private Key of bob: ", b);
s2 = bob.computeSecret(A, "hex", "hex");
//sending B to Alice
s1 = alice.computeSecret(B, "hex", "hex");
console.log("Shared Secret:", s1, s2);
PBKDF2
PBKDF(Password-Based Key Derivation Function)可以用来生成一个更高强度的密码。之前谈到的不管是对称加密(Symmetric Cryptography)、还是像RSA这样的非对称加密(Asymmetric Cryptography、Public-Key Cryptography),都会涉及一个“初始的密码”。这个密码用来生成更加复杂的其他密码。那么可以想像,如果这个“初始密码”能够被猜到或者被伪造,那么整个加密体系的就脆弱了。理论上来说,由人主观想出来的密码都可以通过一定次数的尝试试验出来——因为你不总是喜欢用有规律的字符(123456、65431、1q2w3e4r5t之类)、生日等来生成邮箱密码么?
node里面的PBKDF2是根据HMAC算法来进行制定次数的迭代运算,将用户指定的初始密码进行演化,得到指定长度的新密码。Wifi里用到的WPA、WPA2和Mac文件系统的FileVault都是使用的该算法来生成可用的密码。
我们可以用node的API来模拟WPA2里面的密钥生成,回调中的key是binary格式:
var crypto = require("crypto"),
Buffer = require("buffer").Buffer;
var passphrase, salt;
passphrase = "my-wifi-passcode";
salt = "wifi-ssid";
crypto.pbkdf2(passphrase, salt, 4096, 256, function(err, key) {
//key is in binary
console.log("Encrypt wifi networkd data with key :", new Buffer(key, "binary").toString("hex"));
});
randomBytes
这个函数可以帮你生成伪随即数据,目前我知道的作用,大概是可以帮助自动化测试吧⋯⋯
node的文档里面有同步和异步方法的实例,这里不在赘述。








