如果觉得文章不错,欢迎关注、点赞和分享!
持续分享技术博文,关注微信公众号 👉🏻 前端LeBron
互联网时代,网络上的数据量每天都在以惊人的速度增长。同时,各类网络安全问题层出不穷。在信息安全重要性日益凸显的今天,作为一名开发者,需要加强对安全的认识,并通过技术手段增强服务的安全性。crypto模块的目的是为了提供通用的加密和哈希算法。用纯JavaScript代码实现这些功能不是不可能,但速度会非常慢。Nodejs用C/C++实现这些算法后,通过cypto这个模块暴露为JavaScript接口,这样用起来方便,运行速度也快。
编码方式
为什么信息传输需要编码?
在开发加密解密数据的时候碰到需要把加密好的字节数组转换成 String 对象用于网络传输的需求,如果把字节数组直接转换成 UTF-8 等编码方式的话肯定会存在某些编码没有对应的字符(8bit只能表示128个字符),在编码和解析过程中会出错,不能正确地表达信息。这时就可以通过常用的二进制数据编码方式 Base64 编码或者 Hex 编码来实现。
hex编码
- 编码原理
将一个8位的字节数据用两个16进制数表示出来
- 将8位二进制码重新分组成两个4位的字节
- 其中一个字节的低4位是原字节的高4位,另一个字节的低4位是原数据的低4位
- 高4位都补0,然后输出这两个字节对应的十六进制数字作为编码
- 例子
ASCII码:A(65)
二进制码:0100 0001
重新分组: 00000100 00000001
十六进制: 4 1
Hex编码:41
就算原文件是纯英文内容,编码后内容也和原文完全不一样,普通人难以阅读但由于只有16个字符,听说一些程序员大牛能够记下他们的映射关系,从而达到读hex编码和读原文一样的效果。另外,数据在经过hex编码后,空间占用变成了原来的2倍。
base64编码
- 编码原理
Base64编码是通过64个字符来表示二进制数据,64个字符表示二进制数据只能表示6位,所以它可以通过4个 Base64字符来表示3个字节,如下是Base64的字符编码表
- 举个Base64编码的例子,图就很浅显易懂了
- 字符串长度不是3的倍数时补0,也就是“=”
由64个字符组成,比hex编码更难阅读,但由于每3个字节会被编码为4个字符。
所以,空间占用会是原来的4/3,比hex要节省空间。另外要注意的是,虽然Base64编码后的数据难以阅读,但不能将其作为加密算法使用,因为它解码都不需要你提供密钥啊
urlencode编码
- 编码原理
urlencode编码,看名字就就知道是设计给url编码的对于a-z
,A-Z
,0-9
,.
,-
和_
,urlencode都不会做任何处理原样输出,而其它字节会被编码为%xx
(16进制)的形式,其中xx
就是这个字节对应的hex编码。 由于英文字符原样保留,对于以英文为主的内容,可读性最好,空间占用几乎不变,而对于非英文内容,每个字节会被编码为%xx的3个字符,空间占用是原来的3倍,所以urlencode是一个对英文友好的编码方案。
Hash
摘要:将不固定长度的消息作为输入Hash函数,生成固定长度的输出,这段输出称之为摘要
适用场景:敏感信息的校验和存储、验证消息完整 & 未被篡改
特点
- 输出长度固定:输入长度不固定,输出长度固定(因算法而异,常见的有MD5、SHA系列)。
- 运算不可逆:已知运算结果的情况下,无法通过通过逆运算得到原始字符串。
- 高度离散:输入的微小变化,可导致运算结果差异巨大。
- 弱碰撞性:不同输入的散列值可能相同。
以MD5为例
MD5(Message-Digest Algorithm)是计算机安全领域广泛使用的散列函数(又称哈希算法、摘要算法),主要用来确保消息的完整和一致性。
常见的应用场景:密码保护、下载文件校验等。
应用场景
- 文件完整性校验:比如从网上下载一个软件,一般网站都会将软件的md5值附在网页上,用户下载完软件后,可对下载到本地的软件进行md5运算,然后跟网站上的md5值进行对比,确保软件的完整性
- 密码保护:将md5后的密码保存到数据库,而不是保存明文密码,避免拖库等事件发生后,明文密码泄漏。
- 防篡改:比如数字证书的防篡改,就用到了摘要算法。(当然还要结合数字签名等手段)
简单的md5运算
- hash.digest([encoding])
计算摘要。encoding可以是hex
、base64
或其他。如果声明了encoding,那么返回字符串。否则,返回Buffer实例。注意,调用hash.digest()后,hash对象就作废了,再次调用就会报错。
- hash.update(data[, input_encoding])
input_encoding可以是utf8
、ascii
或者其他。如果data是字符串,且没有指定 input_encoding,则默认是utf8
。注意,hash.update()方法可以调用多次。
const crypto = require('crypto');
const fs = require('fs');
const FILE_PATH = './index.txt'
const ENCODING = 'hex';