机器学习可以解码SHA256哈希吗?


43

我有一个64个字符的SHA256哈希。

我希望训练一个模型,该模型可以预测用于生成哈希的纯文本是否以1开头。

不管这是“可能的”,哪种算法是最佳方法?

我最初的想法:

  • 生成以1开头的大量散列样本和不以1开头的大量散列样本
  • 将哈希的64个字符中的每个字符设置为某种无监督逻辑回归模型的参数。
  • 通过告诉模型正确/错误的时间来训练模型。
  • 希望能够创建一个模型,该模型能够以足够高的精度(以及适当的kappa值)预测明文是否以1开头。

22
仅供参考:这很可能是由比特币开采推动的。
ClojureMostly,2016年

55
“无论模式是否可行,我将如何训练一种允许我进行时间旅行的模型?”
Konrad Rudolph

13
@Joshua OP想要反转 SHA-256。我会让他发布,即使它花费的步骤是SHA-256的一千倍。因为解决方案几乎可以肯定地利用了实际构造中的错误来破坏逻辑,所以我也将不再存在。
康拉德·鲁道夫

15
所有SHA256散列都可以由以“ 1”开头的字符串生成。
Reactgular

8
@cgTag很抱歉,这是错误的。输入确实控制输出,否则,它不是函数。同样,仅因为您拥有无限的事物列表,并不意味着它们中的任何一个都以1开头。注意:我也相信这是真的,但是声称它是正确的却具有误导性。如果您是对的,那么肯定会有论文或其他参考文献。
Pedro A

Answers:


98

这实际上不是一个统计答案,但是:

,您无法从哈希值中确定纯文本的第一个字符,因为对于给定的哈希值,没有“纯文本”之类的东西。

SHA-256是一种哈希算法。无论您使用什么明文,都可以得到一个32字节的签名,通常以64个字符的十六进制字符串表示。明文比64个字符的十六进制字符串要多得多-可以从任意数量的不同明文中生成相同的哈希。没有理由相信在产生给定哈希值的所有纯文本中,第一个字符为“ 1”或不为“ 1”是统一的。


21
这是到目前为止(我认为)唯一正确的答案。所有其他答案似乎更多地涉及学习哈希函数的问题,而不是学习反转哈希(实际问题)。他们似乎都忽略了哈希不是内射函数。
卡·花旗

7
您无法预测第一个字符为一个字符的可能性吗?缺乏一对一的情况在统计学习中并非常见问题。
马修·德鲁里

16
@MatthewDrury鉴于SHA256旨在使给定哈希值的所有输入均等地发生,因此对于任何给定hash,希望有无限多个从1开始的输入。因此,如果您想估计概率,则最佳估计将大致为。1256±ε
康拉德·鲁道夫

12
是的,同意。我只是想指出,缺乏内射性并不是机器学习应用程序真正的结构性问题。
马修·德鲁里

6
@IMil我之所以特别提到它是一个哈希函数的原因并不是要暗示没有哈希函数可能会泄露该信息,而是要激励人们说没有“明文”之类的说法。当然,一个(错误的)哈希函数可能是部分可逆的,并且可以清楚地告诉我们有关将产生该哈希函数的整个纯文本的某些信息,但是没有理由相信SHA-256。
克里斯·H

51

SHA256被设计为尽可能随机,因此您不太可能将以1-前缀的明文和非以-前缀的明文分开。散列字符串应该完全没有任何功能可以将这些信息泄露出去。


5
“不太可能”和“应该”-这就是算法将告诉我的。乍一看,这似乎是不可能的,但是我想知道采用哪种算法和方法来检验该假设。
约翰

24
+1可以确保任何类型的“无监督逻辑回归模型”都无法比猜测做得更好,除非可以提供真正意义上的天文数字的案例。这个问题在风车处倾斜。
ub

44
您可以尝试一下,但是学习者将尝试找到故意不存在的统计关系。
帕维尔·科马罗夫

