Python SHA256 вычисление хеша - PullRequest
1 голос
/ 25 апреля 2019

Я пишу реализацию SHA256 на Python, кажется, что заполнение, анализ и расписание сообщений работают нормально, моя проблема заключается в вычислении хеша.В настоящее время я просто пытаюсь вычислить рабочую переменную 'a'.Это значение, которое я получаю (в шестнадцатеричном формате)

5d6aebe0

Ожидаемый результат, согласно this :

5D6AEBCD

Вот мой код:

Установите рабочие переменные в константы, указанные в FIPS-180

a = int('6a09e667', 16)
b = int('bb67ae85', 16)
c = int('3c6ef372', 16)
d = int('a54ff53a', 16)
e = int('510e527f', 16)
f = int('9b05688c', 16)
g = int('1f83d9ab', 16)
h = int('5be0cd19', 16)

Setдве важные переменные, которые зависят от значения t:

W = int('61626380', 16)
K = int('428a2f98', 16)

Из псевдокода в wikipedia :

S1 = hash.ROTR(e, 6) ^ hash.ROTR(e, 11) ^ hash.ROTR(e, 25)
ch = (e & f) ^ ((~e) & g)#((e1) & g)
temp1 = (h + S1 + ch + K + W) % math.pow(2, 32)
S0 = hash.ROTR(a, 2) ^ hash.ROTR(a, 13) ^ hash.ROTR(a, 22)
maj = (a & b) ^ (a & c) ^ (b & c)
temp2 = (S0 + maj) % math.pow(2, 32)
a = int((temp1 + temp2) % math.pow(2, 32))

Функция ROTR:

@staticmethod
def ROTR(x, n, w=32):
    return (x >> n) | (x << w - n)

Или разделить на функции, как указано в FIPS-180 (Производит тот же вывод)

T1 = int((h + hash.SIGMA1(e) + hash.Ch(e, f, g) + hash.K[t] + W) % math.pow(2, 32))
T2 = int((hash.SIGMA0(a) + hash.Maj(a, b, c)) % math.pow(2, 32))
a = int((T1 + T2) % math.pow(2, 32))

Класс хеширования:

@staticmethod
def ROTR(x, n, w=32):
    return (x >> n) | (x << w - n)
def SIGMA0(x):
    return hash.ROTR(x, 2) ^ hash.ROTR(x, 13) ^ hash.ROTR(x, 22)
def SIGMA1(x):
    return hash.ROTR(x, 6) ^ hash.ROTR(x, 11) ^ hash.ROTR(x, 25)
def Ch(x, y, z):
    return (x & y) ^ (~x & z)
def Maj(x, y, z):
    return (x & y) ^ (x & z) ^ (y & z)

I 'м, используя Python 3, кстати.Заранее спасибо.

1 Ответ

3 голосов
/ 25 апреля 2019

Вам нужно добавить гораздо больше маскировки, чтобы сократить переполнение битов.Например, ваш ROTR:

def ROTR(x, n, w=32):
    return (x >> n) | (x << w - n)

оставляет все старшие биты x без изменений выше границы w;Вы хотите создать маску из w и маскировать старшие биты, например:

def ROTR(x, n, w=32):
    return ((x >> n) | (x << w - n)) & ((1 << w) - 1)

Подобные маски необходимы каждый раз, когда вы могли переполнить предполагаемую «ширину регистра».Они также могут заменить подверженное ошибкам использование % math.pow(2, 32), которое у вас происходит, изменяя:

int((temp1 + temp2) % math.pow(2, 32))

на:

(temp1 + temp2) & ((1 << 32) - 1)

или эквивалентно:

(temp1 + temp2) % 2 ** 32

Это также должно происходить для побитового отрицания, когда переполнение не столь очевидно: Python int имеет бесконечную точность, а побитовое отрицание неотрицательного значения приводит к отрицательному значению, фактически добавляя бесконечное 1биты слева (в поведении дополнения псевдо-двух язык определяет язык).Так что ~x должно стать ~x & ((1 << 32) - 1) или подобным, чтобы вернуть его к положительному значению, содержащему только младшие 32 бита.

Это должно быть сделано глобально (так что temp1 и temp2 на самом делеint, а не float значений при их вычислении).В общем, math.pow совершенно бесполезен;Вы либо хотите использовать оператор ** (который не приводит к float и выполняется более эффективно), либо встроенную функцию pow (которая необходима только для трех аргументов для эффективного модульного возведения в степень).

...