模块安装
JS:npm install crypto-js --save
1. MD5
MD5哈希视为字符串,而是将其视为十六进制数, MD5哈希长度为128位,通常由32 个十六进制数字表示。因此在看见加密字段长度为32位时可以先试试看是不是MD5加密。
JS实现
// 引用 crypto-js 加密模块
var CryptoJS = require('crypto-js')
function MD5Test() {
var text = "hello word!"
return CryptoJS.MD5(text).toString()
}
console.log(MD5Test())
Python实现
import hashlib
def md5_test():
md5 = hashlib.md5()
md5.update('python'.encode('utf-8'))
print(md5.hexdigest())
if __name__ == '__main__':
md5_test()
2. SHA
全称安全哈希算法。SHA 通常指 SHA 家族的五个算法
SHA-1:长度40 SHA-224:长度56 SHA-256:长度64 SHA-384:长度96 SHA-512:长度128
JS实现
var CryptoJS = require('crypto-js')
function SHAEncrypt() {
var text = "hello!"
return CryptoJS.SHA1(text).toString();
return CryptoJS.SHA224(text).toString();
return CryptoJS.SHA256(text).toString();
return CryptoJS.SHA384(text).toString();
return CryptoJS.SHA512(text).toString();
}
console.log(SHAEncrypt())
Python实现
import hashlib
def sha1_test():
sha1 = hashlib.sha1()
sha1.update('hello!'.encode('utf-8'))
print(sha1.hexdigest())
if __name__ == '__main__':
sha1_test()
3. HMAC
简单来说HMAC是在其他算法的基础上加上共享密钥(key)实现的,因此生成的密文长度和使用的基础算法一样。
JS实现
var CryptoJS = require('crypto-js')
function HMACText() {
var text = "hello word"
var key = "我是key"
var a = CryptoJS.HmacMD5(text, key).toString()
// var a = CryptoJS.HmacSHA1(text, key).toString()
console.log("明文:", text);
console.log("密文:", a);
console.log("长度:", a.length);
}
HMACText()
Python实现
import hmac
def hmac_test1():
message = 'hello word!'.encode()
key = b'secret'
md5 = hmac.new(key, message, digestmod='MD5')
print(md5.hexdigest())
def hmac_test2():
key = 'secret'.encode('utf8')
sha1 = hmac.new(key, digestmod='sha1')
sha1.update('hello '.encode('utf8'))
sha1.update('word!'.encode('utf8'))
print(sha1.hexdigest())
if __name__ == '__main__':
hmac_test1()
hmac_test2()
4. 对称加密
简单来说就是加密和解密使用同一个密钥。
常见算法归纳
DES: 56位密钥,由于密钥太短,被逐渐被弃用。
AES: 有128位、192位、256位密钥,现在比较流行。密钥长、可以增加破解的难度和成本。
工作模式归纳
ECB模式 全称Electronic Codebook模式,译为电子密码本模式,每个数据块独立进行加/解密CBC模式 全称Cipher Block Chaining模式,译为密文分组链接模式 先将明文切分成若干小块,然后每个小块与初始块或者上一段的密文段进行逻辑异或运算后,再用密钥进行加密。第一个明文块与一个叫初始化向量的数据块进行逻辑异或运算 CFB模式 全称Cipher FeedBack模式,译为密文反馈模式OFB模式 全称Output Feedback模式,译为输出反馈模式。CTR模式 全称Counter模式,译为计数器模式。
4.1 DES
DES算法的入口参数有3个:key、DATA、Mode、padding
key为7个字节共56位,是DES算法的工作密钥Data为8个字节64位,是要被加密或被解密的数据Mode为DES的工作方式padding为填充模式,如果加密后密文长度如果达不到指定整数倍(8个字节,16个字节),填充
JS实现
var CryptoJS = require('crypto-js')
function encryptByDES(message) {
var keyHex = CryptoJS.enc.Utf8.parse(key)
var encrypted = CryptoJS.DES.encrypt(message, keyHex, {
iv: CryptoJS.enc.Utf8.parse(iv),
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7 //我也可以不要
});
return encrypted.toString()
}
function decryptByDES(ciphertext) {
var keyHex = CryptoJS.enc.Utf8.parse(key)
var decrypted = CryptoJS.DES.decrypt({
ciphertext: CryptoJS.enc.Base64.parse(ciphertext)
}, keyHex, {
iv: CryptoJS.enc.Utf8.parse(iv),
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7 //我也可以不要
});
return decrypted.toString(CryptoJS.enc.Utf8)
}
var key = "我是密钥key"
var iv = "我是初始向量,可以不要"
var message = "我是需要加密的变量"
var encryptedData = encryptByDES(message)
var decryptedData = decryptByDES(encryptedData)
console.log("加密字符串: ", encryptedData)
console.log("解密字符串: ", decryptedData)
Python实现
pip install pyDes
import binascii
# 加密模式 CBC,填充方式 PAD_PKCS5
from pyDes import des, CBC, PAD_PKCS5
def des_encrypt(key, text, iv):
k = des(key, CBC, iv, pad=None, padmode=PAD_PKCS5)
en = k.encrypt(text, padmode=PAD_PKCS5)
return binascii.b2a_hex(en)
def des_decrypt(key, text, iv):
k = des(key, CBC, iv, pad=None, padmode=PAD_PKCS5)
de = k.decrypt(binascii.a2b_hex(text), padmode=PAD_PKCS5)
return de
if __name__ == '__main__':
secret_key = '12345678' # 密钥
text = 'hello world' # 加密对象
iv = secret_key # 偏移量
secret_str = des_encrypt(secret_key, text, iv)
print('加密字符串:', secret_str)
clear_str = des_decrypt(secret_key, secret_str, iv)
print('解密字符串:', clear_str)
4.2 AES
参数定义:
key length(密钥位数,密码长度)AES128,AES192,AES256(128 位、192 位或 256 位) key (密钥,密码)key指的就是密码了,AES128就是128位的,如果位数不够,某些库可能会自动填充到128。 IV (向量)IV称为初始向量,不同的IV加密后的字符串是不同的,加密和解密需要相同的IV。 mode (加密模式)AES分为几种模式,比如ECB,CBC,CFB等等,这些模式除了ECB由于没有使用IV而不太安全,其他模式差别并没有太明显。 padding (填充方式)对于加密解密两端需要使用同一的PADDING模式,大部分PADDING模式为PKCS5, PKCS7, NOPADDING。
JS实现
var CryptoJS = require('crypto-js')
function tripleAesEncrypt() {
var key = CryptoJS.enc.Utf8.parse(aesKey),
iv = CryptoJS.enc.Utf8.parse(aesIv),
srcs = CryptoJS.enc.Utf8.parse(text),
// CBC 加密方式,Pkcs7 填充方式
encrypted = CryptoJS.AES.encrypt(srcs, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString();
}
function tripleAesDecrypt() {
var key = CryptoJS.enc.Utf8.parse(aesKey),
iv = CryptoJS.enc.Utf8.parse(aesIv),
srcs = encryptedData,
// CBC 加密方式,Pkcs7 填充方式
decrypted = CryptoJS.AES.decrypt(srcs, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return decrypted.toString(CryptoJS.enc.Utf8);
}
var text = "hello word!" // 待加密对象
var aesKey = "6f726c64f2c2057c" // 密钥,16 倍数
var aesIv = "0123456789ABCDEF" // 偏移量,16 倍数
var encryptedData = tripleAesEncrypt()
var decryptedData = tripleAesDecrypt()
console.log("加密字符串: ", encryptedData)
console.log("解密字符串: ", decryptedData)
5. 非对称加密
与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
常见非对称加密算法 RSA、DSA。 非对称加密算法私钥由数据接收方持有,不会在网络上传递,保证了密钥的安全。 非对称加密算法通常比对称加密算法计算复杂,性能消耗高。 非对称加密算法可用于数字签名。
注意:
使用时都是使用公钥加密使用私钥解密,公钥可以公开,私钥自己保留。 算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使加密解密速度慢于对称加密
JS实现
npm install node-rsa --save
var NodeRSA = require('node-rsa');
function rsaEncrypt(text) {
pubKey = new NodeRAS(publicKey, 'pkcs8-public')
var encryptedData = pubKey.encrypt(text, 'base64')
return encryptedData
}
function rsaDecrypt(encryptedDate) {
priKey = new NodeRAS(privateKey, 'pkcs8-private')
var decryptedData = priKey.decrypt(encryptedDate, 'utf-8')
return decryptedData
}
var key = new NodeRAS({b: 512}) //生成512位的密钥
var publicKey = key.exportKey('pkcs8-public') // 导出公钥
var privateKey = key.exportKey('pkcs8-private') // 导出私钥
var text = "我是需要加密内容"
var encryptedDate = rsaEncrypt(text)
var decryptedDate = rsaDecrypt(encryptedDate)
console.log("公钥:", publicKey)
console.log("私钥:", privateKey)
console.log("加密字符串:", encryptedDate)
console.log("解密字符串:", decryptedDate)
6. 国密
由国家密码管理局发布的一系列国产加密算法,这其中就包括 SM1、SM2、SM3 、SM4、SM7、SM9、ZUC(祖冲之加密算法)等,SM 代表商密,即商业密码,是指用于商业的、不涉及国家秘密的密码技术。SM1 和 SM7的算法不公开,其余算法都已成为ISO/IEC 国际标准。
6.1 算法分类
算法名称 算法类别 应用领域 特点 SM1 对称(分组)加密算法 芯片 分组长度、密钥长度均为 128 比特 SM2 非对称(基于椭圆曲线 ECC)加密算法 数据加密 ECC 椭圆曲线密码机制 256 位,相比 RSA 处理速度快,消耗更少 SM3 散列(hash)函数算法 完整性校验 安全性及效率与 SHA-256 相当,压缩函数更复杂 SM4 对称(分组)加密算法 数据加密和局域网产品 分组长度、密钥长度均为 128 比特,计算轮数多 SM7 对称(分组)加密算法 非接触式 IC 卡 分组长度、密钥长度均为 128 比特 SM9 标识加密算法(IBE) 端对端离线安全通讯 加密强度等同于 3072 位密钥的 RSA 加密算法 ZUC 对称(序列)加密算法 移动通信 4G 网络 流密码
6.2 算法还原
JS实现sm2
npm install sm-crypto --save
目前支持SM2、SM3 和 SM4
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)
Python实现sm2
pip install gmssl
目前支持SM2、SM3 和 SM4
from gmssl import sm2
# 16 进制的公钥和私钥
private_key = '00B9AB0B828FF68872F21A837FC303668428DEA11DCD1B24429D0C99E24EED83D5'
public_key = 'B9C9A6E04E9C91F7BA880429273747D7EF5DDEB0BB2FF6317EB00BEF331A83081A6994B8993F3F5D6EADDDB81872266C87C018FB4162F5AF347B483E24620207'
sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key=private_key)
# 待加密数据和加密后数据为 bytes 类型
data = b"this is the data to be encrypted"
enc_data = sm2_crypt.encrypt(data)
dec_data = sm2_crypt.decrypt(enc_data)
print('enc_data: ', enc_data.hex())
print('dec_data: ', dec_data)