在Python中复制此Java哈希

2024-09-29 17:45:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在Python中复制此哈希代码,但这两种语言处理字节的方式不同,并生成非常不同的输出

有人能带我到这里吗

Java代码(原始代码)

public static String hash(String filePath, String salt) {

        String finalHash = null;
        Path path = Paths.get(filePath);

        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            byte[] data = Files.readAllBytes(path);
            byte[] dataDigest = md.digest(data);
            byte[] hashDigest = md.digest(salt.getBytes("ISO-8859-1"));
            byte[] xorBytes = new byte[dataDigest.length];

            for (int i = 0; i < dataDigest.length && i < hashDigest.length; i++) {
                xorBytes[i] = (byte) (dataDigest[i] << 1 ^ hashDigest[i] >> 1);
            }

            finalHash = (new HexBinaryAdapter()).marshal(xorBytes);
        } catch (IOException | NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return finalHash;
    }

Python代码(由我翻译)

def generate_hash(file_path: str, salt: bytes) -> str:
    with open(file_path, 'rb') as f:
        data = f.read()

    hashed_file = sha1(data).digest()
    hashed_salt = sha1(salt).digest()

    xor_bytes = []

    for i in range(len(hashed_file)):
        xor_bytes.append((hashed_file[i] << 1 ^ hashed_salt[i] >> 1))

    return ''.join(map(chr, xor_bytes))  # This is probably not equivalent of HexBinaryAdapter

Tags: path代码datastringbytesbytemdfile
1条回答
网友
1楼 · 发布于 2024-09-29 17:45:13

有以下问题:

  • 在Python代码中错误地实现了shift操作:

    在Python代码中,生成的散列存储在类似字节的对象中,作为0255{a1}之间的无符号整数值列表,例如0xc8 = 11001000 = 200。在Java中,整数存储为有符号值,其中二者的补码用于表示负数[2][3]。如果值0x8c存储在byte变量中,则该值将被解释为-56

    >>-运算符在有符号值和无符号值的二进制级别上产生不同的结果,因为它是一个算术移位运算符,保留符号[4]{a5}[6]。例如:

    signed       -56 >> 1 = 1110 0100 = -28
    unsigned     200 >> 1 = 0110 0100 = 100
    

    另一方面,<<-运算符不会导致上述问题,但会导致无法用字节表示的值。例如:

    signed       -56 << 1 = 1 1001 0000 = -112
    unsigned     200 << 1 = 1 1001 0000 = 400
    

    出于这些原因,在Python代码中

    xor_bytes.append((hashed_file[i] << 1 ^ hashed_salt[i] >> 1))
    

    必须由

    xor_bytes.append((hashed_file[i] << 1 ^ tc(hashed_salt[i]) >> 1) & 0xFF)
    

    在哪里

    def tc(val):
        if val > 127:
            val = val - 256
        return val
    

    确定两个补码表示的负值(或更复杂的运算符,请参见[7]

    按位和&)与0xFF一起使用可确保Python代码中只考虑相关字节,类似于Java代码[5]


  • 有几种方法可以将list/bytes-like对象转换为十六进制字符串(如Java代码),例如使用[8][9]

    bytes(xor_bytes).hex() 
    

    或与[8][10](作为二进制字符串)一起使用

    binascii.b2a_hex(bytes(xor_bytes))
    


  • 在Python代码中,必须考虑salt的编码。由于salt已作为二进制字符串传递(在Java代码中它作为字符串传递),因此必须在调用函数之前执行编码:

    saltStr = 'MySalt'
    salt = saltStr.encode('ISO-8859-1')
    

    为了与Java代码保持函数一致性,salt必须作为字符串传递,编码必须在函数中执行


相关问题 更多 >

    热门问题