32
“设计得尽可能随机”是一种轻描淡写的说法。具体而言,该设计旨在具有最大的非线性依赖性,其中每个输入位影响大约50%的输出位,每个输出位取决于大约50%的输入位。这就是混乱和扩散。它使这里的任务(仅恢复第一位)和恢复整个消息一样困难。
MSalters

12
我认为您可以在此答案中“不太可能”加强。OP运用基于统计的技术从内容预测SHA256哈希的任何部分的机会为零,反之亦然,甚至在随机猜测方面也有可检测的改进。实际的解决方案基本上是预先计算整个目标人群的原始内容。
尼尔·斯莱特

43

不管这是“可能的”,哪种算法是最佳方法?

对不起,但这是一个荒谬的问题。如果无法解决问题,那么您将无法找到解决问题的最佳方法。

在这种情况下,这绝对是不可能的,因为哈希是一种单向函数:多个输入(实际上是无限个)可以产生相同的输出。如果输入的第一位本身会以某种方式影响特定哈希值的可能性,则这意味着哈希算法完全有缺陷。

您当然可以训练神经网络,线性分类器,SVM和其他工具以尝试进行预测。而且,如果您能够从某种哈希算法的输出可靠地预测输入,那么这将证明该算法毫无价值。我想说,对于像SHA256这样广泛使用的算法,这种可能性几乎没有了。但是,这是一种快速排除新的,未经验证和未经测试的哈希算法的合理方法。


6
sign(x)

11
@KonradRudolph:“单向功能” 在此上下文中具有特定含义,并非您正在考虑的含义。sign(x)从这个意义上讲,它不是单向功能,因为找到原像是微不足道的。
user2357112 '18

4
也就是说,我也不认为答案是正确使用“单向功能”。
user2357112 '18

1
@ user2357112谢谢,我不知道。我只知道含义是一个可疑的函数,而不是可疑的函数。这也是我反对的答案中给出的定义。
康拉德·鲁道夫

1
是的,很抱歉,我对定义有点松懈。但是,我相信“单向”对于新手来说比更严格的术语更容易理解。
IMil

26

虽然不能用一个例子证明负面。我仍然觉得举个例子是有启发性的。也许有用。它确实显示了人们将如何(试图)解决类似的问题。

我想使用二进制矢量特征进行二进制预测的情况下 ,随机森林是一个不错的选择。我想这种回答是您问题的第二部分:什么是好的算法。

我们非常希望将SHA256字符串预处理为二进制(布尔)向量,因为每个位在统计上都是独立的,因此每个位都是一个很好的功能。这样我们的输入将成为256个元素的布尔向量。

演示版

这是使用Julia DecisionTree.jl库如何完成整个过程的演示。

您可以将以下内容复制粘贴到julia提示符中。

using SHA
using DecisionTree
using Statistics: mean
using Random: randstring

const maxlen=10_000 # longest string (document) to be hashed.

gen_plaintext(x) = gen_plaintext(Val{x}())
gen_plaintext(::Val{true}) = "1" * randstring(rand(0:maxlen-1))
gen_plaintext(::Val{false}) = randstring(rand(1:maxlen))


bitvector(x) = BitVector(digits(x, base=2, pad=8sizeof(x)))
bitvector(x::AbstractVector) = reduce(vcat, bitvector.(x))

function gen_observation(class)
    plaintext = gen_plaintext(class)
    obs = bitvector(sha256(plaintext))
    obs
end

