Algorithm 复杂度为O(n)的反向SHA-256 sigma0函数? 介绍
作为SHA-256散列算法的一部分,有一个函数通常被称为Algorithm 复杂度为O(n)的反向SHA-256 sigma0函数? 介绍,algorithm,hash,cryptography,reverse-engineering,Algorithm,Hash,Cryptography,Reverse Engineering,作为SHA-256散列算法的一部分,有一个函数通常被称为σ1,或sigma0,以方便使用。基本上,它以X作为输入,其中X是32位无符号值。然后像这样转换它: ROTATE_RIGHT(X, 7) ^ ROTATE_RIGHT(X, 18) ^ SHIFT_RIGHT(X, 3) Input: 00000000100110101000111011101001 Output: 01110001101010000010010011100110 0: 0 0 0 0 0 0 0 0 0 0 0
σ1
,或sigma0
,以方便使用。基本上,它以X作为输入,其中X是32位无符号值。然后像这样转换它:
ROTATE_RIGHT(X, 7) ^ ROTATE_RIGHT(X, 18) ^ SHIFT_RIGHT(X, 3)
Input: 00000000100110101000111011101001
Output: 01110001101010000010010011100110
0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 | 0
1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 | 1
2: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 | 1
3: 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 | 1
4: 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 | 0
5: 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 | 0
6: 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 | 0
7: 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 | 1
8: 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 | 1
9: 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 | 0
10: 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 | 1
11: 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 | 0
12: 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 | 1
13: 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 | 0
14: 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 | 0
15: 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 | 0
16: 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 | 0
17: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 | 0
18: 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1
19: 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 0
20: 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 0
21: 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1
22: 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 | 0
23: 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 | 0
24: 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 | 1
25: 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 | 1
26: 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 | 1
27: 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 | 0
28: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 | 0
29: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 | 1
30: 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 | 1
31: 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 | 0
如果您需要,请稍作解释:
- 向右旋转(X,Y)-将X的位向右旋转Y
- 向右移位(X,Y)-将X的位向右移位Y,因此结果的前Y位始终为0
def向右旋转(x,y):
返回(((x&0xffffffff)>>(y&31))|(x>n
def sigma0(x):
返回向右旋转(x,7)^向右旋转(x,18)^向右移位(x,3)
反向函数
我开始怀疑这个东西是否是可逆的,令我惊讶的是,编写一个函数用不了多久,通过给定sigma0
的输出,返回该函数的输入,或者简单地说,反转sigma0
函数。我不会把代码放在这里,因为它是在Node.js中编写的,并且由于更复杂的通过掩码搜索特定的sigma0
输入,但我想给你一个我如何解决它的基本想法,也许你可以给我一些关于如何实现我需要的新想法
我的解决方案很简单,但它也是递归的。我们知道每个输出的位都是两个或三个输入位异或运算的结果。所以我制作了一个依赖表,这样我就可以看到输出的位是如何受到输入位的影响的:
I: 00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
R7 25,26,27,28,29,30,31,00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24
R18 14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,00,01,02,03,04,05,06,07,08,09,10,11,12,13
S3 zz,zz,zz,00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28
---------------------------------------------------------------------------------------------------
O: 00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
这是关于什么的?比如说,在输出的第一位我们有1。为了方便起见,我将把它写成O[0]
,O[1]
,…O[31]
,所以O[x]
是输出的第(x+1)位。对于输入,同样的,标记为I
因此,O[0]==1
。在上表中,我们看到O[0]
是I[25]
和I[14]
的异或运算的结果。这意味着这些输入的位中必须有一位且只有一位是1。因此,在这一点上,我们可以说,我们可以为输入创建两个合适的掩码:
##############0#########1#######
##############1#########0#######
这些掩码是解决方案的关键,至少是挖掘的关键。#
表示任何值(0或1).当我们创建掩码时,我们为下一位调用递归函数,但保留掩码。如果我们没有适合上一个掩码的可能掩码,则上一个掩码没有解决方案,如果我们达到32位,则保证掩码中没有锐化,这就是答案
首先,我需要告诉你这是可行的。但是在Node.js上,它计算每一个值大约100毫秒,我不知道递归算法最复杂的是什么,因为它很难测量。它不能满足我,我绞尽脑汁试图解决这个O(n)
问题
我想知道是否有可能编写一个函数,在O(n)的复杂度内反转sigma0
,其中n
是输入/输出中的位数,它等于32,没有递归、掩码或树,简单而快速
我还没有为我的陈述得出任何数学证明,但是我测试了许多不同的值,我可以自信地宣称输入值的数量等于这个函数的输出值的数量,并且两者都等于2^32-1
。换句话说,对于每个输出,sigma0
功能
这让我想到,原来的函数产生了复杂度为O(n)的结果,这意味着反向函数必须有一个同样适用于O(n)的解 如果你从数学上证明这是不可能的,我也会接受这个答案,但我没有发现任何迹象表明这项任务是不可能的 消耗资源的变通办法 如果我有16gb的可用内存,我可以预先计算所有可能的值到文件中,然后将其作为一个巨大的数组加载到ram中。但这不是一个解决方案,因为还有其他3个类似的函数,要实现这一点,我需要64gb的ram,对于这个简单的任务来说,这太昂贵了 UPD:高斯消去法 多亏了Artjom B.的评论,我找到了一种通过高斯消去法求解XOR方程的好方法。目前我正在尝试求解一个矩阵,如下所示:
ROTATE_RIGHT(X, 7) ^ ROTATE_RIGHT(X, 18) ^ SHIFT_RIGHT(X, 3)
Input: 00000000100110101000111011101001
Output: 01110001101010000010010011100110
0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 | 0
1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 | 1
2: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 | 1
3: 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 | 1
4: 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 | 0
5: 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 | 0
6: 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 | 0
7: 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 | 1
8: 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 | 1
9: 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 | 0
10: 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 | 1
11: 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 | 0
12: 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 | 1
13: 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 | 0
14: 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 | 0
15: 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 | 0
16: 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 | 0
17: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 | 0
18: 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1
19: 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 0
20: 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 0
21: 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 | 1
22: 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 | 0
23: 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 | 0
24: 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 | 1
25: 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 | 1
26: 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 | 1
27: 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 | 0
28: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 | 0
29: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 | 1
30: 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 | 1
31: 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 | 0
发布了矩阵,这样您就可以看到它的外观,而不必浪费时间自己创建它。一旦我解决了问题,我会更新我的问题。如果我们将
sigma0
视为GF(2)32向量上的函数,您会注意到它是线性的。GF(2)32中的加法只是二进制异或:
sigma0(235^352124)
2045075788
>>>sigma0(235)^sigma0(352124)
2045075788
这意味着如果我们可以找到sigma0(x0)=0b1
,sigma0(x1)=0b10
,等等,我们可以很容易地一点一点地反转任何东西。我们可以很容易地用z3
找到这些反转:
导入z3
def z3_sigma0(x):
返回z3.RotateRight(x,7)^z3.RotateRight(x,18)^z3.LShR(x,3)
s=z3.Solver()
xs=[z3.BitVec(f“x{i}”,32)表示范围(32)内的i]
对于范围(32)内的i:
s、 添加(z3_sigma0(xs[i])==(1>def test_inv_once():
…r=random.randrange(2**32)
…返回inv_sigma0(sigma0(r))==r
>>>全部(在范围内(10**6)测试一次)
真的
上述内容可以完全无环无分支地书写:
def inv_sigma0(x):
xn=~x
r=((xn>>0)和1)-1)和0x185744e9
r^=((xn>>1)和1)-1)和0x30ae89d2
r^=((xn>>2)和1)-1)和0x615d13a4
r^=((xn>>3)和1)-1)和0xdaed63a1
r^=((xn>>4)和1)-1)和0x9cd03a8e
r^=((xn>>5)和1)-1)和0x08fdcc39
r^=((xn>>6)和1)-1)和0x11fb9872
r^=((xn>>7)和1)-1)和0x23f730e4
r^=((xn>>8)和1)-1)和0x5fb92521
r^=((xn>>9)和1)-1)和0xb