【问题标题】:How to decide if the chosen password is correct?如何判断选择的密码是否正确?
【发布时间】:2009-07-31 13:21:59
【问题描述】:

如果存在加密文件并且有人想要解密它,可以尝试几种方法。 例如,如果您选择暴力攻击,这很容易:只需尝试所有可能的密钥,您就会找到正确的密钥。对于这个问题,这可能需要太长时间并不重要。 但是尝试密钥意味着以下步骤:

  1. 选择键
  2. 使用密钥解密数据
  3. 检查解密是否成功

除了您需要知道用于加密的算法的问题之外,我无法想象#3 会怎么做。

原因如下:解密数据后,我得到了一些“其他”数据。如果是我可以理解的语言的加密纯文本文件,我现在可以检查结果是否是该语言的文本。 如果它是已知的文件类型,我可以检查特定的文件头。

但是由于人们试图解密一些秘密,所以很可能不知道如果正确解密会得到什么样的信息。

如果不知道要查找什么,如何检查解密结果是否正确?

【问题讨论】:

  • 我认为您的最后一个假设至少在某些时候是不正确的。根据传输数据的上下文,您可以提前了解信息的类型。例如,如果您正在解密电子邮件,则数据只有几种合理的格式。加密不是一种独立存在的技术。您需要防止各种攻击,其中许多攻击不是基于破坏加密方案。
  • @jprete:我同意,如果您能出于某种原因猜出文件格式,那么您将处于一个更好的位置。我的想法更笼统,例如“这是一个文件,不知道从哪里来,不知道内容是什么,但它可能是加密的”。
  • 叫我愤世嫉俗,但如果你不知道内容是有意义的,何必呢?必须有一些关于内容的基础知识,才能激发破解它的欲望。

标签: encryption cryptography


【解决方案1】:

正如您所建议的那样,人们会期望明文具有某种已知格式,例如 JPEG 图像、PDF 文件等。其想法是,给定的密文不太可能同时被解密为有效的 JPEG 图像和有效的 PDF 文件(但见下文)。

但实际上并不那么重要。当有人谈论密码系统是安全时,有人(大致)谈论您能够猜出与给定密文相对应的明文的几率。所以我选择一个随机消息 m 并加密它 c = E(m)。我给你c,如果你猜不到m,那么我们说密码系统是安全的,否则它就坏了。

这只是一个简单的安全定义。还有其他定义要求系统能够hide known plaintexts(语义安全):你给我两条消息,我加密其中一条,你将无法分辨我选择了哪条消息。

关键是,在这些定义中,我们不关心明文的格式,我们只需要你不能猜出被加密的明文。 所以没有第 3 步 :-)

通过不考虑您的第 3 步,我们使安全问题尽可能清晰:与其争论猜测您使用的格式(zip、gzip、bzip2 ......)有多难,我们只讨论破解系统的几率与猜测 key 的几率相比。这是old principle,您应该将所有安全性都集中在密钥中——当您唯一的假设是密钥的保密性时,它会极大地简化事情。

最后,请注意,某些加密方案使您无法验证您是否拥有正确的密钥,因为所有密钥都是合法的。 one-time pad 是这种方案的一个极端示例:您获取明文 m,选择一个完全随机的密钥 k 并将密文计算为 c = m XOR k。这给你一个完全随机的密文,它是完全安全的(唯一完全安全的密码系统,顺便说一句)。

在搜索加密密钥时,您无法知道何时找到了正确的密钥。这是因为 c 可以是长度与 m 相同的任何文件的加密:如果您使用密钥 * 加密消息 m' k' = c XOR m' 你会看到你再次得到相同的密文,因此你不知道是 m 还是 m' 是原始消息。

不用考虑异或,你可以考虑这样的一次性填充:我给你数字 42,告诉你它是两个整数的和(负数,正数,你不知道)。一个整数是消息,另一个是密钥,42 是密文。像上面一样,你猜密钥是没有意义的——如果你希望消息是 100,你声称密钥是 -58,如果你希望消息是 0,你声称密钥是 42,等等。 One time pad 的工作原理与此完全一样,但使用的是位值。

关于在一次性密文中重复使用密钥:假设我的密钥是 7,你看到密文 10 和 20,对应明文 3 和 13。仅从密文,你现在知道了明文的差异是 10。如果你以某种方式获得了其中一个明文的知识,你现在可以推导出另一个!如果数字对应于单个字母,您可以开始查看几个这样的差异并尝试解决由此产生的填字游戏(或让程序根据相关语言的频率分析来解决)。

