簡體   English   中英

Python 和 Java 中的 AES-128 加密但溢出錯誤,無符號字節 integer 小於最小值

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM