[英]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.