NodeJs
加解密工具 const crypto=require(“crypto”)浅谈nodejs中的Crypto模块 [转载]加密算法库Crypto——nodejs中间件系列
哈希&散列 1 2 3 4 5 6 const crypto=require ("crypto" );var md5 = crypto.createHash ('md5' );md5.update ('foo' ); md5.digest (); md5.digest ('hex' );
一旦md5.digest();这个方法被调用了,hash 对象就被清空了是不能被重用的。
1 2 3 4 5 6 7 var sha1 = crypto.createHash ('sha1' );sha1.update ('foo' ); sha1.update ('bar' ); sha1.digest ('hex' ); var sha1 = crypto.createHash ('sha1' );sha1.update ('foobar' ); sha1.digest ('hex' )
这2次sha1加密结果是一样的,也就是说hash.update()方法就是将字符串相加,然后在hash.digest()将字符串加密返回
HMAC HMAC全名是 keyed-Hash Message Authentication Code ,中文直译就是密钥相关的哈希运算消息认证码,HMAC运算利用哈希算法,以一个密钥和一个消息为输入,生成一个加密串作为输出。 HMAC可以有效防止一些类似md5的彩虹表等攻击,比如一些常见的密码直接MD5存入数据库的,可能被反向破解。 crypto.createHmac(algorithm, key) 这个方法返回和createHash一样,返回一个HMAC的实例,有update和digest方法。
1 2 3 4 5 6 7 8 9 10 11 12 var crypto = require ('crypto' );var fs = require ('fs' );var pem = fs.readFileSync ('key.pem' );var key = pem.toString ('ascii' );var hmac = crypto.createHmac ('sha1' , key);hmac.update ('foo' ); {} hmac.digest ('hex' ); '7b058f2f33ca28da3ff3c6506c978825718c7d42'
先通过 fs.readFileSync 方法读取了key.pem密钥,然后将它转为ascii码,最后通过 createHmac(‘sha1’, key) 方法获得HMAC实例,然后执行update和digest,生成一串密钥字符串。 由于key的不同,所以同样的字符串’foo’经过hmac加密后生成的16进制字符串也是不同的,从而更加保障了数据的安全性。 key.pem: 利用opensll命令来创建一个key.pem
1 2 # openssl genrsa -out server.pem 1024 <!-- Generating RSA private key, 1024 bit long modulus -->
加解密算法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 var crypto = require ('crypto' );var fs = require ('fs' );var pem = fs.readFileSync ('key.pem' );var key = pem.toString ('ascii' );var cipher = crypto.createCipher ('blowfish' , key);cipher.update (new Buffer (4 ), 'binary' , 'hex' ); ” cipher.update (new Buffer (4 ), 'binary' , 'hex' ); 'ff57e5f742689c85' cipher.update (new Buffer (4 ), 'binary' , 'hex' ); ” cipher.final ('hex' ) '96576b47fe130547'
读取之前的key,然后利用 blowfish 加密算法生成 cipher 实例,接着update内容到cipher实例,最后通过cipher.final()方法输出加密串。 其中有几个方法我们要看下api的解释
1 2 3 4 5 6 7 crypto.createCipher (algorithm, password) crypto.createCipheriv (algorithm, key, iv) `` ` 上面这2个方法都返回cipher实例,第一个参数 algorithm 表示用何种加密算法,可以利用 openssl list-cipher-algorithms 命令来查看你的系统支持哪些加密算法。password和key, iv表示密钥,即利用何种密钥加密,password是用来派生key和iv的,key的话是算法原生的key,iv表示初始化向量。 ` `` jscipher.update (data, [input_encoding], [output_encoding])
往cipher实例中添加数据,第一个参数是填充的数据,第二个参数表示传入数据的格式,可以是’utf8’, ‘ascii’ 或 ‘binary’,默认是 ‘binary’。第三个参数是返回block的数据格式。 注意:这里我们update了 new Buffer(4),表示通过随机内存中的4byte字节的内容填充进去。为什么第一次update没有block返回呢? 因为4byte不够生成一个block,所以这点我们要注意下。 最后我们通过final方法和之前digest方法一样,生成加密过后的串。
1 decipher.setAutoPadding (auto_padding=true )
如果这些加密块不是使用标准的填充块的话,你可以把自动填充关闭。 这么做是为了防止执行 decipher.final()的时候监察和去除标准填充块,从而可能出错,一般这个方法不会去用。必须在执行update之前执行它。demo
1 2 3 4 5 6 7 8 var crypto = require ('crypto' );var cipher = crypto.createCipher ('aes-256-cbc' ,'InmbuvP6Z8' )var text = "123|123123123123123" ;var crypted = cipher.update (text,'utf8' ,'hex' )crypted += cipher.final ('hex' ) var decipher = crypto.createDecipher ('aes-256-cbc' ,'InmbuvP6Z8' )var dec = decipher.update (crypted,'hex' ,'utf8' )dec += decipher.final ('utf8' )
ok。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 var crypto = require ('crypto' );var fs = require ('fs' );var pem = fs.readFileSync ('key.pem' );var key = pem.toString ('ascii' );var plaintext = Buffer .from ('abcdefghijklmnopqrstuv' );var encrypted = “”;var cipher = crypto.createCipher ('blowfish' , key);.. encrypted += cipher.update (plaintext, 'binary' , 'hex' ); encrypted += cipher.final ('hex' ); var decrypted = “”;var decipher = crypto.createDecipher ('blowfish' , key);decrypted += decipher.update (encrypted, 'hex' , 'binary' ); decrypted += decipher.final ('binary' ); var output = new Buffer (decrypted);output plaintext
最后我们看下签名和验证 Class: Signer 和 Class: Verify
先通过openssl命令生成公钥:
1 # openssl req -key server.pem -new -x509 -out cert.pem
还记得我们之前说的不对称加密算法么,这里我们就利用私钥和公钥来做个简单的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 var crypto = require ('crypto' );var fs = require ('fs' );var privatePem = fs.readFileSync ('server.pem' );var publicPem = fs.readFileSync ('cert.pem' );var key = privatePem.toString ();var pubkey = publicPem.toString ();var data = “abcdef”var sign = crypto.createSign ('RSA-SHA256' );sign.update (data); {} var sig = sign.sign (key, 'hex' );var verify = crypto.createVerify ('RSA-SHA256' );verify.update (data); {} verify.update (data); {} verify.verify (pubkey, sig, 'hex' ); 1
首先通过,crypto.createVerify(algorithm)和crypto.createSign(algorithm)方法生成实例,然后利用update方法更新数据,最后利用key(私钥)生成签名,同样的验证也是如此,最后通过 verify.verify(pubkey, sig, ‘hex’); 函数签名。