function feature_mat(obs)
    convert(Array, reduce(hcat, obs)')
end

########################################

const train_labels = rand(Bool, 100_000)
const train_obs = gen_observation.(train_labels)
const train_feature_mat = feature_mat(train_obs)

const test_labels = rand(Bool, 100_000)
const test_obs = gen_observation.(test_labels)
const test_feature_mat = feature_mat(test_obs)


# Train the model
const model = build_forest(train_labels, train_feature_mat)
@show model


#Training Set accuracy:
@show mean(apply_forest(model, train_feature_mat) .== train_labels)

#Test Set accuracy:
@show mean(apply_forest(model, test_feature_mat) .== test_labels)

结果

当我这样做时,训练100,000个随机ASCII字符串,其长度最大为10,000。这是我看到的结果:

训练模型

julia> const model = build_forest(train_labels, train_feature_mat)
Ensemble of Decision Trees
Trees:      10
Avg Leaves: 16124.7
Avg Depth:  17.9

训练集准确性:

julia> mean(apply_forest(model, train_feature_mat) .== train_labels)
0.95162

测试仪精度:

julia> mean(apply_forest(model, test_feature_mat) .== test_labels)
0.5016

讨论区

因此,基本上什么都没有。我们从训练组的95%上升到测试组的50%以上。有人可以运用适当的假设检验,看看我们是否可以拒绝原
假设,但我敢肯定我们不能。与猜测率相比,这是很小的改进。

这表明它是无法学习的。如果是“随机森林”,则可以从拟合良好到仅达到猜测率。随机森林非常有能力学习困难的输入。如果有什么要学习的,我希望至少有百分之几。

您可以通过更改代码来使用不同的哈希函数。当在构建hash函数中使用julia时,我得到的结果基本相同(这不是加密安全的hsah,但仍然是一个很好的哈希,因此确实应该发送类似的字符串),这可能会很有趣。对于,我也得到了基本相同的结果 CRC32c


15

哈希函数(通过设计)非常不适合使用它们进行任何机器学习。

ML本质上是建模/估计局部连续函数的方法系列。即,您正在尝试描述一些物理系统,尽管它可能具有某些不连续性,但在某种意义上,它在大多数参数空间中都足够平滑,因此只能使用分散的测试数据样本来预测其他结果输入。为此,AI算法需要以某种方式将数据分解为一个聪明的基础表示形式,为此训练表明,例如,如果您看到这样或那样的形状(看起来与这种或这种卷积的结果相关),那么输出在相应区域中具有这样和这样的结构的好机会(可以再次用卷积或某种形式描述)。

(我知道,许多ML方法根本都不像卷积,但总的思路始终是相同的:您的输入空间是如此之高,无法进行详尽的采样,因此您发现了一个聪明的分解方法,可以进行推断比较稀疏的样本得出的结果。)

但是,密码散列函数背后的想法是,对纯文本的任何更改都应导致完全不同的摘要。因此,无论您如何分解函数,局部估计器都不允许您推断该部分周围的微小波动如何影响结果。除非您当然要实际处理有限集合中的所有信息,否则这不会被称为机器学习:您只会构建一个Rainbow table


4
阅读此书后,我想到a)建立一个彩虹表,您需要知道要使用的哈希函数,b)给定足够大的值,机器学习算法可能会确定正在使用哪种算法。输入和输出样本(至少在算法具有可识别缺陷的情况下)。因此,如果将原始问题重述为需要识别的未知哈希函数,那么在实际操作中可能会更有趣。
senderle

7

这是一个有趣的问题,因为它引发了有关什么被视为“机器学习”的问题。如果可以解决,肯定会有一种算法最终可以解决此问题。它是这样的:

  1. 选择您喜欢的编程语言,然后确定将每个字符串映射到(可能非常大)整数的编码。

  2. 选择一个随机数并将其转换为字符串。检查它是否是您所用语言的有效程序。如果不是,请选择另一个号码,然后重试。如果是这样,请启动它,立即暂停它,并将其添加到已暂停程序的列表中。

  3. 运行所有暂停的程序一会儿。如果它们中的任何一个都停止了而没有产生适当的解决方案,请从列表中删除它们。如果有足够的解决方案,那么您就完成了!否则,让它们全部运行一段时间后返回2。

毫无疑问,如果您有无限的存储空间和无限的时间,上述算法最终将找到一个好的解决方案。但这可能不是您所说的“机器学习”的意思。

问题在于:如果考虑所有可能的问题,那么平均而言,没有机器学习算法可以做得更好!这就是所谓的免费午餐定理。事实证明,在任何给定的机器学习算法中,您可能会遇到的所有问题中,它可以迅速解决的数量几乎没有。

