【JS逆向】【15.编码算法】对称加密(AES与DES),非对称加密(RSA)(详细笔记)

本文详细介绍了对称加密(AES与DES)中的CBC模式加密和解密过程,以及非对称加密(RSA)的公钥私钥机制,包括加密和解密示例。着重展示了如何在JavaScript中实现AES-CBC-128加密和RSA加密解密操作。
摘要由CSDN通过智能技术生成

一、对称加密(AES与DES)

1. 前言

随着互联网的发展,越来越多的数据需要在网络中进行传输。为了保证数据的安全性,在进行网络传输时,需要对数据进行加密操作,使得数据在传输过程中不被窃取或篡改。AES(Advanced Encryption Standard)就是一种经典的加密算法。

AES 算法源于比利时密码学家 Joan Daemen 和 Vincent Rijmen,它是一种对称加密算法通过使用相同的密钥对数据进行加密和解密操作。AES 算法中,加密和解密操作是相反的过程,因此需要使用相同的密钥作为加密和解密的关键参数。

AES 算法使用分组密码体制,将明文按照固定大小进行分组,然后对每一分组进行加密。在加密过程中,AES 算法采用了多轮加密的方式,每一轮加密都包含了四种操作:SubBytes、ShiftRows、MixColumns 和 AddRoundKey。通过这些操作,AES 算法可以更加安全高效地对数据进行加密。

AES是一种对称加密,所谓对称加密就是加密与解密使用的秘钥是一个。

2. 安装

pip install pycryptodome

AES 加密最常用的模式就是 ECB模式 CBC模式,当然还有很多其它模式,他们都属于AES加密。ECB模式CBC模式俩者区别就是 ECB 不需要 iv偏移量,而CBC需要

"""
# 参数	作用及数据类型

1. 秘钥 :加密的时候用秘钥,解密的时候需要同样的秘钥才能解出来; 数据类型为bytes
2. 明文 :需要加密的参数; 数据类型为bytes
3. 模式 :aes 加密常用的有 ECB 和 CBC 模式(为主)(我只用了这两个模式,还有其他模式);数据类型为aes类内部的枚举量
iv 偏移量 :这个参数在 ECB 模式下不需要,在 CBC 模式下需要;数据类型为bytes

AES - CBC - 128 用得最多
长度
    16: *AES-128*  
    24: *AES-192*
    32: *AES-256*
    
MODE 加密模式: 
    常见的ECB, CBC
    ECB:是一种基础的加密方式,密文被分割成分组长度相等的块(不足补齐),然后单独一个个加密,一个个输出组成密文。
    CBC:是一种循环模式,前一个分组的密文和当前分组的明文异或或操作后再加密,这样做的目的是增强破解难度。
"""

3. CBC加密

先加密 - 编码 - 解码 - 解密

from Crypto.Cipher import AES
import base64

# AES-128模式:key:16;  iv:16位; 明文:是16的倍数;
# 明文
data = "Alex is ugly!"  # 需要加密的内容
data = '{"name":"alex","msg":"ugly"}'
print(len(data))  # 13 位
while len(data) % 16 != 0:  # 如果data不足16位的倍数就用空格补足为16位
    data += "\0"
print(data, len(data))  # Alex is ugly!    16位

# 密钥
key = "1234567890123456".encode()  # 保证16位数
# 偏移量
iv = "aaaabbbbccccdddd".encode()  # 偏移量--必须16字节

# (1) 加密
# 创建一个aes对象
aes = AES.new(key, AES.MODE_CBC, iv)  # 参数:密钥,MODE_CBC模式,偏移量

encrypt_data = aes.encrypt(data.encode()) # 加密明文
print(f"aes加密数据::::{encrypt_data}")  # b'\x93\x1e\xdca\xbd\x08\xb1\xed\xef\xdbc\xc0\xa31\xaco'

# (2) base64编码
base64_encrypt_data = base64.b64encode(encrypt_data).decode()  # 将返回的字节型数据转进行base64编码
print("base64_encrypt_data:", base64_encrypt_data)  # kx7cYb0Ise3v22PAozGsbw==

4. CBC解密

# (3) base64解码
base64_encrypt_data = "kx7cYb0Ise3v22PAozGsbw=="
base64_encrypt_data = "ipmd89j3VlVClCk6EuFQFVxIeag1OwY0FrEKRTz2c9Y="

encrypt_data = base64.b64decode(base64_encrypt_data)
print(encrypt_data)

# (4) 解密,发生在服务端
# 密钥
key = "1234567890123456".encode()
# 偏移量
iv = "aaaabbbbccccdddd".encode()

# 解密
# 构建aes算法对象
aes = AES.new(key, AES.MODE_CBC, iv)
source_data = aes.decrypt(encrypt_data).decode()
print("source_data::::", source_data)  # source_data:::: Alex is ugly! 

