NodeJS中的Crypto应用

在爬虫JS解密的时候常常会遇到常见的加密,例如:MD5,Sha1,Sha256,AES,RSA等加密算法,这些能够在Python中调用,当然有时候采纳NodeJS调用也很不便,相熟NodeJS常见的加密算法对逆向JS很有帮忙。NodeJS 中的 Crypto 模块提供了加密性能,包含对 OpenSSL 的哈希、HMAC、加密、解密、签名、以及验证性能的一整套封装。

Hash

将任意长度的二进制值串映射为固定长度的二进制值串,这个映射的规定就是哈希算法,而通过原始数据映射之后失去的二进制值串就是哈希值(散列值).一个优良的哈希算法须要满足:

  • 从哈希值不能反向推导出原始数据(所以哈希算法也叫单向哈希算法);
  • 对输出数据十分敏感,哪怕原始数据只批改了一个 Bit,最初失去的哈希值也大不相同;
  • 散列抵触的概率要很小,对于不同的原始数据,哈希值雷同的概率十分小;
  • 哈希算法的执行效率要尽量高效,针对较长的文本,也能疾速地计算出哈希值。

哈希算法严格来说并不属于加密算法,传统意义上的 加密 是与 解密 相配对的。哈希算法只能加密不能反向解密。

MD5

在NodeJS中 MD5 Hash 函数的用法如下:

const crypto = require('crypto');const hash = crypto.createHash('md5');console.log(hash.update('666666').digest('hex'))// f379eaf3c831b04de153469d1bec345econst hash2 = crypto.Hash('md5');console.log(hash2.update('666666').digest('hex'))// f379eaf3c831b04de153469d1bec345e

其中摘要的编码方式有如下三种:

  • latin1
  • hex
  • base64

Sha1

const crypto = require('crypto');const hash = crypto.createHash('sha1');console.log(hash.update('666666').digest('hex'))// 1411678a0b9e25ee2f7c8b2f7ac92b6a74b3f9c5const hash2 = crypto.Hash('sha1');console.log(hash2.update('666666').digest('hex'))// 1411678a0b9e25ee2f7c8b2f7ac92b6a74b3f9c5

Base64

百度百科中对Base64有一个很好的解释:“Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来示意二进制数据的办法”。
什么是“可打印字符”呢?为什么要用它来传输8Bit字节码呢?在答复这两个问题之前咱们有必要来思考一下什么状况下须要应用到Base64?Base64个别用于在HTTP协定下传输二进制数据,因为HTTP协定是文本协定,所以在HTTP协定下传输二进制数据须要将二进制数据转换为字符数据。然而间接转换是不行的。因为网络传输只能传输可打印字符。什么是可打印字符?在ASCII码中规定,0~31、127这33个字符属于控制字符,32~126这95个字符属于可打印字符,也就是说网络传输只能传输这95个字符,不在这个范畴内的字符无奈传输。那么该怎么能力传输其余字符呢?其中一种形式就是应用Base64。

Base64,就是应用64个可打印字符来示意二进制数据的办法。Base64的索引与对应字符的关系如下表所示:

更加具体的解释能够参考:什么是Base64?

严格来说Base64也不是加密算法,然而爬虫中也会常常遇到,所以在此给出在NodeJS中的Base64的"加密"与"解密"。在浏览器中加密与解密别离对应 btoaatob

Base64加密

对应浏览器中的 btoa

const data = '666666';const encodedData = Buffer.from(data, 'utf-8').toString('base64'); // 输出编码为utf8,输入为base64console.log(encodedData);// NjY2NjY2

Base64解密

对应浏览器中的 atob

const data = 'NjY2NjY2';const decodedData = Buffer.from(data, 'base64').toString('utf8'); // 输出编码为base64,输入编码为utf8console.log(decodedData);// 666666

DES

DES 是 Data Encryption Standard(数据加密规范)的缩写。它是由IBM公司研制的一种对称明码算法,美国国家标准局于1977年颁布把它作为非机要部门应用的数据加密规范,它始终沉闷在国内窃密通信的舞台上,表演了非常重要的角色。

DES是一个分组加密算法,典型的DES以64位为分组对数据加密,加密和解密用的是同一个算法。它的密钥长度是56位(因为每个第8 位都用作奇偶校验),密钥能够是任意的56位的数,而且能够任意时候扭转。其中有极少数被认为是易破解的弱密钥,然而很容易避开它们不必。所以保密性依赖于密钥。

DES加解密

const crypto = require('crypto');const cipher = crypto.createCipheriv('des-cbc', '01234567', '01234567')var crypted = cipher.update('666666', 'utf8', 'base64');crypted += cipher.final('base64');console.log(crypted); // 83OX84xg+iM=

DES解密

const crypto = require('crypto');const cipher = crypto.createDecipheriv('des-cbc', '01234567', '01234567')var crypted = cipher.update('83OX84xg+iM=', 'base64', 'utf8');crypted += cipher.final('utf8');console.log(crypted); // 666666

AES

高级加密规范(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的)。对称加密算法也就是加密和解密用雷同的密钥,具体的加密流程如下图:

AES加密

const crypto = require('crypto');const cipher = crypto.createCipheriv('aes128', '0123456789abcdef', '0123456789abcdef')var crypted = cipher.update('666666', 'utf8', 'hex');crypted += cipher.final('hex');console.log(crypted); // c319a2c27be50284fec9fc95d7045737

阐明:

createCipheriv原型如下:

crypto.createCipheriv(algorithm,key,iv [,options])

  1. iv是初始化向量,能够 为空 或者 16 字节的字符串
  2. key是加密密钥,依据选用的算法不同,密钥长度也不同,对应关系如下:

    1. aes128对应16位长度密钥
    2. aes192对应24位长度秘钥
    3. aes256对应32位长度密钥

AES解密

const crypto = require('crypto');const cipher = crypto.createDecipheriv('aes128', '0123456789abcdef', '0123456789abcdef')var data = cipher.update('c319a2c27be50284fec9fc95d7045737', 'hex', 'utf8'); // 输出数据编码为hex(16进制),输入为utf8data += cipher.final('utf8');console.log(data); // 666666

RSA

RSA公开密钥明码体制是一种应用不同的加密密钥与解密密钥,也就是在计算上由已知加密密钥推导出解密密钥是不可行的 。
在公开密钥明码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即机密密钥)SK是须要窃密的。加密算法E和解密算法D也都是公开的。尽管解密密钥SK是由公开密钥PK决定的,但却不能依据PK计算出SK。
正是基于这种实践,1978年呈现了驰名的RSA算法,它通常是学生成一对RSA密钥,其中之一是窃密密钥,由用户保留;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为进步窃密强度,RSA密钥至多为500位长,个别举荐应用1024位。这就使加密的计算量很大。为缩小计算量,在传送信息时,常采纳传统加密办法与公开密钥加密办法相结合的形式,即信息采纳改良的DES或IDEA对话密钥加密,而后应用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核查信息摘要。

RSA加解密

const crypto = require('crypto');const {privateKey, publicKey} = crypto.generateKeyPairSync('rsa', {    modulusLength: 2048,});const encodedData = crypto.privateEncrypt(privateKey, Buffer.from('666666','utf8')); // 传入utf8编码的数据console.log(encodedData.toString('hex'));const rawData = crypto.publicDecrypt(publicKey, Buffer.from(encodedData, 'hex')); // 传入hex(16进制)数据console.log(rawData.toString('utf8'));

总结

常见的加密计划采纳Python模块或者NodeJS自带的Crypto模块就能够解决,然而在工作中还是举荐先扣JS加密代码,如果难度比拟大,或者须要耗时,那么就能够采纳Python或者NodeJS来模仿加密计划。在局部网站中还会有本人创建的算法,这种个别不倡议用Python或者NodeJS模仿实现,还是间接扣JS代码来的不便。