它可以快速解决这些问题,只是因为它们受算法可以预期的模式支配。例如,许多成功的算法都假定以下条件:

  1. 解决方案可以通过一系列复杂的矩阵乘法和非线性失真来描述,并由一组参数控制。

  2. 好的解决方案将在参数空间中聚集在一起,因此您要做的就是选择一个搜索邻域,在其中找到最佳解决方案,移动您的搜索邻域,以使最佳解决方案位于中心,然后重复。

显然,这两个假设都不成立。第二点尤其令人怀疑。没有免费的午餐告诉我们,这些假设在大多数情况下都不成立。实际上,它们几乎永远不会保持住!它们确实可以解决某些实际问题,这只是我们的好运。

您选择的问题从一开始就是为了违反假设2而设计的。哈希函数经过专门设计,以便类似的输入提供完全不同的输出。

因此,您的问题-什么是解决该问题的最佳机器学习算法?-可能有一个非常简单的答案:随机搜索。


我不知道量子计算将如何影响无自由午餐定理。据推测,量子计算也受到它的限制。
Max Vernon

1
@MaxVernon哦,有趣。与其他量子算法相比,我希望所有量子算法具有相同的性质。我不知道所有的量子优化算法是否都比经典算法具有平均情况下的加速。他们可能!我有一个问题和自我解答,谈论可能相关的“免费午餐”定理。(tldr;只有当您忽略一些已完成的工作时,午餐才是免费的...但是我想知道量子情况是否会发生变化。)
senderle

5

这几乎是不可能的。但是,人们观察到SHA256中的一些模式,这可能表明它是非随机。他们的tldr:

“要区分理想的随机排列散列和SHA256,将大量(〜2 ^ 80)个候选1024位块进行散列两次,就像在比特币中所做的那样。确保候选块的位被稀疏设置(比根据比特币协议,期望的平均值为512),丢弃不符合比特币“难度”标准的候选区块(在该区块中,生成的散列以大量的0开头),剩下的有效输入候选集(467369,当完成此分析),观察输入块中特定的一组32位(位于比特币具有随机数的位置,输入比特607-639)。请注意,随机数字段中设置的平均位数向左偏斜,即少于设定的16位的期望值(估计平均值15.428)。”

请参阅lobste.rs上的讨论。一种可能的解释是矿工造成的偏见。


2
这是有趣的。但是对lobste.rs的回复可能是正确的。这是一个巨大的偏差,很容易发现。长期以来未被注意的观点是牵强的。
senderle '18

1
@senderle为了利用偏差(如果有的话),应该提出一种算法(本质上是ML /优化算法),该算法在计算上很便宜,以便在最先进的硬件上实现/测量时自己的开销由它提供的加速来补偿。我非常粗略的猜测是,就#hashtrials而言,该因子应大于10倍才能击败蛮力及其超优化的实现。这可能会非常严重,特别是对于押注加密和安全协议的人们。
IndieSolver

4

我会回答一个程序。为了减少计算要求,我将使用sha256的变体,我称之为sha16,它只是sha256的前16位。

#!/usr/bin/python3

import hashlib
from itertools import count

def sha16(plaintext):
    h = hashlib.sha256()
    h.update(plaintext)
    return h.hexdigest()[:4]

def has_plaintext_start_with_1(digest):
    """Return True if and only if the given digest can be generated from a
    plaintext starting with "1" first bit."""
    return True

def plaintext_starting_with_1(digest):
    """Return a plaintext starting with '1' matching the given digest."""
    for c in count():
        plaintext = (b'\x80' + str(c).encode('ascii'))
        d = sha16(plaintext)
        if d == digest:
            return plaintext

for digest in range(0x10000):
    digest = "%04x" % (digest,)
    plain = plaintext_starting_with_1(digest)
    print("%s hashes to %s" % (plain, digest))

产生输出:

b'\x8094207' hashes to 0000
b'\x8047770' hashes to 0001
b'\x8078597' hashes to 0002
b'\x8025129' hashes to 0003
b'\x8055307' hashes to 0004
b'\x80120019' hashes to 0005
b'\x8062700' hashes to 0006
b'\x8036411' hashes to 0007
b'\x80135953' hashes to 0008
b'\x8044091' hashes to 0009
b'\x808968' hashes to 000a
b'\x8039318' hashes to 000b
[...]

