[英]AES-128 encryption in both Python and Java but overflow error,unsigned byte integer is less than minimum
我是 Python 的新手,并将用 Java 编写的AES
加密重写为 Python,但发生了异常:
OverflowError 无符号字节 integer 小于最小值
将 32 字节密钥字符串转换为 16 字节长度的字节数组的算法是固定的,该算法在 function keyToBytes
中实现,我不能使用其他方法,例如使用sha256
到 hash 密钥字符串。
/**
* custom algorithm to convert the string of key to bytes
* @param key
* @return
*/
public static byte[] keyToBytes(String key) {
int length = key.length();//32 bytes
byte[] bArr = new byte[(length / 2)]; //16 bytes length
int a2 = 0;
int b = 30;
int c = 2;
while (true) {
int i = a2 + 2;
if (i > length) {
i = length - 1;
}
int i2 = a2 / 2;
String substring = key.substring(a2, i);
bArr[i2] = (byte) Integer.parseInt(substring, 16);
if (a2 == b) {
break;
}
a2 += c;
}
return bArr;
}
public static String aesEncrypt(byte[]key, String text) {
try {
IvParameterSpec ivParameterSpec = new IvParameterSpec(new byte[16]);
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
Cipher instance = Cipher.getInstance("AES/CBC/PKCS5Padding");
instance.init(1, secretKeySpec, ivParameterSpec);
byte[] bytes = text.getBytes(StandardCharsets.UTF_8);
String result = Base64.getEncoder().encodeToString(instance.doFinal(bytes));
return result;
} catch (NoSuchAlgorithmException e) {
System.out.println(e);
return null;
} catch (InvalidKeyException e) {
System.out.println(e);
return null;
} catch (IllegalBlockSizeException e) {
System.out.println(e);
return null;
} catch (InvalidAlgorithmParameterException e) {
System.out.println(e);
return null;
} catch (BadPaddingException e) {
System.out.println(e);
return null;
} catch (NoSuchPaddingException e) {
System.out.println(e);
return null;
}
}
public static void main(String[] args) {
String key = "7e585aedb1dd597382cf5aaaabfa221d";
byte [] keyInBytes = keyToBytes(key);
System.out.println(Arrays.toString(keyInBytes));
String text = "hello world";
String ret = aesEncrypt(keyInBytes,text);
System.out.println(ret);
}
output
[126, 88, 90, -19, -79, -35, 89, 115, -126, -49, 90, -86, -85, -6, 34, 29]
2gAIBaXGgTfepnHit0A7sg==
import base64
from Crypto.Cipher import AES
from Crypto import Random
import array
BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s : s[0:-ord(s[-1])]
class AESChiper:
def __init__(self, key):
self.bs = 16
self.key = array.array('B',key).tobytes()
def encrypt(self, message):
message = self._pad(message)
iv = b'0'*16
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return base64.b64encode(iv + cipher.encrypt(message)).decode('utf-8')
def _pad(self, s):
return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)
@staticmethod
def _unpad(s):
return s[:-ord(s[len(s)-1:])]
@staticmethod
def keyToBytes(key:str):
keyLength = len(key)
bArr = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
a2 = 0
b = 30
c = 2
while True:
i = a2 +2
if i > keyLength:
i = keyLength - 1
i2 = int(a2/2)
substring = key[a2:i]
num = int(substring,16)
## convert hex string to decimal
## 8 bits integer in 2's complement
## if the value not between -128 - 127 then do substraction
if num > 127:
num = num - 256
bArr[i2] = num
if a2 == b:
break
a2 = a2 + c
return bArr
if __name__ == "__main__":
key = "7e585aedb1dd597382cf5aaaabfa221d"
text = 'hello world'
keyInBytes = AESChiper.keyToBytes(key)
print(keyInBytes)
ciphter = AESChiper(keyInBytes)
ret = ciphter.encrypt(text)
print(ret)
output
[126, 88, 90, -19, -79, -35, 89, 115, -126, -49, 90, -86, -85, -6, 34, 29]
exception has occurred: OverflowError in
self.key = array.array('B',key).tobytes()
unsigned byte integer is less than minimum
最终解决java中的问题
keyInBytes = keyToBytes("7e585aedb1dd597382cf5aaaabfa221d")
output
[126, 88, 90, -19, -79, -35, 89, 115, -126, -49, 90, -86, -85, -6, 34, 29]
对于此数组中的每个值都是十进制形式的有符号字节,范围为 -128 到 + 127 请注意,对于每对两个字符 7e 58 5a ed... 它使用 Interger.parseInt("ed",16) == int('ed',16) == 237 So, the represented 32 bits signed integer in both Python and Java, they are same But In Java, when the integer 237 was converted to byte, it's by default masked to 237 - 256 = -19
if num > 127:
num = num - 256
bArr[i2] = num
在 Python 方面,即使减去 256 并得到掩码值 -19,它仍然是一个 32 位,integer 不是有符号字节。
将 32 位有符号 integer 列表转换为字节形式
key = [126, 88, 90, -19, -79, -35, 89, 115, -126, -49, 90, -86, -85, -6, 34, 29]
keyInBytes = array.array('b',key).tobytes()
aes加密
def encrypt(self, message):
message = self._pad(message)
iv = array.array('b',[0]*16).tobytes()
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return base64.b64encode(cipher.encrypt(message)).decode('utf-8')
output
2gAIBaXGgTfepnHit0A7sg==
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.