【讨论】:

  • 我正在写一个类似的答案......这真的是一个问题 - 我得到一个文件,我怎么知道它没问题。关于一次性便笺式加密的一个重要点是,您可以找到一个密钥,将您的消息解密为您想要的任何其他消息 - 使其成为完美的加密(除了人为因素,如贿赂或间谍活动)。
  • @Kobi:确切地说,一次性密码本是完美的,除了您必须分发大量密钥(每个密钥只能使用一次)、防止贿赂等事实。 . :-)
  • "在搜索加密密钥时,您无法知道何时找到了正确的密钥。" - 这基本上不是意味着试图解密任何东西都是没有意义的吗?我不能说你找到了你要找的东西,为什么还要开始? (我想到你不知道的文件格式,不是纯文本或任何常见的)如果我加密一个已经加密的文件,如果他们不从我这里得到密钥,没有人可以解密它,因为没有解密方法。听起来太安全了,难以置信。
  • @Holderwa:你是对的,开始搜索密钥是没有意义的。我已经用另一种解释一次性垫如何工作的方式更新了答案。这不太安全 - 问题在于您必须将密钥安全地分发给接收者,并且您必须为每条消息使用 new 密钥。
  • @Martin:非常感谢,非常好的解释。现在这也意味着,如果你能摆脱密钥分配问题,你就万事大吉了。具体来说,如果您不想加密传输给其他人,而是为了保护您自己、个人或企业信息的安全,而您是唯一拥有密钥的人。
【解决方案2】:

你可以使用像 unix 这样的启发式算法

file

命令会检查已知的文件类型。如果您解密了没有可识别类型的数据,那么解密它无论如何都对您没有帮助,因为您无法解释它,所以它仍然与加密一样好。

【讨论】:

  • 非常好。存在密码学——如果你不知道你在找什么,你怎么知道什么时候找到它? :)
  • “存在密码学”——我喜欢这个。
  • 是的,完全正确!但这意味着如果你不知道你在寻找什么,因为它是一种你不知道的文件格式,你就没有机会解密它。这里肯定有漏洞,是牢不可破的加密;除了从知道它的人那里得到钥匙。
  • @Holgerwa:使用秘密文件格式等同于使用秘密加密方法,而后者早已被大多数人接受为一种有缺陷的想法(“通过默默无闻来保证安全”)。见en.wikipedia.org/wiki/Kerckhoffs%27_principle
【解决方案3】:

我不久前写了一个工具,通过简单地检查字节值的分布来检查文件是否可能被加密,因为加密文件应该与随机噪声无法区分。这里的假设是,一个不正确解密的文件保留了随机性,而一个正确解密的文件将显示出结构。

#!/usr/bin/env python

import math
import sys
import os

MAGIC_COEFF=3

def get_random_bytes(filename):
        BLOCK_SIZE=1024*1024
        BLOCKS=10

        f=open(filename)
        bytes=list(f.read(BLOCK_SIZE))

        if len(bytes) < BLOCK_SIZE:
                return bytes

        f.seek(0, 2)
        file_len = f.tell()
        index = BLOCK_SIZE
        cnt=0
        while index < file_len and cnt < BLOCKS:
                f.seek(index)
                more_bytes = f.read(BLOCK_SIZE)
                bytes.extend(more_bytes)
                index+=ord(os.urandom(1))*BLOCK_SIZE
                cnt+=1

        return bytes

def failed_n_gram(n,bytes):
        print "\t%d-gram analysis"%(n)
        N = len(bytes)/n
        states = 2**(8*n)
        print "\tN: %d states: %d"%(N, states)

        if N < states:
                print "\tinsufficient data"
                return False

        histo = [0]*states
        P = 1.0/states

        expected = N/states * 1.0
        # I forgot how this was derived, or what it is suppose to be
        magic = math.sqrt(N*P*(1-P))*MAGIC_COEFF
        print "\texpected: %f magic: %f" %(expected, magic)

        idx=0
        while idx<len(bytes)-n:
                val=0
                for x in xrange(n):
                        val = val << 8
                        val = val | ord(bytes[idx+x])

                histo[val]+=1
                idx+=1

                count=histo[val]
                if count - expected > magic:
                        print "\tfailed: %s occured %d times" %( hex(val), count)
                        return True

        # need this check because the absence of certain bytes is also
        # a sign something is up
        for i in xrange(len(histo)):
                count = histo[i]
                if expected-count > magic:
                        print "\tfailed: %s occured %d times" %( hex(i), count)
                        return True

        print ""

        return False

def main():
        for f in sys.argv[1:]:
                print f
                rand_bytes = get_random_bytes(f)

                if failed_n_gram(3,rand_bytes):
                        continue

                if failed_n_gram(2,rand_bytes):
                        continue

                if failed_n_gram(1,rand_bytes):
                        continue


if __name__ == "__main__":
        main()

我觉得这很合理:

