AES解密——java到python码转换
AES decryption - java to python code conversion
我正在尝试与银行集成 API。这是银行提供的 Java 示例代码,用于执行 encryption/decryption.
package com.example.restservice;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Base64;
public class EncHelper {
public static String encrypt(String key, String enc) throws Exception {
// TODO Auto-generated method stub
byte[] iv1 = new byte[] { (byte) 0x81, 0x12, 0x39, (byte) 0x9C,
0x07, 0x72, 0x6F, 0x5A, (byte) 0x8E, 0x12, 0x39,
(byte) 0x9C, 0x17, 0x71, 0x61, 0x5A };
StringBuilder sb = new StringBuilder();
for (byte b : iv1) {
sb.append(String.format("%02X", b));
}
System.out.println(sb.toString());
AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv1);
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"),
"AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(1, skeySpec, paramSpec);
byte[] encrypted = cipher.doFinal(enc.getBytes());
String base64encodedString = Base64.getEncoder().encodeToString(encrypted);
// System.out.println(base64encodedString);
return base64encodedString;
}
public static String decrypt(String key, String encrypted) throws Exception {
byte[] keyAsB = key.getBytes("UTF-8");
SecretKeySpec skeySpec = new SecretKeySpec(keyAsB,
"AES");
byte[] iv1 = new byte[] { (byte) 0x81, 0x12, 0x39, (byte) 0x9C,
0x07, 0x72, 0x6F, 0x5A, (byte) 0x8E, 0x12, 0x39,
(byte) 0x9C, 0x17, 0x71, 0x61, 0x5A };
AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv1);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(2, skeySpec, paramSpec);
byte[] encBytes = Base64.getDecoder().decode(encrypted.getBytes());
byte[] original = cipher.doFinal(encBytes);
return new String(original);
}
}
Python 我写的代码是
from Crypto.Cipher import AES
import base64
from Crypto import Random
aes_mode = AES.MODE_CBC
BS = 16
pad = lambda s: bytes(s + (BS - len(s) % BS) * chr(BS - len(s) % BS), 'utf-8')
unpad = lambda s : s[0:-ord(s[-1:])]
class AESCipher:
def __init__( self, key, key_is_hex=True):
self.size = len(key)
if key_is_hex:
self.key = bytes.fromhex(key)
else:
self.key = bytes(key, 'utf-8')
def encrypt( self, raw, padData=True):
raw = pad(raw)
iv = Random.new().read( AES.block_size )
cipher = AES.new(self.key, AES.MODE_CBC, iv )
return base64.b64encode( iv + cipher.encrypt( raw ) )
def decrypt( self, enc ):
enc = base64.b64decode(enc)
iv = enc[:16]
cipher = AES.new(self.key, AES.MODE_CBC, iv )
d = cipher.decrypt( enc[16:])
return unpad(d).decode('utf8')
如果我使用 java 程序并进行加密,我将无法使用我的 python 代码正确解密
这里是java加密代码
EncHelper.encrypt("skeyskeyskeyskey", "ThisTextIsBeingEncryptedHere")
这输出 +CPCZOmJ67d7rwtt/afUaPciCfcUTZtJaFMCctnh2Qs=
cipher1 = AESCipher('skeyskeyskeyskey', False)
x = cipher1.decrypt("+CPCZOmJ67d7rwtt/afUaPciCfcUTZtJaFMCctnh2Qs=")
print(x)
这输出 ncryptedHere
而不是 ThisTextIsBeingEncryptedHere
基本上我在解密时丢失了一些字符。
这里有什么问题?
正在使用的 AES 模式是 'CBC',需要初始化向量 ('iv')。 Java-side银行API使用固定的iv(即UNSECURE)用于加密和解密,但在加密时不与密文连接边.
您的 Python 代码使用的是 RANDOM iv(这很好)但它与密文 (iv|ciphertext) 连接在一起。在解密方面,您获取 iv 并解密其余部分 - 这就是某些文本似乎丢失的原因。
解决方案:对您的PYTHON代码使用相同的静态iv(与Java端相同)并解密完整的密文。
我正在尝试与银行集成 API。这是银行提供的 Java 示例代码,用于执行 encryption/decryption.
package com.example.restservice;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Base64;
public class EncHelper {
public static String encrypt(String key, String enc) throws Exception {
// TODO Auto-generated method stub
byte[] iv1 = new byte[] { (byte) 0x81, 0x12, 0x39, (byte) 0x9C,
0x07, 0x72, 0x6F, 0x5A, (byte) 0x8E, 0x12, 0x39,
(byte) 0x9C, 0x17, 0x71, 0x61, 0x5A };
StringBuilder sb = new StringBuilder();
for (byte b : iv1) {
sb.append(String.format("%02X", b));
}
System.out.println(sb.toString());
AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv1);
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"),
"AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(1, skeySpec, paramSpec);
byte[] encrypted = cipher.doFinal(enc.getBytes());
String base64encodedString = Base64.getEncoder().encodeToString(encrypted);
// System.out.println(base64encodedString);
return base64encodedString;
}
public static String decrypt(String key, String encrypted) throws Exception {
byte[] keyAsB = key.getBytes("UTF-8");
SecretKeySpec skeySpec = new SecretKeySpec(keyAsB,
"AES");
byte[] iv1 = new byte[] { (byte) 0x81, 0x12, 0x39, (byte) 0x9C,
0x07, 0x72, 0x6F, 0x5A, (byte) 0x8E, 0x12, 0x39,
(byte) 0x9C, 0x17, 0x71, 0x61, 0x5A };
AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv1);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(2, skeySpec, paramSpec);
byte[] encBytes = Base64.getDecoder().decode(encrypted.getBytes());
byte[] original = cipher.doFinal(encBytes);
return new String(original);
}
}
Python 我写的代码是
from Crypto.Cipher import AES
import base64
from Crypto import Random
aes_mode = AES.MODE_CBC
BS = 16
pad = lambda s: bytes(s + (BS - len(s) % BS) * chr(BS - len(s) % BS), 'utf-8')
unpad = lambda s : s[0:-ord(s[-1:])]
class AESCipher:
def __init__( self, key, key_is_hex=True):
self.size = len(key)
if key_is_hex:
self.key = bytes.fromhex(key)
else:
self.key = bytes(key, 'utf-8')
def encrypt( self, raw, padData=True):
raw = pad(raw)
iv = Random.new().read( AES.block_size )
cipher = AES.new(self.key, AES.MODE_CBC, iv )
return base64.b64encode( iv + cipher.encrypt( raw ) )
def decrypt( self, enc ):
enc = base64.b64decode(enc)
iv = enc[:16]
cipher = AES.new(self.key, AES.MODE_CBC, iv )
d = cipher.decrypt( enc[16:])
return unpad(d).decode('utf8')
如果我使用 java 程序并进行加密,我将无法使用我的 python 代码正确解密
这里是java加密代码
EncHelper.encrypt("skeyskeyskeyskey", "ThisTextIsBeingEncryptedHere")
这输出 +CPCZOmJ67d7rwtt/afUaPciCfcUTZtJaFMCctnh2Qs=
cipher1 = AESCipher('skeyskeyskeyskey', False)
x = cipher1.decrypt("+CPCZOmJ67d7rwtt/afUaPciCfcUTZtJaFMCctnh2Qs=")
print(x)
这输出 ncryptedHere
而不是 ThisTextIsBeingEncryptedHere
基本上我在解密时丢失了一些字符。
这里有什么问题?
正在使用的 AES 模式是 'CBC',需要初始化向量 ('iv')。 Java-side银行API使用固定的iv(即UNSECURE)用于加密和解密,但在加密时不与密文连接边.
您的 Python 代码使用的是 RANDOM iv(这很好)但它与密文 (iv|ciphertext) 连接在一起。在解密方面,您获取 iv 并解密其余部分 - 这就是某些文本似乎丢失的原因。
解决方案:对您的PYTHON代码使用相同的静态iv(与Java端相同)并解密完整的密文。