什么是AES
Note:
- 网上有很多实现代码但是鱼龙混杂,笔者摸索了半天,实现了AES加密文本跨平台的安全传输
- 这里以Python和Java为例,方案采用AES128+Base64.这里以Python和Java为例,方案采用AES128+Base64。
AES的算法本身是跨平台的,只不过以下这些要素决定了跨平台不是那么简单:
- 加密模式: ECB,CBC,CFB,OFB,CTR,XTS…
- 密钥长度: 128, 256
- iv向量(init vector): 需要与密钥同时设置
- padding: NoPadding,ZeroPadding,PKCS5Padding,ISO10126Padding,ANSI X.923,SSL3Padding…
- 密钥: 用于加解密的key
参见: Github aes-cross
Java的实现
Note:
- Base64 需要第三方jar包 http://www.java2s.com/Code/Jar/a/Downloadaxis103jar.htm
- 注意padding与unpadding的方法
import java.util.Arrays;
import java.lang.Throwable;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.axis.encoding.Base64;
public class aesEncryption {
private static final String CYPHER_MODE = "AES/CBC/NoPadding";
public static byte[] encrypt(byte[] key, byte[] initVector, byte[] value) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector);
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance(CYPHER_MODE);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
int blockSize = cipher.getBlockSize();
byte[] plaintext = padding(value, blockSize);
return cipher.doFinal(plaintext);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static byte[] decrypt(byte[] key, byte[] initVector, byte[] encrypted) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector);
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance(CYPHER_MODE);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
return unpadding(cipher.doFinal(encrypted));
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
private static byte[] padding(byte[] value, int blockSize) {
int plaintextLength = value.length;
if (plaintextLength % blockSize != 0) {
plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
}
byte[] plaintext = new byte[plaintextLength];
System.arraycopy(value, 0, plaintext, 0, value.length);
return plaintext;
}
private static byte[] unpadding(byte[] bytes) {
int i = bytes.length - 1;
while (i >= 0 && bytes[i] == 0)
{
--i;
}
return Arrays.copyOf(bytes, i + 1);
}
public static void main(String[] args) {
try {
byte[] key = "keyskeyskeyskeys".getBytes();
byte[] iv = "keyskeyskeyskeys".getBytes();
byte[] content = "123".getBytes("utf-8");
byte[] cyphertext = encrypt(key, iv, content);
String b64 = Base64.encode(cyphertext);
System.out.println(b64);
byte[] de_b64 = decrypt(key, iv, Base64.decode(b64));
String plaintext = new String(de_b64);
System.out.println(plaintext);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
Python的实现
Note:
- key 和 iv 值要与之前的Java代码里分别
- 注意padding与unpadding的方法
from Crypto.Cipher import AES
import base64
class AESEncrypt:
def __init__(self, key, iv):
self.key = key
self.iv = iv
self.mode = AES.MODE_CBC
def encrypt(self, text):
cryptor = AES.new(self.key, self.mode, self.key)
length = AES.block_size
text_pad = self.padding(length, text)
ciphertext = cryptor.encrypt(text_pad)
cryptedStr = str(base64.b64encode(ciphertext), encoding='utf-8')
return cryptedStr
def padding(self, length, text):
count = len(text.encode('utf-8'))
if count % length != 0:
add = length - (count % length)
else:
add = 0
text1 = text + ('\0' * add)
return text1
def decrypt(self, text):
base_text = base64.b64decode(text)
cryptor = AES.new(self.key, self.mode, self.key)
plain_text = cryptor.decrypt(base_text)
ne = plain_text.decode('utf-8').rstrip('\0')
return ne
if __name__ == '__main__':
aes_encrypt = AESEncrypt(key='keyskeyskeyskeys', iv="keyskeyskeyskeys") # 初始化key和IV
text = '123'
sign_data = aes_encrypt.encrypt(text)
print(sign_data)
data = aes_encrypt.decrypt(sign_data)
print(data)
结果
明文:123
密文:nUY/Ft988QAYJYbKh2pxyw==
本文介绍了一种使用AES128+Base64实现的跨平台加密方案,详细展示了在Java和Python中如何进行AES加密和解密的过程。通过对比不同加密模式、密钥长度和填充方式,解释了跨平台实现的复杂性。
1675