$ entropy.py ~/bin/entropy.py entropy.py.enc entropy.py.zip 
/Users/steve/bin/entropy.py
        1-gram analysis
        N: 1680 states: 256
        expected: 6.000000 magic: 10.226918
        failed: 0xa occured 17 times
entropy.py.enc
        1-gram analysis
        N: 1744 states: 256
        expected: 6.000000 magic: 10.419895

entropy.py.zip
        1-gram analysis
        N: 821 states: 256
        expected: 3.000000 magic: 7.149270
        failed: 0x0 occured 11 times

这里.enc是跑通的源代码:

openssl enc -aes-256-cbc -in entropy.py -out entropy.py.enc

.zip 是不言自明的。

一些注意事项:

  1. 它不会检查整个文件,只检查第一个 KB,然后是文件中的随机块。因此,如果一个文件是附加了一个 jpeg 的随机数据,它会欺骗程序。确定是否检查整个文件的唯一方法。

  2. 根据我的经验,代码可靠地检测到文件何时未加密(因为几乎所有有用的数据都有结构),但由于其统计性质,有时可能会误诊加密/随机文件。

    李>
  3. 正如已经指出的那样,这种分析对于 OTP 来说是失败的,因为你可以让它说出你想要的任何东西。

  4. 使用风险自负,而且肯定不是检查结果的唯一方法。

【讨论】:

  • 这种更复杂的变体是检查文件是否正确解密的好方法。通常,只有正确的分布才会出现非随机的。不利的一面是,如果文件在加密之前被压缩,或者是压缩文件类型(如 jpeg 或 png 图像),它可能看起来非常随机,以至于您的统计分析无法区分。
  • 我实际上打赌压缩文件更有可能无法分析,因为从某种意义上说,它们使数据更加有序,以便使用更少的字节存储更多。如果没有其他正确解压缩所需的结构将是充分结构化的。虽然像 JPG 这样的无损压缩可能会奏效。
  • 如果你已经解密但没有解压缩数据(特别是如果你不知道它被压缩了),统计分析很可能会失败,这是我的观点。显然,如果你先解压数据,那就不适用了。
  • 直觉告诉我压缩不会删除结构,它会增加结构。因此,X.zip 比解密后的 X 更有可能被提取。
【解决方案4】:

其中一种方法是使用一些标准算法(如 zip)压缩源数据。如果解密后您可以解压缩结果 - 它已正确解密。压缩几乎通常在加密之前由加密程序完成 - 因为这是暴力破解程序需要为每次试验重复并在其上浪费时间的另一个步骤,并且因为加密数据几乎肯定是不可压缩的(使用链式算法压缩后大小不会减小)。

【讨论】:

    【解决方案5】:

    如果没有更明确定义的场景,我只能指向cryptanalysis methods。我想说验证结果是密码分析的一个简单部分,这是普遍接受的。与解密已知密码相比,彻底的验证检查只需要很少的 CPU。

    【讨论】:

    • 我不认为你是正确的。当您进行蛮力攻击时,您需要验证您是否为您尝试的每个密钥找到了正确的密钥,这很容易比解密花费更长的时间,从而使总时间成倍增加。
    • 但始终假设您尝试解密的数据采用您知道的格式。知道了这一点,一个人不会因为这个原因而试图保守秘密吗?
    • @Holgerwa:这不太实际。在大多数系统中,您可以在某处访问明文消息(例如,考虑公开部署的密码系统),如果您不这样做,在第一次破解之后您就有了,并且所有其他破解变得更加容易。
    【解决方案6】:

    你是认真地问这样的问题吗? 好吧,如果它知道里面有什么,那么您无论如何都不需要解密它吗?

    不知何故,这与编程问题无关,它更数学化。我在大学上过一些加密数学课程。

    如果没有大量数据点,您无法确认。 当然,如果您的结果有意义并且清楚,它在简单的英语(或使用的任何语言)中是有意义的,但要回答您的问题。

    如果您能够解密,您也应该能够加密。 因此,使用解密的逆过程对结果进行加密,如果得到相同的结果,您可能会很成功……如果不是什么问题,可能是错误的。

    【讨论】:

    • 我爱 -2 没有解释
    • 嗯,这个问题显然与编程有关——几乎所有的密码学都是——很明显,他的问题是他不知道密钥,而不是他不知道算法。
    • 正确,即使您知道算法,如果原始数据是您已知的文件格式,您也只能通过密码分析找到任何东西。如果这是解密者的唯一机会,为什么加密者会在选择已知文件格式时犯这样的错误?
    • @grobartn:我认为这与编程非常相关。如果我使用加密/解密算法,你知道的越多越好。当然,所有科目都是一样的:)
    猜你喜欢
    • 1970-01-01
    • 2021-09-09
    • 2014-11-20
    • 1970-01-01
    • 1970-01-01
    • 2015-04-07
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多