加密是确保数据安全、保护隐私、遵守法律法规的关键技术。它不仅在传输过程中保护数据免受窥探,还确保数据在存储和处理时的安全性,并防止数据被篡改或滥用。因此,现代互联网和通信系统中的加密技术至关重要。
1、哈希算法
哈希(Hash)是一种将任意长度的输入(如字符串、文件等)通过哈希函数转换为
固定长度
输出的过程。输出通常称为哈希值或摘要
哈希加密的主要场景就是 密码存储、大文件分片上传验证文件完整性
特点
- 确定性:相同的
输入
总是产生相同的哈希值
。 - 高效性:计算哈希值的过程应快速完成。
- 抗碰撞性:难以找到两个不同的输入产生相同的哈希值。
- 单向性:从哈希值
无法反推
出原始输入
。
常见算法
md5
:较旧的哈希算法,已不推荐用于安全用途,但仍被一些应用使用。sha1
:较为常见的哈希算法,已不推荐用于安全用途。sha256
:当前广泛使用的安全哈希算法。sha512
:更强大的哈希算法,产生更长的哈希值
名称 | 输出长度 | 说明 |
---|---|---|
md5 | 128位(16字节) | 较旧的哈希算法,已不推荐用于安全用途,但仍被一些应用使用。 |
sha1 | 160 位(20 字节) | 较为常见的哈希算法,已不推荐用于安全用途。 |
sha256 | 256 位(32 字节) | |
sha512 | 512 位(64 字节) | |
sha224 | 224 位(28 字节) | |
sha384 | 384 位(48 字节) | |
sha3-256 | 256 位(32 字节) | 较新的安全哈希算法 |
sha3-512 | 512 位(64 字节) | 较新的安全哈希算法 |
sha3-224 | 224 位(28 字节) | 较新的安全哈希算法 |
sha3-384 | 384 位(48 字节) | 较新的安全哈希算法 |
举例
基本使用
const crypto = require("crypto");
console.log("当前支持的hash算法列表", crypto.getHashes(), crypto.getHashes().join()); // RSA-MD5,RSA-RIPEMD160,RSA-SHA1,RSA-SHA1-2,RSA-SHA224,RSA-SHA256,RSA-SHA3-224,RSA-SHA3-256,RSA-SHA3-384,RSA-SHA3-512,RSA-SHA384,RSA-SHA512,RSA-SHA512/224,RSA-SHA512/256,RSA-SM3,blake2b512,blake2s256,id-rsassa-pkcs1-v1_5-with-sha3-224,id-rsassa-pkcs1-v1_5-with-sha3-256,id-rsassa-pkcs1-v1_5-with-sha3-384,id-rsassa-pkcs1-v1_5-with-sha3-512,md5,md5-sha1,md5WithRSAEncryption,ripemd,ripemd160,ripemd160WithRSA,rmd160,sha1,sha1WithRSAEncryption,sha224,sha224WithRSAEncryption,sha256,sha256WithRSAEncryption,sha3-224,sha3-256,sha3-384,sha3-512,sha384,sha384WithRSAEncryption,sha512,sha512-224,sha512-224WithRSAEncryption,sha512-256,sha512-256WithRSAEncryption,sha512WithRSAEncryption,shake128,shake256,sm3,sm3WithRSAEncryption,ssl3-md5,ssl3-sha1
// md5 的使用
// 1、创建一个 md5 哈希对象
const hash = crypto.createHash("md5");
// 2、要加密的数据
hash.update("hello");
// 3、获取最终的哈希值(以十六进制格式输出)
// 每个十六进制字符表示 4 位二进制数据。128位转化为十六进制就是 128/4 = 32 个十六进制字符。
const hashValue = hash.digest("hex");
console.log('md5(128 位,16个字节)',hashValue, hashValue.length);
console.log(
"sha256(256 位,32个字节)",
crypto.createHash("sha256").update("hello").digest("hex"),
crypto.createHash("sha256").update("hello").digest("hex").length
);
但是在实际开发中,不会直接这样使用,而是
加盐
(通过向原始数据(如密码)添加一个随机值(称为盐)来增加哈希的复杂度,防止一些常见的攻击方法,如彩虹表攻击和字典攻击。)
const crypto = require("crypto");
const hash = crypto.createHash("md5");
let salt = crypto.randomBytes(16).toString("hex");
hash.update("hello" + salt);
// 3、获取最终的哈希值(以十六进制格式输出)
// 每个十六进制字符表示 4 位二进制数据。128位转化为十六进制就是 128/4 = 32 个十六进制字符。
const hashValue = hash.digest("hex");
console.log("加盐值:", salt); // 加盐值: 9c82520f02a63d5bad96ce364d5728c8
console.log("加盐加密后", hashValue, hashValue.length); // 加盐加密后 88758b255e6748fa5238ddd5b6b1959f 32
// 使用固定的盐,
const hash1 = crypto.createHash("md5");
let salt1 = Buffer.from("123", "utf-8").toString("hex");
hash1.update("hello" + salt1);
const hashValue1 = hash1.digest("hex");
console.log("加盐值:", salt1); // 加盐值: 313233
console.log("加盐加密后", hashValue1, hashValue1.length); // 加盐加密后 3fb4b5daa2aeefc00a160c265d87128a 32
2、对称加密
对称加密是一种简单而快速的加密方式,它使用相同的密钥(称为对称密钥)来进行加密和解密。发送者和接收者在加密和解密过程中都使用相同的密钥。
特点
- 相同的密钥:发送方和接收方都需要拥有相同的密钥才能进行加密和解密操作。这意味着双方在通信之前需要安全地交换密钥。
- 速度较快
- 适合加密大量数据
常见算法
名称 | 说明 | 密钥长度 |
---|---|---|
AES | AES 是一种非常安全且高效的加密标准,被广泛应用于政府、金融、商业等多个领域。 | 支持 128 位、192 位和 256 位密钥长度 |
DES | DES 是一种历史较久的加密算法,曾经是美国的加密标准,但由于其 56 位密钥长度较短,已经不再安全,逐渐被替代。 | 56位 |
举例
const crypto = require("crypto");
// 获取所有支持的加密算法
const ciphers = crypto.getCiphers();
console.log("Supported ciphers:", ciphers, ciphers.join()); // aes-128-cbc,aes-128-cbc-hmac-sha1,aes-128-cbc-hmac-sha256,aes-128-ccm,aes-128-cfb,aes-128-cfb1,aes-128-cfb8,aes-128-ctr,aes-128-ecb,aes-128-gcm,aes-128-ocb,aes-128-ofb,aes-128-xts,aes-192-cbc,aes-192-ccm,aes-192-cfb,aes-192-cfb1,aes-192-cfb8,aes-192-ctr,aes-192-ecb,aes-192-gcm,aes-192-ocb,aes-192-ofb,aes-256-cbc,aes-256-cbc-hmac-sha1,aes-256-cbc-hmac-sha256,aes-256-ccm,aes-256-cfb,aes-256-cfb1,aes-256-cfb8,aes-256-ctr,aes-256-ecb,aes-256-gcm,aes-256-ocb,aes-256-ofb,aes-256-xts,aes128,aes128-wrap,aes192,aes192-wrap,aes256,aes256-wrap,aria-128-cbc,aria-128-ccm,aria-128-cfb,aria-128-cfb1,aria-128-cfb8,aria-128-ctr,aria-128-ecb,aria-128-gcm,aria-128-ofb,aria-192-cbc,aria-192-ccm,aria-192-cfb,aria-192-cfb1,aria-192-cfb8,aria-192-ctr,aria-192-ecb,aria-192-gcm,aria-192-ofb,aria-256-cbc,aria-256-ccm,aria-256-cfb,aria-256-cfb1,aria-256-cfb8,aria-256-ctr,aria-256-ecb,aria-256-gcm,aria-256-ofb,aria128,aria192,aria256,camellia-128-cbc,camellia-128-cfb,camellia-128-cfb1,camellia-128-cfb8,camellia-128-ctr,camellia-128-ecb,camellia-128-ofb,camellia-192-cbc,camellia-192-cfb,camellia-192-cfb1,camellia-192-cfb8,camellia-192-ctr,camellia-192-ecb,camellia-192-ofb,camellia-256-cbc,camellia-256-cfb,camellia-256-cfb1,camellia-256-cfb8,camellia-256-ctr,camellia-256-ecb,camellia-256-ofb,camellia128,camellia192,camellia256,chacha20,chacha20-poly1305,des-ede,des-ede-cbc,des-ede-cfb,des-ede-ecb,des-ede-ofb,des-ede3,des-ede3-cbc,des-ede3-cfb,des-ede3-cfb1,des-ede3-cfb8,des-ede3-ecb,des-ede3-ofb,des3,des3-wrap,id-aes128-CCM,id-aes128-GCM,id-aes128-wrap,id-aes128-wrap-pad,id-aes192-CCM,id-aes192-GCM,id-aes192-wrap,id-aes192-wrap-pad,id-aes256-CCM,id-aes256-GCM,id-aes256-wrap,id-aes256-wrap-pad,id-smime-alg-CMS3DESwrap,sm4,sm4-cbc,sm4-cfb,sm4-ctr,sm4-ecb,sm4-ofb
// 密钥 (key):这是加密和解密操作所用的秘密密钥,必须保密。通常应该是随机生成并安全存储。
// 初始化向量 (iv):用于增加加密的随机性。aes-256-cbc 算法需要 16 字节的 IV(128 位)。
// 加密数据
// 1、设置密钥和初始化向量(IV)
const key = crypto.randomBytes(32); // 256位密钥
const iv = crypto.randomBytes(16); // 128位初始化向量
console.log("key", key, "长度", key.length);
console.log("iv", iv, "长度", iv.length);
// 2、创建加密器
const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
const data = "我是呆呆狗";
// update() 方法用于加密数据,final() 方法用于结束加密过程并返回剩余部分。
// update() 方法的参数是待加密的数据,第二个参数是输入数据的编码,第三个参数是输出数据的编码。
let encryptedData = cipher.update(data, "utf8", "hex");
// final 方法的参数是输出数据的编码。
encryptedData += cipher.final("hex");
console.log("加密后的数据:", encryptedData);
console.log("Key:", key.toString("hex"));
console.log("IV:", iv.toString("hex"));
// 解密
// 1、创建解密器
const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
// 2、解密数据
let decryptedData = decipher.update(encryptedData, "hex", "utf8");
decryptedData += decipher.final("utf8");
console.log("解密数据:", decryptedData);
比如在实际开发中,有些网站会对请求体的信息进行加密,这个时候就适合用
对称加密
3、非对称加密
非对称加密使用一对密钥,分别是公钥和私钥。发送者使用接收者的公钥进行加密,而接收者使用自己的私钥进行解密。公钥可以自由分享给任何人,而私钥必须保密。
常见的情况就是, 使用非对称加密来交换 对称加密的密钥,然后使用对称加密算法,来加密解密实际数据
特点
- 使用一对密钥,(公钥和私钥)
- 公钥加密,私钥解密。
- 加密效率较低
常见算法
RSA
这个是最长远的非对称加密算法之一
const crypto = require("node:crypto");
// 生成 RSA 密钥对
const { privateKey, publicKey } = crypto.generateKeyPairSync("rsa", {
modulusLength: 2048,
publicKeyEncoding: { type: "spki", format: "pem" },
privateKeyEncoding: { type: "pkcs8", format: "pem" },
});
console.log("私钥", privateKey);
console.log("公钥", publicKey);
// 要加密的数据
const text = "我是呆呆狗";
// 使用公钥进行加密
const encrypted = crypto.publicEncrypt(publicKey, Buffer.from(text, "utf-8"));
console.log("加密后的数据", encrypted.toString("hex"));
// 使用私钥进行解密
const decrypted = crypto.privateDecrypt(privateKey, encrypted);
console.log("解密后的数据", decrypted.toString("utf-8"));