说明:本文不是算法的科普,仅是学习过程中的总结,旨在比较各算法的加密过程以及密文长度,以便逆向过程中遇到加密数据能帮助推测是使用了何种加密。有错漏之处烦请指正,仅供初学者参考。
哈希算法
哈希算法是一种将任意长度的数据映射为固定长度数据的算法,其中所得的结果就是哈希值。根据哈希算法的特性,无论输入数据的大小如何,所得到的哈希值长度都是固定的。
MD5
var crypto = require('crypto-js')
function md5(text) {
return crypto.MD5(text).toString()
}
SHA
SHA系列的算法有五个,分别是SHA-1、SHA-224、SHA-256、SHA-384、SHA-512
var crypto = require('crypto-js')
function sha1(text) {
return crypto.SHA1(text).toString()
}
HMAC
HMAC是密钥相关的哈希运算消息认证码(Hash-based Message Authentication Code)的缩写,基于hash函数和密钥进行消息认证。
var crypto = require('crypto-js')
function hmacMD5(text) {
var key = 'secret key'
return crypto.HmacMD5(text, key).toString()
}
function hmacSHA1(text) {
var key = 'secret key'
return crypto.HmacSHA1(text, key).toString()
}
算法 | 加密后密文长度 |
MD5 | 32字符 |
SHA-1 | 40字符 |
SHA-224 | 56字符 |
SHA-256 | 64字符 |
SHA-384 | 96字符 |
SHA-512 | 128字符 |
对称加密算法
对称加密算法是一种使用同一个密钥进行加密和解密的算法
DES
const crypto = require('crypto-js')
const desKey = "1234abcd" // 密钥
const desIv = "5678zxcv" // 初始向量
function desEncrypt(text) {
const key = crypto.enc.Utf8.parse(desKey),
iv = crypto.enc.Utf8.parse(desIv),
str = crypto.enc.Utf8.parse(text),
encrypted = crypto.DES.encrypt(str, key, {
iv: iv,
mode: crypto.mode.CBC,
padding: crypto.pad.Pkcs7
});
return encrypted.toString();
}
function desDecrypt(text) {
const key = crypto.enc.Utf8.parse(desKey),
iv = crypto.enc.Utf8.parse(desIv),
decrypted = crypto.DES.decrypt(text, key, {
iv: iv,
mode: crypto.mode.CBC,
padding: crypto.pad.Pkcs7
});
return decrypted.toString(crypto.enc.Utf8)
}
AES
const crypto = require('crypto-js')
const aesKey = "1234abcd" // 密钥
const aesIv = "5678zxcv" // 初始向量
function aesEncrypt(text) {
const key = crypto.enc.Utf8.parse(aesKey),
iv = crypto.enc.Utf8.parse(aesIv),
str = crypto.enc.Utf8.parse(text),
encrypted = crypto.AES.encrypt(str, key, {
iv: iv,
mode: crypto.mode.CBC,
padding: crypto.pad.Pkcs7
});
return encrypted.toString();
}
function aesDecrypt(text) {
const key = crypto.enc.Utf8.parse(aesKey),
iv = crypto.enc.Utf8.parse(aesIv),
decrypted = crypto.AES.decrypt(text, key, {
iv: iv,
mode: crypto.mode.CBC,
padding: crypto.pad.Pkcs7
});
return decrypted.toString(crypto.enc.Utf8)
}
-
mode 支持:ECB,CBC,CFB,CTR,CTRGladman,OFB 等。
-
padding 支持:Pkcs7,ZeroPadding,NoPadding,AnsiX923,Iso10126,Iso97971 等。
DES和AES用现成的算法库进行加密解密的代码看起来几乎没有区别,但是两种算法是有很大区别的:
- 密钥长度:AES的密钥长度可以是128位、192位或256位,而DES的密钥长度只有56位。AES密钥长度的增加使其更难以破解。
- 加密轮数:AES的加密轮数是10、12或14轮(取决于密钥长度),而DES只有固定的16轮。虽然AES的轮数更多,但这并不是为了简单地增加复杂性。事实上,AES每一轮都使用了新的子密钥,而DES的所有轮都使用相同的子密钥。
- 处理方式:在DES中,明文被分为两部分,然后进行进一步的处理。而在AES中,整个块不进行除法,而是整个块一起处理以生成密文。
- 灵活性:AES允许包括128、192、256位在内的各种长度的文本,而DES只允许对64位固定文本进行加密。
- 速度:AES比DES快得多。AES可以在几秒钟内加密大型文件,而DES最初只在硬件上有效。
- 安全性:AES被认为比DES更安全,并且到目前为止,尚未遇到任何严重攻击的AES。由于DES中使用的共享密钥的比特大小较小,因此它被认为不如AES安全。
加密后的密文结尾常见‘=’,类似:
+ndbEkWNw2QAfIYQtwC14w==
非对称加密算法
非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
RSA
const NodeRSA = require('node-rsa');
const key = new NodeRSA({b: 512}); //生成512位秘钥
const publicKey = key.exportKey('pkcs8-public'); //导出公钥
const privatekey = key.exportKey('pkcs8-private'); //导出私钥
function rsaEncrypt(text) {
pubKey = new NodeRSA(publicKey,'pkcs8-public');
return pubKey.encrypt(text, 'base64')
}
function rsaDecrypt(text) {
priKey = new NodeRSA(privatekey,'pkcs8-private');
return priKey.decrypt(text, 'utf8')
}
RSA产生的密文长度通常有88字符、172字符、344字符
国家密码算法
国产加密算法,包括SM1、SM2、SM3 、SM4、SM7、SM9、ZUC等,常见的有SM2、SM3、SM4
算法 | 类别 | 应用领域 |
SM1 | 对称(分组)加密算法 | 芯片 |
SM2 | 非对称(基于椭圆曲线 ECC)加密算法 | 数据加密 |
SM3 | 散列(hash)函数算法 | 完整性校验 |
SM4 | 对称(分组)加密算法 | 数据加密和局域网产品 |
SM7 | 对称(分组)加密算法 | 非接触式 IC 卡 |
SM9 | 标识加密算法(IBE) | 端对端离线安全通讯 |
ZUC | 对称(序列)加密算法 | 移动通信 4G 网络 |
SM2
const sm2 = require('sm-crypto').sm2
// 1 - C1C3C2, 0 - C1C2C3, 默认为1
const cipherMode = 1
// 获取密钥对
let keypair = sm2.generateKeyPairHex()
let publicKey = keypair.publicKey // 公钥
let privateKey = keypair.privateKey // 私钥
let msgString = "this is the data to be encrypted"
let encryptData = sm2.doEncrypt(msgString, publicKey, cipherMode) // 加密
let decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode) // 解密
console.log("encryptData: ", encryptData)
console.log("decryptData: ", decryptData)
SM3
const sm3 = require('sm-crypto').sm3
const data = 'this is the data to be encrypted'
const hash = sm3(data)
console.log('SM3 Hash:', hash)
SM4
const sm4 = require('sm-crypto').sm4;
const key = '0123456789ABCDEF0123456789ABCDEF' // 设置SM4密钥(128位, 16字节)
const mode = 'ecb' // 设置SM4加解密模式(ecb、cbc、ctr等)
const plaintext = 'this is the data to be encrypted'
const ciphertext = sm4.encrypt(plaintext, key, { mode }) // 加密
const decryptedText = sm4.decrypt(ciphertext, key, { mode }) // 解密
console.log('Encrypted:', ciphertext)
console.log('Decrypted:', decryptedText)