Python SHA256 哈希计算
Python SHA256 hash computation
我正在 Python 中编写 SHA256 实现,填充、解析和消息调度似乎工作正常,我的问题在于哈希计算。目前我只是想计算工作变量 '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)
设置依赖于值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))
哈希 class:
@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)
我正在使用 Python 3 顺便说一下。提前致谢。
您需要在此处添加更多掩码以减少溢出位。例如,您的 ROTR
:
def ROTR(x, n, w=32):
return (x >> n) | (x << w - n)
在 w
边界上方保留 x
的所有高位;你想从 w
构建一个掩码并屏蔽掉高位,例如:
def ROTR(x, n, w=32):
return ((x >> n) | (x << w - n)) & ((1 << w) - 1)
任何时候您可能会溢出假定的"register width",都需要类似的掩码。它们还可以替换您正在进行的 % 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
函数(只需要它的三个参数进行有效的模幂运算)。
我正在 Python 中编写 SHA256 实现,填充、解析和消息调度似乎工作正常,我的问题在于哈希计算。目前我只是想计算工作变量 '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)
设置依赖于值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))
哈希 class:
@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)
我正在使用 Python 3 顺便说一下。提前致谢。
您需要在此处添加更多掩码以减少溢出位。例如,您的 ROTR
:
def ROTR(x, n, w=32):
return (x >> n) | (x << w - n)
在 w
边界上方保留 x
的所有高位;你想从 w
构建一个掩码并屏蔽掉高位,例如:
def ROTR(x, n, w=32):
return ((x >> n) | (x << w - n)) & ((1 << w) - 1)
任何时候您可能会溢出假定的"register width",都需要类似的掩码。它们还可以替换您正在进行的 % 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
函数(只需要它的三个参数进行有效的模幂运算)。