node.js_crypto pbkdf2算法加密

1,766 阅读3分钟

一、知识点分析

1.crypto 模块提供了加密功能,实现了包括对openSSl的哈希、HMAC、加密、解密、签名、以及验证功能的一整套封装
2.crypto模块的目的是为了提供通用的加密和哈希算法,用纯javascript代码实现这些功能不是不可能,但速度会非常慢,node.js用C/C++实现这些算法后,通过cypto这个模块暴露为javascript接口,这样用起来也方便,运行速度也快

二、PBKDF2加密

①关于PBKDF2加密解释

PBKDF2通过哈希算法进行加密,由于哈希算法是单向的,能够将不论大小的数据转化为定长的“指纹”,并且无法被反向计算。另外,即使数据源仅仅修改了一点点,哈希的结果也会全然不同。
这种特性是的他很适合用于保存password。由于我们需要加密后的password无法被破解,同时也能保证正确校验每一个用户的password。可是哈希加密能够通过字典攻击和暴力攻击破解。 password加盐。盐是一个加入到用户的password哈希过程中的一段随机序列。这个机制可以防止通过预先计算结果的彩虹表破解。每一个用户都有自己的盐,这种结果就是即使用户的password一样,通过加盐后哈希值也将不同。为了校验password是否正确,我们需要存储盐值,通常和password哈希值一起存放在账户数据库中,或者直接存为哈希字符串的一部分。

②使用
1)方法一,使用cropty加密

文档地址:nodejs.cn/api/crypto.…

PBKDF2 是 Node.js 的 crypto 模块原生支持的标准方法。
1.引入crypto模块(已经存在node,直接引入crypto模块)
引入方式1: import cropty from "cropty"
引入方式2: const crypto = require('crypto');
2.使用
1.crypto-生成随机盐值-提供异步基于密码的密钥派生函数 2 (PBKDF2) 实现: 应用由 digest 指定的选定 HMAC 摘要算法以从 passwordsalt 和 iterations 导出请求字节长度 (keylen) 的密钥。
参数简介:

  • password: 需要加密的密码
  • salt:  盐值,应该尽可能唯一,建议盐值随机,长度至少为16字节。--crypto.randomBytes()
  • iterations: 迭代次数,必须是数字格式,迭代次数越多,派生密钥就越安全,但需要时间也会更长
  • keylen: 导出请求字节长度的密钥
  • digest:digest 是 null,则将使用 'sha1'。 此行为已弃用,请显式指定 digest,值一个哈希函数,eg:'MD5'、'sha1'、'sha256'、'sha512'
  • callback: 它是一个具有两个参数的函数,即err和DerivedKey。如果在派生密钥时发生错误,则设置 err;否则 err 将是 null。 默认情况下,成功生成的 derivedKey 将作为 Buffer 传给回调。 如果任何输入参数指定了无效的值或类型,则会抛出错误。
function pbkdf2_encrypt(username, password) {
  // crypto.randomBytes()方法生成 32 字节的随机数 - 这里作为盐值
  crypto.randomBytes(32, (err, salt) => {
    if (err) throw err;
    // 参数列表:(密码(password),盐值(salt),迭代次数(iterations),生成密钥长度(keylen),摘要函数(digest))
    crypto.pbkdf2(password, salt, 4096, 512, 'sha256', (err, key) => {
      if (err) throw err;
      // 将用户名、密码哈希值和盐值存入数据库
      console.log(username, key.toString('hex'), salt.toString('hex'));
    });
  });
}

pbkdf2_encrypt('zhangSan', '123456');

2.crypto-生成随机盐值-提供同步基于密码的密钥派生函数 2 (PBKDF2) 实现

function pbkdf2_encrypt(username, password) {
   const salt = crypto.randomBytes(32);//方法生成 32 字节的随机数 - 这里作为盐值
   const result = crypto.pbkdf2Sync(password, salt, iterations, keylen, 'sha256');
   return keyvalue.toString('hex') //字符串加密成hex字符串
}

2)方法二:使用croptyjs加密

// 官方示例
 var str = '123456';                                                      
 var salt = CryptoJS.lib.WordArray.random(128/8);   //随机产生盐值  
 var saltTwo =parseInt(salt,16).toString(16)
 var key128Bits = CryptoJS.PBKDF2(str, saltTwo, { keySize: 128/32 });          
 var key256Bits = CryptoJS.PBKDF2(str, saltTwo, { keySize: 256/32 }); 
 var key512Bits = CryptoJS.PBKDF2(str, saltTwo, { keySize: 512/32 });
 var key512Bits1000Iterations = CryptoJS.PBKDF2("Secret Passphrase", saltTwo, {
     keySize: 512/32,                                                          
     iterations: 1000                                                        
});
var key256Bits1000Iterations = CryptoJS.PBKDF2(word, salt, {
  keySize: 256/32,
  iterations: 10000,
  hasher: CryptoJS.algo.SHA256
});
return key256Bits1000Iterations.toString(CryptoJS.enc.Hex);