import json
data_dict = json.loads(source_data.rstrip("\0"))
print("name:", data_dict.get("name"))
print("msg:", data_dict.get("msg"))
  1. 在Python中进行AES加密解密时,所传入的密文、明文、秘钥、iv偏移量、都需要是bytes(字节型)数据。python 在构建aes对象时也只能接受bytes类型数据。
  2. 秘钥,iv偏移量,待加密的明文,字节长度不够16字节或者16字节倍数的时候需要进行补全。
  3. CBC模式需要重新生成AES对象,为了防止这类错误,无论是什么模式都重新生成AES对象就可以了。

二、非对称加密(RSA)

非对称加密,加密和解密的秘钥不是同一个秘钥,这里需要两把钥匙,一个公钥, 一个私钥, 公钥发送给客户端。发送端用公钥对数据进行加密,再发送给接收端,接收端使用私钥来对数据解密。由于私钥只存放在接受端这边,所以即使数据被截获了,也是无法进行解密的。

1. 公钥和密钥

常见的非对称加密算法:RSA,DSA等等, 我们就介绍一个. RSA加密, 也是最常见的一种加密方案。

数字签名是什么?在这里插入图片描述
鲍勃有两把钥匙,一把是公钥,另一把是私钥
在这里插入图片描述
鲍勃把公钥送给他的朋友们----帕蒂、道格、苏珊----每人一把。
在这里插入图片描述
苏珊要给鲍勃写一封保密的信。她写完后用鲍勃的公钥加密,就可以达到保密的效果。
在这里插入图片描述
鲍勃收信后,用私钥解密,就看到了信件内容。这里要强调的是,只要鲍勃的私钥不泄露,这封信就是安全的,即使落在别人手里,也无法解密。
在这里插入图片描述
鲍勃给苏珊回信,决定采用"数字签名"。他写完后先用Hash函数,生成信件的摘要(digest)。
在这里插入图片描述
然后,鲍勃使用私钥,对这个摘要加密,生成"数字签名"(signature)。
在这里插入图片描述
鲍勃将这个签名,附在信件下面,一起发给苏珊。
在这里插入图片描述
苏珊收信后,取下数字签名,用鲍勃的公钥解密,得到信件的摘要。由此证明,这封信确实是鲍勃发出的。
在这里插入图片描述
苏珊再对信件本身使用Hash函数,将得到的结果,与上一步得到的摘要进行对比。如果两者一致,就证明这封信未被修改过。
在这里插入图片描述
复杂的情况出现了。道格想欺骗苏珊,他偷偷使用了苏珊的电脑,用自己的公钥换走了鲍勃的公钥。此时,苏珊实际拥有的是道格的公钥,但是还以为这是鲍勃的公钥。因此,道格就可以冒充鲍勃,用自己的私钥做成"数字签名",写信给苏珊,让苏珊用假的鲍勃公钥进行解密。
在这里插入图片描述
后来,苏珊感觉不对劲,发现自己无法确定公钥是否真的属于鲍勃。她想到了一个办法,要求鲍勃去找"证书中心"(certificate authority,简称CA),为公钥做认证。证书中心用自己的私钥,对鲍勃的公钥和一些相关信息一起加密,生成"数字证书"(Digital Certificate)。
在这里插入图片描述
鲍勃拿到数字证书以后,就可以放心了。以后再给苏珊写信,只要在签名的同时,再附上数字证书就行了。在这里插入图片描述
苏珊收信后,用CA的公钥解开数字证书,就可以拿到鲍勃真实的公钥了,然后就能证明"数字签名"是否真的是鲍勃签的。

2. 生成公私钥

from Crypto.PublicKey import RSA

# 生成秘钥
rsakey = RSA.generate(1024)
with open("rsa.public.pem", mode="wb") as f:
    f.write(rsakey.publickey().exportKey())  # 公钥

with open("rsa.private.pem", mode="wb") as f:
    f.write(rsakey.exportKey())  # 私钥

3. 公私钥加密和解密

加密

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64

# 明文数据
data = "I like you"

# 读取公钥
with open("rsa.public.pem", "r") as f: 
    public_key = f.read()
    print("公钥 - public_key::::", public_key)
    # (1)基于公钥做加密
    rsa_pk = RSA.importKey(public_key)
    rsa = PKCS1_v1_5.new(rsa_pk)

    encrypt_data = rsa.encrypt(data.encode())
    print("加密数据 - encrypt_data::::", encrypt_data)
    # (2)base64编码 - 处理成b64方便传输
    b64_encrypt_data = base64.b64encode(encrypt_data).decode()
    print("b 64_加密数据 - b64_encrypt_data::::", b64_encrypt_data)

解密

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64

b64_encrypt_data = "XA7rH4aYoZ+mrQddsCt+zGOG4uB+oqU2BOoo6rxaYJAj3y/4wR2a/hId5tsgisxZoVw1j2mlSYOZzFIpKSwv53JrI/SYtWl7qH4QCXimaTB4a4qZ+Vf//h7KoI51vlXu9o1GQYMm9ijrb0MmUZc9BX85UdLf0/+p46s5tBcC1IU="

