当前位置: 首页 > 工具软件 > crypto-bar > 使用案例 >

nodejs之Crypto模块实现加密

羊舌承天
2023-12-01

参考:http://cnodejs.org/topic/56e22b279386fbf86ddd69ce

参考二:http://cnodejs.org/topic/504061d7fef591855112bab5

参考三:https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/001434501504929883d11d84a1541c6907eefd792c0da51000

加密知识:

SSL(SecureSocketLayer)是netscape公司提出的主要用于web的安全通信标准,.TLS(TransportLayerSecurity)是IETF的TLS工作组在SSL3.0基础之上提出的安全通信标准,SSL/TLS提供的安全机制可以保证应用层数据在互联网络传输不被监听,伪造和窜改。

在介绍 SSL/TLS 知识的之前,我们有必要了解下加密算法的知识:1、什么是加密算法加密算法很容易理解,就是把明文变成人家看不懂的东西,然后送给自己想要的送到的地方,接收方用配套的解密算法又把密文解开成明文,这样就不怕密文给人家截获而泄密。2、加密算法的种类大致分为2类,一种是基于key的,一种不是基于key的。不基于key的算法就是消息双方都通过一定的加密和解密算法来进行通信,这种算法缺点很明显如果加密算法被破解了就泄露了。3、基于key的加密算法key是一个什么东西呢?随便你,可以是一个随机产生的数字,或者一个单词,啥都行,只要你用的算法认为你选来做key的东西合法就行。所以基于key的加密算法又分为2类:对称加密和不对称加密。对称加密算法的原理很容易理解,通信一方用KEK加密明文,另一方收到之后用同样的KEY来解密就可以得到明文。4、不对称加密算法不对称加密指双方用不同的KEY加密和解密明文,通信双方都要有自己的公共密钥和私有密钥。举个例子比较容易理解,我们们假设通信双方分别是A,B. A,拥有KEY_A1,KEY_A2,其中KEY_A1是A的私有密钥,KEY_A2是A的公共密钥。 B,拥有KEY_B1,KEY_B2,其中KEY_B1是B的私有密钥,KEY_B2是B的公共密钥。公共密钥和私有密钥的特点是,经过其中任何一把加密过的明文,只能用另外一把才能够解开。也就是说经过KEY_A1加密过的明文,只有KEY_A2才能够解密,反之亦然。5、不对称加密算法通信过程:A-------->;KEY_A2------------>BA<--------KEY_B2<------------A这个过程叫做公共密钥交换,老外管这叫keyexchange。之后A和B就分别用对方的公共密钥解密,用自己的私有密钥加密。一般公共密钥是要发布出去的,这就是SSL使用的验证机制(注意不是数据传输机制)。常用的不对称加密一般有RSA,DSA,DH等。我们一般使用RSA。

关于SSL:一般情况下的网络协议应用中,数据在机器中经过简单的由上到下的几次包装,就进入网络,如果这些包被截获的话,那么可以很容易的根据网络协议得到里面的数据.由网络监听工具可以很容易的做到这一点。

SSL就是为了加密这些数据而产生的协议,可以这么理解,它是位与应用层和 TCP/IP之间的一层,数据经过它流出的时候被加密,再往TCP/IP送,而数据从TCP/IP流入之后先进入它这一层被解密,同时它也能够验证网络连接两端的身份(根据我们之前学习的不对称加密算法只是可知)。

SSL协议包含2个子协议,一个是包协议,一个是握手协议。包协议位于握手协议更下一层,我们暂时对包协议的内容没有兴趣。SSL握手过程说简单点就是:通信双方通过不对称加密算法来协商好一个对称加密算法以及使用的key,然后用这个算法加密以后所有的数据完成应用层协议的数据交换。

