一、文章概述在互联网时代,网络上的数据量每天都在以惊人的速度增长。与此同时,各种网络安全问题也层出不穷。在信息安全的重要性日益凸显的今天,作为开发者,更需要强化安全意识,通过技术手段提升服务的安全性。crypto模块是nodejs的核心模块之一,提供了安全相关的功能,如摘要计算、加密、电子签名等。面对长长的API列表,很多初学者不知如何上手,所以它涉及到很多安全领域的知识。本文重点讲解API背后的理论知识,主要包括以下内容:摘要(hash)、基于摘要的消息认证码(HMAC)对称加密、非对称加密、电子签名块加密模式本文摘自《Nodejs学习笔记》、更多章节及更新,请访问github主页地址。2.Digest(hash)摘要:以可变长度的消息作为输入,通过运行哈希函数生成固定长度的输出。此输出称为摘要。通常用于验证消息是否完整且未被篡改。摘要操作是不可逆的。也就是说,当输入固定时,输出也是固定的。但是,如果输出已知,输入就无法逆转。伪代码如下。digest=Hash(message)常用的摘要算法和对应的输出位数如下:MD5:128-bitSHA-1:160-bitSHA256:256-bitSHA512:512-bitnodejs中的例子:varcrypto=require('crypto');varmd5=crypto.createHash('md5');varmessage='hello';vardigest=md5.update(message,'utf8').digest('hex');console.log(digest);//输出结果如下:注意这里是16进制//5d41402abc4b2a76b9719d911017c592备注:在各种文章或文档中,abstract、hash、hash这三个词经常一起使用,导致很多初学者看的一头雾水.有时指的是同一个东西,只要记住上面summary的定义即可。3.MAC、HMAMAC(MessageAuthenticationCode):消息认证码,保证数据完整性。操作的结果取决于消息本身和密钥。MAC可以用许多不同的方式实现,例如HMAC。HMAC(Hash-basedMessageAuthenticationCode):可以粗略理解为一个带有秘钥的哈希函数。nodejs示例如下:constcrypto=require('crypto');//参数一:汇总函数//参数二:秘钥lethmac=crypto.createHmac('md5','123456');letret=hmac.update('hello').digest('hex');console.log(ret);//9c699d7af73a49247a239cb0dd2f81394.对称加密,非对称加密加解密:给定明文,通过一定算法,生成加密密文,这个过程叫做加密。反之就是解密。encryptedText=encrypt(plainText)plainText=decrypt(encryptedText)secretkey:为了进一步增强加解密算法的安全性,在加解密过程中引入了secretkey。密钥可以看作是加密/解密算法的一个参数。在已知密文的情况下,如果不知道用于解密的密钥,则无法解密密文。encryptedText=encrypt(plainText,encryptKey)plainText=decrypt(encryptedText,decryptKey)根据加解密密钥是否相同,加密算法可分为对称加密和非对称加密。1、对称加密加密和解密使用相同的密钥,即encryptKey===decryptKey。常见的对称加密算法:DES、3DES、AES、Blowfish、RC5、IDEA。加解密伪代码:encryptedText=encrypt(plainText,key);//加密plainText=decrypt(encryptedText,key);//解密2.非对称加密也称为公钥加密。加密和解密使用的密钥不同,即encryptKey!==decryptKey。加密密钥是公开的,称为公钥。解密密钥是保密的,称为秘密密钥。常见的非对称加密算法:RSA、DSA、ElGamal。加解密伪代码:encryptedText=encrypt(plainText,publicKey);//加密的明文=decrypt(encryptedText,privateKey);//解密3.比较与应用除了秘钥的不同,还有运算速度的不同。一般来说:对称加密比非对称加密快。非对称加密通常用于加密短文本,对称加密通常用于加密长文本。两者可以结合使用,比如HTTPS协议,在握手阶段可以通过RSA交换生成对称密钥。在后续的通信阶段,可以使用对称加密算法对数据进行加密,在握手阶段生成秘钥。备注:对称密钥交换不一定要通过RSA,也可以通过DH,这里不展开。5、数字签名从签名中,可以大致猜出数字签名的用途。主要功能如下:确认信息来自特定主体。确认信息完整且未被篡改。为了达到上述目的,需要两个过程:Sender:生成签名。接收方:验证签名。1.发送方对签名计算的原始信息生成摘要。使用私钥对摘要进行签名以获得电子签名。将电子签名的原始信息发送给接收方。附:签名伪码digest=hash(message);//计算摘要digitalSignature=sign(digest,privateKey);//计算数字签名2.接收方验证签名,用公钥对电子签名进行解密,得到摘要D1。(如果不能解决,信息源主体验证失败。)计算原始信息的摘要D2。比较D1和D2,如果D1等于D2,说明原始信息完整,没有被篡改。附:签名验证伪码digest1=verify(digitalSignature,publicKey);//获取摘要digest2=hash(message);//计算原始消息的摘要digest1===digest2//验证是否相等3.相对于非对称加密由于RSA算法的特殊性,加密/解密,签名/验证看起来很相似,很多同学很容易混淆。先记住下面的结论,以后有时间再详细介绍。加密/解密:公钥加密,私钥解密。签名/验证:私钥签名,公钥验证。6.块加密方式、填充和初始化向量常见的对称加密算法,如AES、DES,都采用块加密方式。其中,需要掌握三个关键概念:mode、padding、initializationvector。只有理解了这三点,我们才能知道crypto模块的对称加密API的参数是什么意思,如果出现问题应该如何排查。1、分块加密方式所谓分块加密就是将(较长的)明文拆分成固定长度的块,然后按照特定的方式对拆分后的块进行加密。常见的数据包加密方式有:ECB(不安全)、CBC(最常用)、CFB、OFB、CTR等。以最简单的ECB为例,先将报文拆分成相等的模块,然后用秘钥加密.图片来源:这里,更多关于块加密模式的介绍可以在wiki中找到。下面假设每个块的长度为128位2.初始化向量:IV为了增强算法的安全性,在一些块加密模式(CFB、OFB、CTR)来随机化加密结果。也就是说,对于同一份明文,IV不同,加密的结果也不同。以CBC为例,每个数据块与前一个加密块经过OR运算后进行加密。对于第一个数据块,它与IV进行或运算。IV的大小与数据块的大小(128位)有关,与秘钥的长度无关。如图,图片来源在这里3.Padding:padding块加密方式需要对固定长度的块进行加密。数据包拆分后,最后一个数据块的长度可能小于128位。这时候需要padding来满足长度要求。有多种填充方法。常用的填充方式是PKCS7。假设数据包长度为k字节,最后一个数据包长度为k-last,可以看出无论明文长度是多少,明文都会在加密前进行填充(否则解密函数无法区分最后一个数据包是否被填充,因为有一种情况是最后一个包的长度正好等于k)如果最后一个包的长度等于k-last===k,那么填充的内容就是一个完整的包kkk...k(kbytes)如果最后一个包的长度小于k-last