# (3)base64解码
encrypt_data = base64.b64decode(b64_encrypt_data)
print("encrypt_data:", encrypt_data)

# (4)基于私钥解密
with open("rsa.private.pem", "r") as f:  # 读取私钥
    private_key = f.read()
    rsa_pk = RSA.importKey(private_key)
    rsa = PKCS1_v1_5.new(rsa_pk)
    data = rsa.decrypt(encrypt_data,None)
    print("data:", data.decode())
  • 21
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
双向 RSA + AES 加密是一种常见的加密方式,其中使用 RSA 算法加密 AES 密钥,然后使用 AES 算法加密数据。在 C# 中,可以使用 `RSACryptoServiceProvider` 类和 `AesCryptoServiceProvider` 类来实现此加密方式。以下是一个简单的示例: ```csharp using System; using System.IO; using System.Security.Cryptography; using System.Text; class Program { static void Main(string[] args) { string plainText = "Hello, world!"; byte[] encryptedData = Encrypt(plainText); string decryptedText = Decrypt(encryptedData); Console.WriteLine("Original text: {0}", plainText); Console.WriteLine("Encrypted data: {0}", Convert.ToBase64String(encryptedData)); Console.WriteLine("Decrypted text: {0}", decryptedText); } static byte[] Encrypt(string plainText) { byte[] aesKey = GenerateAesKey(); using (var rsa = new RSACryptoServiceProvider()) { rsa.PersistKeyInCsp = false; byte[] encryptedAesKey = rsa.Encrypt(aesKey, true); // 使用 RSA 加密 AES 密钥 using (var aes = new AesCryptoServiceProvider()) { aes.Key = aesKey; aes.GenerateIV(); using (var memoryStream = new MemoryStream()) { memoryStream.Write(aes.IV, 0, aes.IV.Length); using (var cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write)) { byte[] plainData = Encoding.UTF8.GetBytes(plainText); cryptoStream.Write(plainData, 0, plainData.Length); cryptoStream.FlushFinalBlock(); } byte[] encryptedData = memoryStream.ToArray(); byte[] result = new byte[encryptedAesKey.Length + encryptedData.Length]; Buffer.BlockCopy(encryptedAesKey, 0, result, 0, encryptedAesKey.Length); Buffer.BlockCopy(encryptedData, 0, result, encryptedAesKey.Length, encryptedData.Length); return result; } } } } static string Decrypt(byte[] encryptedData) { byte[] encryptedAesKey = new byte[128]; // RSA 加密 AES 密钥得到的密文长度为 128 字节 byte[] encryptedDataOnly = new byte[encryptedData.Length - encryptedAesKey.Length]; Buffer.BlockCopy(encryptedData, 0, encryptedAesKey, 0, encryptedAesKey.Length); Buffer.BlockCopy(encryptedData, encryptedAesKey.Length, encryptedDataOnly, 0, encryptedDataOnly.Length); using (var rsa = new RSACryptoServiceProvider()) { rsa.PersistKeyInCsp = false; byte[] aesKey = rsa.Decrypt(encryptedAesKey, true); // 使用 RSA 解密 AES 密钥 using (var aes = new AesCryptoServiceProvider()) { aes.Key = aesKey; aes.IV = encryptedDataOnly.Take(aes.IV.Length).ToArray(); using (var memoryStream = new MemoryStream()) { using (var cryptoStream = new CryptoStream(memoryStream, aes.CreateDecryptor(), CryptoStreamMode.Write)) { cryptoStream.Write(encryptedDataOnly, aes.IV.Length, encryptedDataOnly.Length - aes.IV.Length); cryptoStream.FlushFinalBlock(); } byte[] decryptedData = memoryStream.ToArray(); return Encoding.UTF8.GetString(decryptedData); } } } } static byte[] GenerateAesKey() { using (var aes = new AesCryptoServiceProvider()) { aes.GenerateKey(); return aes.Key; } } } ``` 上面的代码中,首先调用 `GenerateAesKey` 方法生成 AES 密钥,然后使用 RSA 算法加密 AES 密钥。加密时,先将 AES 密钥使用 RSA 加密,然后使用 AES 算法加密数据。具体来说,将 AES 密钥和 IV 都写入 `MemoryStream` 对象中,然后使用 `CryptoStream` 对象将数据写入 `MemoryStream` 对象中。最后将密文和 RSA 加密的 AES 密钥一起返回。 解密时,先从密文中取出 RSA 加密的 AES 密钥,然后使用 RSA 算法解密 AES 密钥。解密时,先从密文中取出 AES 的 IV 值,然后使用 `CryptoStream` 对象将数据解密。最后将解密后的文本返回。 注意,上面的示例仅用于演示 RSA + AES 加密的基本原理,实际使用中还需要考虑安全性等因素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

My.ICBM

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值