Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 复杂度为O(n)的反向SHA-256 sigma0函数? 介绍_Algorithm_Hash_Cryptography_Reverse Engineering - Fatal编程技术网

Algorithm 复杂度为O(n)的反向SHA-256 sigma0函数? 介绍

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

作为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 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
此外,如果您需要这些代码,下面是Python的完整版本:

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