crypto 简单了解

阅读前:文章记录crypto库的简单了解,和一些简单的用法,与具体加解密算法的实现无关。

文中例子使用到了node的crypto模块 和  npm sjcl(Stanford Javascript Crypto Library) 包。 

文章概要:

  1. crypto
  2. Hash(散列)算法
  3. Hmac算法
  4. PBKDF2函数
  5. 对称加密 AES
  6. 小结

 1. crypto

Crypto++ 库是一个用c++ 编写的密码类库,提供完整的加密实现,并且通常包括不太流行,不常使用的方案。(简单说:包括了加解密算法的库)

AES和AES候选(AES and AES candidates):Rijndael (AES selection), RC6, MARS, Twofish, Serpent, CAST-256
分组密码操作模式(Block cipher modes of operation): ECB, CBC, CTS, CFB, OFB, CTR
分组密码填充方案(Block ciphers padding schemes): PKCS#5, PKCS#7, Zeros, One and zeros, W3C Padding
基于密码的密钥派生函数(Password based key derivation functions):PBKDF1 and PBKDF2 from PKCS #5, PBKDF from PKCS #12 appendix B, Krawczyk and Eronen's HKDF

......

后台:文中使用的是node,node 中有cypto这个模块,提供加密功能。

前端:文中使用的是sjcl库,sjcl (Stanford Javascript Crypto Library)。

 2.Hash(散列)算法

散列算法也叫哈希算法,用来把任意长度的输入变换成固定长度的输出。常见的有md5,sha1等。

const crypto = require('crypto');

const hash = crypto.createHash('md5');

// 可任意多次调用update():
// 指定要摘要的原始内容,可以在摘要被输出之前使用多次update方法来添加摘要内容
hash.update('Hello, world!');
hash.update('Hello, nodejs!');

console.log(hash.digest('hex')); 

eg. 一种应用:将压缩包文件计算出MD5值,当客户端下载完压缩包也计算出MD5,然后比对,文件是否下载完毕。

 3. Hmac算法

 HMAC算法将散列算法与一个密钥结合在一起,以阻止对签名完整性的破坏,密钥发生了变化,输出结果也会发生变化.(Hmac可以理解为用随机数“增强”的哈希算法)

let hmac = crypto.createHmac(algorithm,key);
hmac.update(data);
console.log(hmac.digest('hex'));

// algorithm 是一个可用的摘要算法,例如 sha1、md5、sha256
// key为一个字符串,用于指定一个PEM格式的密钥
const crypto = require('crypto');

const hmac = crypto.createHmac('sha256', key);

hmac.update('Hello, world!');
hmac.update('Hello, nodejs!');

console.log(hmac.digest('hex'));

 

 4.PBKDF2函数

 PBKDF2:是一个用来导出密钥的函数,常用于生成加密的密码

DK = PBKDF2(PRF, Password, Salt, c, dkLen)
PRF:一个伪随机函数,例如HASH_HMAC函数,它会输出长度为hLen的结果。
Password:是用来生成密钥的原文密码。
Salt:一个加密用的盐值。
c:重复计算的次数。
dkLen:期望得到的密钥的长度。
DK:最后产生的密钥。
基本原理:通过一个伪随机函数(例如HMAC函数),把明文和一个盐值作为输入参数,然后重复进行运算,并最终产生密钥。
var sjcl = require('sjcl.js');
// 密码,盐值,迭代次数,期待秘钥长度,伪随机函数
sjcl.misc.pbkdf2(pwd, salt, iteration, 256, hmacSHA256)

 5.对称加密 AES

 AES是一种常用的对称加密算法,加解密都用同一个密钥

分组密码又称为秘密钥密码或对称密码。利用分组密码对明文进行加密时,首先需要对明文进行分组,每组的长度都相同,然后对每组明文分别加密得到等长的密文,分组密码的特点是加密密钥与解密密钥相同。 分组密码的安全性应该主要依赖于密钥,而不依赖于对加密算法和解密算法的保密。因此,分组密码的加密和解密算法可以公开。

重点:分组密码的安全性应该主要依赖于密钥

后端node crypto 模块

// data:需要加解密的内容,
// 密钥
// 初始化向量(iv)

function aesEncrypt(data, key, iv) {
  var ivBuffer = new Buffer(iv, 'hex');
  // 给定的算法,密钥和初始化向量(iv)创建并返回Cipher对象
  const cipher = crypto.createCipher('aes-256-cbc', key, ivBuffer);
  // 用数据更新cipherData
  var crypted = cipher.update(data, 'utf8', 'hex');
  crypted += cipher.final('hex');
  return crypted;
}

function aesDecrypt(data, key, iv) {
  var ivBuffer = new Buffer(iv, 'hex');
  // 给定的算法,密钥和初始化向量(iv)解密数据
  const decipher = crypto.createDecipher('aes-256-cbc', key, ivBuffer);
  // 用数据更新decrypted
  var decrypted = decipher.update(data, 'hex', 'utf8');
  decrypted += decipher.final('utf8');
  return decrypted;
}

前端:sjcl库

// str:需要加解密的内容,
// 密钥
// 初始化向量(iv)
// 返回数据格式
export function encrypt(str, key, iv, sourceEncode = 'utf8String') {
 var aes = new sjcl.cipher.aes(sjcl.codec.hex.toBits(key));
 if (sourceEncode) {
   str = sjcl.codec[sourceEncode].toBits(str);
 }
 var encrypted = sjcl.mode['cbc'].encrypt(aes, str, sjcl.codec.hex.toBits(iv));
 return sjcl.codec.base64.fromBits(encrypted);
}
export function decrypt(str, key, iv, sourceEncode = 'base64') {
 var aes = new sjcl.cipher.aes(sjcl.codec.hex.toBits(key));
 if (sourceEncode) {
  str = sjcl.codec[sourceEncode].toBits(str);
 }
 var decrypted = sjcl.mode['cbc'].decrypt(aes,str, sjcl.codec.hex.toBits(iv));
 return sjcl.codec.utf8String.fromBits(decrypted);
}

前后端的算法加解密算法一致(例子中使用的aes-256-cbc),数据可以加密传输了,怎么产生密钥就是需要思考的问题。

 

 6.小结

文中例子比较粗糙,理解不准确之处,还请教正。

关于加解密crypto库还常用的有,非对称加密算法,以及签名。然后在实际项目中我并没有使用过 还需理解,有时间还会补上,修正本篇。

你可能感兴趣的:(crypto 简单了解)