SSL通信流程:握手一般都是由client发起的,SSL也不例外。1、client送给server它自己本身使用的ssl的version(ssl一共有三个version),加密算法的一些配置,和一些随机产生的数据,以及其他在SSL协议中需要用到的信息。2、server送给client它自己的SSL的version,加密算法的配置,随机产生的数据,还会用自己的私有密钥加密SERVER-HELLO信息。Server还同时把自己的证书文件给送过去。同时有个可选的项目,就是server可以要求需要客户的certificate。3、client就用server送过来的certificate来验证server的身份。如果server身份验证没通过,本次通信结束。通过证书验证之后,得到server的公共密钥,解开server送来的被其用私有密钥加密过的SERVER-HELLO信息,看看对头与否。如果不对,说明对方只有该server的公共密钥而没有私有密钥,必是假的。通信告吹。4、client使用到目前为止所有产生了的随机数据(sharedsecret),client产生本次握手中的premastersecret(这个步骤是有可能有server的参与的,由他们使用的加密算法决定),并且把这个用server的公共密钥加密,送回给server.如果server要求需要验证client,那么client也需要自己把自己的证书送过去,同时送一些自己签过名的数据过去。RSA就是我们上一章说过的一种不对称加密算法。首先server把自己的RSA公共密钥送给client,client于是用这个key加密一个随机产生的值(这个随机产生的值就是sharedsecret),再把结果送给server.5、Server验证完client的身份之后,然后用自己的私有密钥解密得到premastersecret然后双方利用这个premastersecret来共同协商,得到mastersecret.6、双方用master一起产生真正的sessionkey,着就是他们在剩下的过程中的对称加密的key了。这个key还可以用来验证数据完整性。双方再交换结束信息。握手结束。

回过头来我们看openssl,openssl就是实现ssl的一个软件,下面我就讨论刚才的命令,生成一个私有密钥:openssl genrsa -des3 -out server.key 1024genras表示生成RSA私有密钥文件,-des3表示用DES3加密该文件,1024是我们的key的长度。一般用512就可以了,784可用于商业行为了,1024可以用于军事用途了。生成server.key的时候会要你输入一个密码,这个密钥用来保护你的server.key文件,这样即使人家偷走你的server.key文件,也打不开,拿不到你的私有密钥。

node利用 OpenSSL库来实现它的加密技术,这是因为OpenSSL已经是一个广泛被采用的加密算法。它包括了类似MD5 or SHA-1 算法;Crypto模块提供了一种封装安全凭证的方式,用于HTTPS网络或HTTP连接,也对OpenSSL的Hash,HMAC,加密,解密、签名和验证方法进行了封装;

公开密钥加密包括4个类,Cipher, Decipher,Sign, and Verify,即加密,解密,签名,验证。

md5、sha1、sha256、sha512、ripemd160这些可以通过 crypto.createHash() 来创建一个Hash实例,MD5是最常用的,但是他有一定的碰撞的问题;

1.  通过Crypto模块,简单加密生成一个哈希值:
var hash = crypto.createHash('sha256').update(data).digest()
这个语句拆开来看,就是crypto.createHash('sha256')先用sha256算法创建一个Hash实例;接着使用.update(data)接受明文data数据,最后调用.digest()方法,获得加密字符串,即密文。
然后,使用
Ed25519组件,简单直接地生成对应密钥对:

var keypair = ed.MakeKeypair(hash);

var crypto = require('crypto');
    var md5 = crypto.createHash(‘md5’);
    md5.update(‘foo’);//接受明文data数据
    md5.digest();//返回加密的密文,默认返回的是2进制的数据,
    md5.digest(‘hex’); //返回加密的密文,以16进制的形式打印
  hash1.update()//方法有记忆功能,下面的两个结果是一样的:也就是说hash.update()方法就是将字符串相加,然后在hash.digest()将字符串加密返回

     var sha1 = crypto.createHash('sha1');
    sha1.update('foo');
  sha1.update('bar');
  sha1.digest('hex');
    //结果'8843d7f92416211de9ebb963ff4ce28125932878'
    
    var sha1 = crypto.createHash('sha1');
  sha1.update('foobar');
 sha1.digest('hex');
    //结果'8843d7f92416211de9ebb963ff4ce28125932878'

