从哈希字符串,java与python

时间:2017-12-06 14:45:47

标签: java python hash byte

我有将纯Java Curve25519函数转换为Python等效的问题,具体问题与将哈希字符串转换为字节等效的摘要函数有关,java实现:

数据示例:

sP ="这是用于测试目的的秘密密码短语样本"

/**
 * Calculate the SHA-256 hash of a string
 *
 * @param       input           Data to be hashed
 * @return                      The hash digest
 */
public static byte[] singleDigest(String input) {
    byte[] bytes;
    try {
        bytes = singleDigest(input.getBytes("UTF-8"));
        System.out.println("bytes"+bytes);
        System.out.println("before singleDigest"+input);
    } catch (UnsupportedEncodingException exc) {
        bytes = null;
    }
    return bytes;
}

/**
 * Calculate the SHA-256 hash of a byte array
 *
 * @param       input           Data to be hashed
 * @return                      The hash digest
 */
public static byte[] singleDigest(byte[] input) {
    byte[] bytes;
    synchronized (digest) {
        digest.reset();
        bytes = digest.digest(input);

        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            System.out.println(bytes[i]);
            sb.append(String.format("%02x", bytes[i] & 0xFF));
        }
        System.out.println(sb.toString());
    }
    return bytes;
}

生成此字节输出:

byteOutput:82,-57,124,58,-105,76,123,3,119,-21,121,71,-54,73,-75,54,31,-33,-49, -68,-16,-19,125,-61,-116,-82,96,50,-35,-119,-28,25

有正数和负数,在python端,我使用此函数将散列字符串转换为byte:

secret = sha256(sP.encode('utf-8')).hexdigest()
sct = ParseHexString(secret).getData()

class ParseHexString(object):

    def __init__(self, hex):
        """

        """
        if not isinstance(hex, str):
            return None
        else:

            self.hex = hex
            self.listOfByte = None

        self.run()

    def run(self):

        if len(self.hex)&0x01 == 1:
            return None

        lbytes = []
        for i in range(0, len(self.hex), 2):
            op1, op2 = self.hex[i:i + 2]
            oop1 = ord(op1)
            oop2 = ord(op2)

            char1 = oop1 - 0x57 if oop1 > 0x60 else oop1 - 0x30
            char2 = oop2 - 0x57 if oop2 > 0x60 else oop2 - 0x30

            if (char1 < 0 or char2 < 0 or char1 > 15 or char2 > 15):
                print("Invalid hex number ",op1,op2)

            lbytes.append(((char1 << 4) + char2))

        self.listOfByte = lbytes

    def getData(self):
        return self.listOfByte

由于bytearray(0 - 256)的内部表示,以及某些散列字符串的输出,我在这里使用了列表而不是可变的bytearray 是不同的,只是正整数:

82,199,124,58,151,76,123,3,119,235,121,71,202,73,181,54,31,217,207,188,240,237,125,196 ,140,174,96,50,221,137,228,25

我注意到(256 - JavaByteOutput [x] == PythonByteOtput [x])当JavaByteOutput是负数时,问题是,我如何修改我的ParseHexString类以获得等效的正/负输出,我想要纯粹的python代码,没有库。

感谢您的回答。 问候 亚历

2 个答案:

答案 0 :(得分:1)

这里的重点:Java只知道签名类型。

这意味着:虽然Java字节也是大约8位,但范围是-128到127.无符号字节从0到255.

这就是全部。唯一真正重要的是你对价值观的处理方式保持一致。有关此主题的进一步想法,请参阅here

答案 1 :(得分:1)

在Python中,a % b始终返回一个值与b相同的值,介于0(包括)和b之间(不包括)。在这种情况下,b为256。

所以要将值移到范围[-128,128],每个值加128,取模数基数256然后减去128:

x = [82, 199, 124, 58, 151, 76, 123, 3, 119, 235, 121, 71, 202, 73, 181, 54, 31, 217, 207, 188, 240, 237, 125, 196, 140, 174, 96, 50, 221, 137, 228, 25]

y = [(xi + 128) % 256 - 128 for xi in x]
# [82, -57, 124, 58, -105, 76, 123, 3, 119, -21, 121, 71, -54, 73, -75, 54, 31, -39, -49, -68, -16, -19, 125, -60, -116, -82, 96, 50, -35, -119, -28, 25]

因此,在ParseHexString.run中定义:

self.listOfByte = [(xi + 128) % 256 - 128 for xi in lbytes]

如果NumPy是一个选项,你可以简单地view无符号的1字节整数作为带符号的1字节整数:

import numpy as np
x = np.array([82, 199, 124, 58, 151, 76, 123, 3, 119, 235, 121, 71, 202, 73, 181, 54, 31, 217, 207, 188, 240, 237, 125, 196, 140, 174, 96, 50, 221, 137, 228, 25], dtype='uint8')

x.view('i1')
# array([  82,  -57,  124,   58, -105,   76,  123,    3,  119,  -21,  121,
#          71,  -54,   73,  -75,   54,   31,  -39,  -49,  -68,  -16,  -19,
#         125,  -60, -116,  -82,   96,   50,  -35, -119,  -28,   25], dtype=int8)