我会将完整的证明留给读者练习,但请注意:对于每个可能的摘要(从0000到ffff),都有一个以“ 1”开头的输入。

还有一个输入不以“ 1”开头。还有一部也是从莎士比亚的完整著作开始的。

尽管我的强力证明可能在计算上变得不可行,但这适用于任何相当好的哈希函数。


在数学上,我不愿意相信你。您的程序演示了sha16函数是射影,但仅此而已。您没有提供正式证明,该程序可以证明实际的SHA-256功能。按照您的结论风格,可以解决Collat​​z猜想,因为它已经解决了32位,并且程序可以轻松运行更长的时间。
罗兰·伊利格

4

您所描述的基本上是预映像攻击。您正在尝试找到一个输入,以便在对其进行哈希处理时,输出具有一些属性,例如“前导1”。*

密码散列的一个明确目标是防止此类前映像攻击。如果您可以进行此类攻击,我们倾向于认为该算法不安全并停止使用它。

因此,尽管这并非不可能,但这意味着您的机器学习算法必须同时胜过世界上很大一部分数学家及其超级计算机。您不太可能会这样做。

但是,如果您这样做了,您将成为打破主要加密哈希算法的人。那个名望值得!

*从技术上讲,“第一次原像攻击”试图找到特定哈希值的匹配项。但是,为了表明哈希算法具有第一个像前攻击的持久性,它们通常表明您找不到与哈希输入有关的任何有意义的信息。


2

这里的大多数答案都在告诉您为什么您不能执行此操作,但这是直接的答案:

不管这是“可能的”,哪种算法是最佳方法?

假设输入足够大:

  1. 计算有效字符集的数量。
  2. 从步骤1中取数字的倒数。

这就是输入字符串以“ 1”开头的可能性。您甚至不需要查看输入。如果您能做得更好,则意味着哈希值非常混乱。与尝试训练算法以选择随机数相比,您可以节省大量CPU周期。

您可以训练算法,由于过度拟合,可能会得出不同的答案。除非哈希算法确实有什么问题。与仅选择一个随机值相比,使用该算法出错的可能性更高。


1

哈希函数是有意设计的,很难建模,因此(正如已经指出的那样),这可能非常困难。尽管如此,哈希函数的任何弱点都会降低其熵,从而使其更可预测。

不管这是“可能的”,哪种算法是最佳方法?

一个有用的示例是“ 物理上不可克隆的函数 ”或PUF-与硬件哈希函数类似。通常,有意使用制造差异为每个PUF提供稍微不同的响应,以使它们的“散列”输出对于给定的输入而言是不同的。设计弱点限制了熵,但是,如果有足够的质询-响应对,通常可以构建PUF的黑匣子模型,以便可以预测新的,以前看不见的质询的响应。

逻辑回归是这些建模攻击最常用的方法,例如Rührmair的论文。

遗传算法(或更笼统地说是进化策略)可能是一种替代方法,因为它们适用于不可微分和/或线性可分离的问题。上面的文章中也对它们进行了讨论。


1

251222562256

26402641

2256264(2256264)!

S=(2256264)
C=90100S
CSC

(1S1S11S2...1S(C1))(SC1SCSC2SC1SC3SC2...12)=(SC1)!S!

=(110(2256264)1)!(2256264)!
2(2263.99184665662260.6509677217)
210.13222373912260.6509677217

22562512


1

问题在于“机器学习”不是智能的。它只是试图找到模式。在SHA-256中,没有模式。没什么可找的。机器学习没有比蛮力更好的机会了。

如果您想通过计算机破解SHA-256,唯一的可能性就是创建真实的智能,并且由于许多聪明的人还没有找到创建SHA-256的方法,因此您需要创建比许多聪明的人。到那时,我们还不知道这样的超人类智能是否会破解SHA-256,证明它不会被破解,或者是否会决定它不够聪明(就像人类一样)。第四个可能性当然是,这样的超人类人工智能甚至不会打扰,而是会考虑更重要的问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.