2、HMACHMAC名是 keyed-Hash Message Authentication Code,中文直译就是密钥相关的哈希运算消息认证码,HMAC运算利用哈希算法,以一个密钥和一个消息为输入,生成一个加密串作为输出。HMAC可以有效防止一些类似md5的彩虹表等攻击,比如一些常见的密码直接MD5存入数据库的,可能被反向破解。crypto.createHmac(algorithm, key)这个方法返回和createHash一样,返回一个HMAC的实例,有update和digest方法。我们来看下实际的应用:

 var crypto = require('crypto');
 var fs = require('fs');
var pem = fs.readFileSync('key.pem');//从key.pem文件中读取数据;//利用openssl genrsa  -out XX.pem 1024 来生成key.pem;(在命令行生成,1024是文件长度);命令行vi XX.pem可以打开生成的XX.pem文件;var key = pem.toString('ascii');//转成ascii码
 var hmac = crypto.createHmac('sha1', key);//返回一个hmac实例、 hmac.update('foo');//添加铭文hmac.digest('hex');//返回的密文
//结果:'7b058f2f33ca28da3ff3c6506c978825718c7d42'

我们先通过 fs.readFileSync 方法读取了key.pem密钥,然后将它转为ascii码,最后通过 createHmac(‘sha1’, key) 方法获得HMAC实例,然后执行update和digest,生成一串密钥字符串。由于key的不同,所以同样的字符串’foo’经过hmac加密后生成的16进制字符串也是不同的,从而更加保障了数据的安全性。

========常用加密====

  /**
     * @加密模块
     * @md5可以被彩虹吧破解,这里就不用啦
     * @author lwt
     * */
    //导入模块
    var crypto = require('crypto');
    /**
     * @aes192加密模块
     * @param str string 要加密的字符串
     * @param secret string 要使用的加密密钥(要记住,不然就解不了密啦)
     * @retrun string 加密后的字符串
     * */
    exports.getEncAse192 = function(str, secret) {
        var cipher = crypto.createCipher("aes192", secret); //设置加密类型 和 要使用的加密密钥
        var enc = cipher.update(str, "utf8", "hex");    //编码方式从utf-8转为hex;
        enc += cipher.final("hex"); //编码方式从转为hex;
        return enc; //返回加密后的字符串
    }
    /**
     * @aes192解密模块
     * @param str string 要解密的字符串
     * @param secret string 要使用的解密密钥(要和密码的加密密钥对应,不然就解不了密啦)
     * @retrun string 解密后的字符串
     * */
    exports.getDecAse192 = function(str, secret) {
        var decipher = crypto.createDecipher("aes192", secret);
        var dec = decipher.update(str, "hex", "utf8");//编码方式从hex转为utf-8;
        dec += decipher.final("utf8");//编码方式从utf-8;
        return dec;
    }
    /**
     * @Hmac-sha1加密模块 (每次加密随机,不可逆)
     * @param str string 要加密的字符串
     * @param secret string 要使用的加密密钥
     * @retrun string 加密后的字符串
     * */
    exports.getHmac = function(str, secret) {
        var buf = crypto.randomBytes(16);
        secret = buf.toString("hex");//密钥加密;
        var Signture = crypto.createHmac("sha1", secret);//定义加密方式
        Signture.update(str);
        var miwen=Signture.digest().toString("base64");//生成的密文后将再次作为明文再通过pbkdf2算法迭代加密;
        return miwen;
    }
    /**
     * @sha1加密模块 (加密固定,不可逆)
     * @param str string 要加密的字符串
     * @retrun string 加密后的字符串
     * */
    exports.getSha1 = function(str) {
        var sha1 = crypto.createHash("sha1");//定义加密方式:md5不可逆,此处的md5可以换成任意hash加密的方法名称;
        sha1.update(str);
        var res = sha1.digest("hex");  //加密后的值d
        return res;
    }

 类似资料: