AES加密和解密

阅读更多

本文重点在于如何在JAVA和Python中使用AES,以及相关的重要概念,而不是专门讲AES算法原理。

 

AES作为一个块加密算法 [block cipher],每次加密的明文大小固定为128bit,所以明文比较长的时候需要先分组再加密然后整合,这个过程中就会出现两个重要的因素:模式 和 填充方式。

 

 

1. 模式

分组密码工作模式,常用的包含ECB,CBC,OFB,CFB和CTR,详见 Block_cipher_mode_of_operation

 

1)ECB模式作为最简单的工作模式,直接将明文分组,每组分别加密,每个分组独立且前后文无关。
AES加密和解密_第1张图片
 

 


 2)CBC模式,将明文分组与前一个密文分组进行XOR运算,然后再进行加密。每个分组的加解密都依赖于前一个分组。而第一个分组没有前一个分组,因此需要一个初始化向量 IV。


AES加密和解密_第2张图片
 

3)其他模式不再详述,ECB模式因为其简洁性(不需要额外的初始化向量IV)仍然被广泛使用,但是已经被认为是不安全的工作模式,具体原因见上文引用的wiki,为了保证传输信息的安全性,CBC目前是个推荐的选择,而且建议每次加密使用不同的 Key 和 IV 。

 

 2. 填充方式

鉴于明文长度随机,分组之后,最后一个组往往需要补齐。

填充方式很多,详见 Padding (cryptography)

 

以下是在Java中常用的 PKCS7 它是基于字节的填充方案 [Byte padding],其特点为:

1)填充的都是相同的字节

2)该字节的值,就是要填充的字节的个数

 

举例,

假定加密块长度要求为 8 byte,数据长度为 1 byte,那么需要填充7个byte,每个byte值为0x07

 

数据: FF

PKCS7 填充: FF 07 07 07 07 07 07 07

 

如果明文正好被整除了,需要增加一个完整的填充块,方便解密时判断最后一个字节是消息字节还是填充字节。

 

PKCS7支持长度小于256字节的加密块,而Java中经常出现的是PKCS5,PKCS5可以认为是PKCS7的一个特例,只处理8字节的加密块,理论上来说PKCS5是不适用于AES加密的,但是JCA (Java Cryptography Architecture) 标准中却只有PKCS5,这个可以认为是历史原因,实际上在加密块大于8字节时,PKCS5内部就用PKCS7方式填充。

 

3. 关于秘钥Key,长度可以是 128, 192 和 256 bits(注意加密块始终是 128 bits),Java默认只支持 128 bits,如果需要支持更长的key,需要添加扩展包 Java Cryptography Extension (JCE)。

 

4. Java中加密和解密的流程

创建Cipher实例 -> 用key初始化 -> 执行加解密,分组的操作只需要在创建实例时指定模式即可,不需要手动处理

 

以 CBC 模式加密为例

public byte[] encryptCBCMode(String key, String vector, String plainText) throws
        NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException,
        InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
    IvParameterSpec iv = new IvParameterSpec(vector.getBytes(StandardCharsets.UTF_8));
    SecretKey keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
    cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);

    return cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
}

 

解密时将 Cipher.ENCRYPT_MODE 替换为 Cipher.DECRYPT_MODE。

 

5. Python中加密和解密的流程

使用 cryptography 库,和Java流程类似,同样以 CBC 模式为例

def encrypt_cbc_mode(key, iv, plain_bytes):
	backend = default_backend()
	cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)
	encryptor = cipher.encryptor()
	# add pkcs#7 padding before encrypt
	padder = padding.PKCS7(128).padder()
	padded_data = padder.update(plain_bytes) + padder.finalize()
	return encryptor.update(padded_data) + encryptor.finalize()

 

更多代码可以参考 Information-Security

 

 

 

 

  • AES加密和解密_第3张图片
  • 大小: 77.5 KB
  • AES加密和解密_第4张图片
  • 大小: 94.6 KB
  • 查看图片附件

你可能感兴趣的:(AES,ECB,CBC,PKCS)