在Java中,下面的代码可以对任意长度的字符串进行加密,并顺利解密。
Java代码。
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class AesEncryption {
public static void main(String[] args) throws NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchPaddingException {
AesEncryption ae = new AesEncryption();
byte[] secret = ae.encrypt("Hello World!");
for (byte b : secret)
System.out.print(String.format("%d, ", b));
System.out.print("\n");
System.out.print(String.format("%s\n", ae.decrypt(secret)));
}
private final IvParameterSpec iv;
private final SecretKeySpec keySpec;
public AesEncryption() throws NoSuchAlgorithmException {
byte[] key = "thisisasecretkey".getBytes(StandardCharsets.UTF_8);
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(key);
this.iv = new IvParameterSpec(md.digest());
this.keySpec = new SecretKeySpec(key, "AES");
}
public byte[] encrypt(String content) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, this.keySpec, this.iv);
return cipher.doFinal(content.getBytes());
}
public String decrypt(byte[] secret) throws InvalidAlgorithmParameterException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, this.keySpec, this.iv);
return new String(cipher.doFinal(secret));
}
}
Python代码:
import array
import hashlib
from Crypto.Cipher import AES
Class AesEncryption:
def __init__(self):
key = 'thisisasecretkey'.encode('UTF-8')
md = hashlib.md5()
md.update(key)
iv = md.digest()
self.__cryptor = AES.new(key, AES.MODE_CFB, iv, segment_size=128)
def encrypt(self, content):
return self.__cryptor.encrypt(AesEncryption.r_pad(content.encode('UTF-8')))[:len(content.encode('UTF-8'))]
def decrypt(self, secret):
return self.__cryptor.decrypt(secret)
@staticmethod
def r_pad(payload):
length = 16 - (len(payload) % 16)
return payload + (chr(length) * length).encode('UTF-8')
if __name__ == '__main__':
secretstr = array.array('B', [-108, 20, -91, -103, 13, 59, 94, -51, 17, -104, -30, -83]).tostring()
ae = AesEncryption()
print(ae.decrypt(secretstr).decode('UTF-8'))
但是当我把Java代码产生的秘密字节数组传给PyCrypto时 解密失败了 Python代码使用的是 AES.MODE_CFB
和 segment_size = 128
来匹配Java中的AES模式,但纯文本的长度不符合16字节块的要求。改变 segment_size
也不会产生同样的结果。所以我想 NoPadding
可能是问题所在。的算法是什么?AES/CFB/NoPadding
模式在Java中的应用?它与PyCrypto中使用的算法又有什么不同?谢谢。