什么是对称加密

什么叫对称加密呢,你可以这么理解,一方通过密钥将信息加密后,把密文传给另一方,另一方通过这个相同的密钥将密文解密,转换成可以理解的明文。

什么是非对称加密

  • A要向B发送信息,A和B都要产生一对用于加密和解密的公钥和私钥。
  • A的私钥保密,A的公钥告诉B;B的私钥保密,B的公钥告诉A。
  • A要给B发送信息时,A用B的公钥加密信息,因为A知道B的公钥。
  • A将这个消息发给B(已经用B的公钥加密消息)。
  • B收到这个消息后,B用自己的私钥解密A的消息,其他所有收到这个报文的人都无法解密,因为只有B才有B的私钥。
  • 反过来,B向A发送消息也是一样。

对称加密和非对称加密的对比:

对称加密加密与解密使用的是同样的密钥,所以速度快,但由于需要将密钥在网络传输,所以
安全性不高。

  • 非对称加密使用了一对密钥,公钥与私钥,所以安全性高,但加密与解密速度慢。
  • 解决的办法是将对称加密的密钥使用非对称加密的公钥进行加密,然后发送出去,接收方使用私钥进行解密得到对称加密的密钥,然后双方可以使用对称加密来进行沟通

什么是AES:

AES 算法全称是 Advanced Encryption Standard,是DES 算法的替代者,也是现在最流行的对称加密算法之一。

AES的加密流程:

1.把明文按照128bit拆分成若干个明文块。
2.按照选择的填充方式来填充最后一个明文块。
3.每一个明文块利用AES加密器和密钥,加密成密文块。
4.拼接所有的密文块,成为最终的密文结果。

AES加密三要素:

想要搞明白AES算法,首先要搞清楚三个基本概念。
秘钥,填充,模式。

1.秘钥:
对称加密之所以对称就是因为这类算法对明文的加密和解密使用的是同
一个密钥。
AES支持三种长度的密钥:128位,192位,256位

2.填充:

说到填充一定要说一下,AES 分组加密的特性,AES 加密并不是一股脑将明文加密成密文的,而是把明文拆分成一个个独立的明文块,且每个明文块128bit。
假如一段明文长度是196bit,如果按每128bit一个明文块来拆分的话,第二个明文块只有64bit,不足128bit。这时候怎么办呢?就需要对明文块
进行填充(Padding)。

填充的类型:(主要用到的有前三种)
• NoPadding
• PKCS7Padding
• ZeroPadding
• AnsiX923
• Iso10126
• Iso97971

3.模式:

AES的工作模式,体现在把明文块加密成密文块的处理过程中。AES加密算法提供了五种不同的工作模式:
ECB、CBC、CTR、CFB、OFB
模式之间的主题思想是近似的,在处理细节上有一些差别。

ECB模式:

ECB模式(Electronic Codebook Book)是最简单的工作模式,在该模式下,每一个明文块的加密都是完全独立,互不干涉的。
这样的好处是什么呢?
1.简单
2.有利于并行计算
缺点同样也很明显:
相同的明文块经过加密会变成相同的密文块,因此安全性较差。

CBC模式:

CBC模式(Cipher Block Chaining)引入了一个新的概念:初始向量IV(Initialization Vector)。
IV是做什么用的呢?它的作用和MD5的“加盐”有些类似,目的是防止同样的明文块始终加密成同样的密文块。
CBC模式在每一个明文块加密前会让明文块和一个值先做异或操作。
IV作为初始化变量,参与第一个明文块的异或,后续的每一个明文块和它 前一个明文块所加密出的密文块相异或。
这样相同的明文块加密出的密文块显然是不一样的。
CBC模式的好处是什么呢?安全性更高
坏处也很明显:
1.无法并行计算,性能上不如ECB
2.引入初始化向量IV,增加复杂度。

用JavaScript实现AES加密的脚本:

var CryptoJS = require("crypto-js");
var key ="ABC123456789";    //秘钥
var iv = "1234567812345678";  //初始向量IV
function encrypt(text){
    return CryptoJS.AES.encrypt(text,CryptoJS.enc.Utf8.parse(key),{
        iv:CryptoJS.enc.Utf8.parse(iv),
        mode:CryptoJS.mode.CBC,  // CBC模式
        padding:CryptoJS.pad.Pkcs7 // 这里选择的填充类型为Pkcs7 ,还可能是ZeroPadding    NoPadding
    })
}
function decrypt(text){
    var result = CryptoJS.AES.decrypt(text,CryptoJS.enc.Utf8.parse(key),{
        iv:CryptoJS.enc.Utf8.parse(iv),
        mode:CryptoJS.mode.CBC,  //解密的模式必须和加密的模式相同,包括填充类型也需要相同。
        padding:CryptoJS.pad.Pkcs7
    })
    return result.toString(CryptoJS.enc.Utf8)
}
var text="测试AES加密";
var encoded=encrypt(text)
console.log(encoded.toString());
console.log(decrypt(encoded))

ECB模式下的,python代码实现的例子

import base64
from Crypto.Cipher import AES
 
'''
采用AES对称加密算法
'''
# str不是32的倍数那就补足为16的倍数
def add_to_32(value):
    while len(value) % 32 != 0:
        value += '\0'
    return str.encode(value)  # 返回bytes
 
def add_to_16(value):
    while len(value) % 16 != 0:
        value += '\0'
    return str.encode(value)  # 返回bytes
 
#加密方法
def encrypt_oracle(text):
    # 秘钥
    key = 'VW1lMjAxMlRyaXAwMzA5AA=='
    # 待加密文本
    # 初始化加密器
    aes = AES.new(add_to_16(key), AES.MODE_ECB)
    #先进行aes加密
    encrypt_aes = aes.encrypt(add_to_16(text))
    #用base64转成字符串形式
    encrypted_text = str(base64.encodebytes(encrypt_aes), encoding='utf-8')  # 执行加密并转码返回bytes
    print(encrypted_text)
    return encrypted_text
#解密方法
def decrypt_oralce(text):
    # 秘钥
    key = 'VW1lMjAxMlRyaXAwMzA5AA=='
    # 密文
    # 初始化加密器
    aes = AES.new(add_to_16(key), AES.MODE_ECB)
    #优先逆向解密base64成bytes
    base64_decrypted = base64.decodebytes(text.encode(encoding='utf-8'))
    #执行解密密并转码返回str
    decrypted_text = str(aes.decrypt(base64_decrypted),encoding='utf-8').replace('\0','')
    print('decrypted_text',decrypted_text)
    return decrypted_text
 
if __name__ == '__main__':
 
    text = '''{'aaa': '111', 'bbb': '222'}'''
    entrypted_text = encrypt_oracle(text)
 
    decrypt_oralce(entrypted_text)

注意key是16位或者32位的,选择对应的key加密函数。————————————————————————————————————————————