[英]AES/CBC/PKCS5Padding encrypt in java decrypt in python goes wrong
[英]AES/CBC/PKCS5Padding from java to python
我的任務是將這個 java 代碼轉換為 python。 而且我無法在 python 中獲得與 java 相同的結果。 我需要幫助來轉換此代碼。 非常感謝任何提示。
Java代碼
import org.apache.commons.lang.RandomStringUtils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import java.util.Base64;
public String decryptTextusingAES(String text, String kek) throws Exception{
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] keyBytes= new byte[16];
byte[] b= kek.getBytes("UTF-8");
int len= b.length;
if (len> keyBytes.length) len = keyBytes.length;
System.arraycopy(b, 0, keyBytes, 0, len);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
cipher.init(Cipher.DECRYPT_MODE,keySpec,ivSpec);
BASE64Decoder decoder = new BASE64Decoder();
byte [] results = cipher.doFinal(decoder.decodeBuffer(text));
return new String(results,"UTF-8");
}
Python代碼
from Crypto.Cipher import AES
from base64 import b64decode
BLOCK_SIZE = AES.block_size
pad = lambda s: s + (BLOCK_SIZE - len(s.encode()) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s.encode()) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]
class AESCipher:
def __init__(self, secretkey: str):
self.key = secretkey # key
self.iv = secretkey[0:16] # offset
def decrypt(self, encrypted_text):
encrypted_text = b64decode(encrypted_text)
cipher = AES.new(key=self.key.encode(), mode=AES.MODE_CBC, IV=self.iv.encode())
decrypted_text = cipher.decrypt(encrypted_text)
print("unpad : ",decrypted_text)
return unpad(decrypted_text).decode('utf-8')
if __name__ == '__main__':
# message to encrypt
message = "mxoqPaEdpujwTOmeKGomHgXAgdVc0Ca7cm0Qqjm2WMQ="
secret_key = "935554679694777871163316"
AES_pkcs5_obj = AESCipher(secret_key)
decrypted_message = AES_pkcs5_obj.decrypt(message)
print("Decrypted : ",decrypted_message)
Python 代碼不斷給出這個 output:
unpad : b'rt\xfb\x98o\x8f.\t\xb1d0tx-i\x88\xd1\xfdV\xef\xece\xf2\x8a\xf7\xf8\x00O\xdb\x8c\xcb\xf2'
Decrypted :
但它應該在解密時給出這個:284174634921775587013963
這是加密字符串“mxoqPaEdpujwTOmeKGomHgXAgdVc0Ca7cm0Qqjm2WMQ=”
這是應該使用“935554679694777871163316”來解密上述字符串的密鑰。
您的密鑰似乎只有 192 位(24 個字符)...您依賴於自動檢測正確的 AES 算法。 據我所知,此配置中的 python 只有 AES256 可用,您需要 256 位密鑰(32 個字符)。 算法試圖拉伸密鑰以適應 AES256 的使用也可能存在問題,這可能在語言/框架之間以不同的方式完成。
看看那些參考實現,它們是相互兼容的。 您可以從那里開始 go 並繼續您的開發。
Java:
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
private static final IvParameterSpec IV = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
void testEncryption() throws GeneralSecurityException {
final byte[] key = "AnyRandomInsecure256bitLongKeyXX".getBytes(StandardCharsets.US_ASCII);
final SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
final String encrypted = encrypt("data", keySpec, IV);
final String decrypted = decrypt(encrypted, keySpec, IV);
System.out.printf("%s <-> %s", encrypted, decrypted);
}
String encrypt(final String data, final SecretKeySpec keySpec, final IvParameterSpec ivSpec)
throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes(StandardCharsets.UTF_8)));
}
String decrypt(final String cipherText, final SecretKeySpec keySpec, final IvParameterSpec ivSpec)
throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
return new String(cipher.doFinal(Base64.getDecoder().decode(cipherText)), StandardCharsets.UTF_8);
}
Python:
from Crypto.Cipher import AES
from base64 import b64decode, b64encode
IV = bytes([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
BLOCK_SIZE = 16
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]
def encrypt(plain_text, key):
plain_text = pad(plain_text)
cipher = AES.new(key, AES.MODE_CBC, IV)
return b64encode(cipher.encrypt(plain_text))
def decrypt(cipher_text, key):
cipher_text = b64decode(cipher_text)
cipher = AES.new(key, AES.MODE_CBC, IV)
return unpad(cipher.decrypt(cipher_text))
if __name__ == '__main__':
key = "AnyRandomInsecure256bitLongKeyXX".encode()
encrypted = encrypt("data", key)
decrypted = decrypt(encrypted, key)
print(f"{encrypted} <-> {decrypted}")
生成隨機 IV 然后將其添加到您生成的密文的前綴也是最佳實踐。 看看這里
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.