【问题标题】:AES-128 encryption in both Python and Java but overflow error,unsigned byte integer is less than minimumPython 和 Java 中的 AES-128 加密但溢出错误,无符号字节整数小于最小值
【发布时间】:2019-10-01 14:14:28
【问题描述】:

我是 Python 新手,将用 Java 编写的 AES 加密重写为 Python,但得到发生异常:

OverflowError 无符号字节整数小于最小值

将 32 字节密钥字符串转换为长度为 16 字节的字节数组的算法是固定的,在函数 keyToBytes 中实现,我不能使用其他方法,例如使用 sha256 到哈希密钥字符串。

/**
 * 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);
}

输出

[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)

输出

[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 python aes


    【解决方案1】:

    最终解决问题 在java中

    keyInBytes = keyToBytes("7e585aedb1dd597382cf5aaaabfa221d")
    

    输出

    [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 转换 因此,Python 和 Java 中表示的 32 位有符号整数,它们是相同的 但是在 Java 中,当整数 237 被转换为字节时,它默认被屏蔽为 237 - 256 = -19

     if num > 127:      
        num = num - 256
    bArr[i2] = num 
    

    在 Python 端,即使减去 256 并得到掩码值 -19,它仍然是一个 32 位的有符号整数而不是有符号字节。

    将 32 位有符号整数列表转换为字节形式

    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')
    

    输出

    2gAIBaXGgTfepnHit0A7sg==
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-18
      • 2015-10-24
      • 2020-12-03
      • 1970-01-01
      • 2013-06-09
      相关资源
      最近更新 更多