Encryption 如何确定所选密码是否正确?
如果存在一个加密文件,并且有人想要解密它,有几种方法可以尝试。 例如,如果您选择暴力攻击,这很简单:只要尝试所有可能的键,您就会找到正确的键。对于这个问题,这可能需要太长时间并不重要。 但尝试按键意味着以下步骤:Encryption 如何确定所选密码是否正确?,encryption,cryptography,Encryption,Cryptography,如果存在一个加密文件,并且有人想要解密它,有几种方法可以尝试。 例如,如果您选择暴力攻击,这很简单:只要尝试所有可能的键,您就会找到正确的键。对于这个问题,这可能需要太长时间并不重要。 但尝试按键意味着以下步骤: 选择键 用密钥解密数据 检查解密是否成功 除了需要知道用于加密的算法这一问题之外,我无法想象人们会怎么做 原因如下:解密数据后,我得到一些“其他”数据。在使用我能理解的语言加密的纯文本文件的情况下,我现在可以检查结果是否是该语言中的文本。 如果是已知的文件类型,我可以检查特定的文件头
如果不知道要查找什么,如何检查解密结果是否正确?你真的在问这样的问题吗? 如果知道里面有什么,你就不需要解密了,对吧 不知何故,这与编程问题无关,它更像数学问题。我在大学上了一些加密数学课 如果没有大量的数据点,你无法确认。 当然,如果你的结果是有意义的和清楚的,它在简单的英语(或任何使用的语言)中是有意义的,但要回答你的问题 如果你能够解密,你也应该能够加密。
因此,使用解密的反向过程对结果进行加密,如果得到相同的结果,则可能是金色的……如果不是,则可能有错误。其中一种方法是使用一些标准算法(如zip)压缩源数据。如果解密后你可以解压结果-它是正确的解密。压缩通常在加密之前由加密程序完成,因为这是另一个步骤,bruteforcer需要在每次试验中重复并浪费时间,而且加密数据几乎肯定是不可压缩的(使用链式算法压缩后大小不会减小).您可以使用类似unix的启发式方法
file
命令不检查已知的文件类型。如果你解密了没有可识别类型的数据,解密对你没有任何帮助,因为你无法解释它,所以它仍然和加密的一样好。没有更明确的定义,我只能指出。我想说,人们普遍认为验证结果是密码分析的一个简单部分。与解密一个已知的密码相比,彻底的验证检查只需要很少的cpu。正如您所建议的,人们会期望明文具有某种已知的格式,例如JPEG图像、PDF文件等。其想法是,给定的密文不太可能同时被解密为有效的JPEG图像和有效的PDF文件(但见下文) 但这其实并不重要。当一个人谈论密码系统是安全的时,他(粗略地)谈论你能够猜出与给定密文对应的明文的几率。所以我选择一个随机消息m并对它进行加密c=E(m).我给你c,如果你猜不出m,那么我们说密码系统是安全的,否则它就坏了 这只是一个简单的安全定义。还有其他定义要求系统能够(语义安全性):你给我两条消息,我加密其中一条,你将无法知道我选择了哪条消息 关键是,在这些定义中,我们不关心明文的格式,我们所需要的是您无法猜测加密的明文。因此没有步骤3:-) 通过不考虑您的步骤3,我们尽可能清楚地说明了安全性问题:我们不讨论猜测您使用的格式(zip、gzip、bzip2等)有多难,而只讨论了与猜测密钥的几率相比破坏系统的几率。您应该将所有的安全性都集中在密钥中,这是一个很好的解决方案——当您唯一的假设是密钥的保密性时,它可以极大地简化事情 最后,请注意,由于所有密钥都是合法的,因此某些加密方案使您无法验证是否拥有正确的密钥。这是这样一个方案的极端例子:取明文m,选择一个完全随机的密钥k,然后计算密文c=mxor k。这给你一个完全随机的密文,它是完全安全的(唯一完全安全的密码系统,顺便说一句)
搜索加密密钥时,您无法知道何时找到了正确的密钥。这是因为c可以是与m长度相同的任何文件的加密:如果您使用密钥*k'=c XOR m'加密消息m',您将看到您再次获得相同的密文,因此您无法知道m或m'是否是原始消息 不用考虑异或,你可以这样想一次性pad:我给你数字42,告诉你这是两个整数的和(负,正,你不知道)。一个整数是消息,另一个是密钥,42是密文。如上所述,猜测键是没有意义的——如果希望消息为100,则声明键为-58;如果希望消息为0,则声明键为42,以此类推。一次pad的工作方式与此完全相同,但取决于位值 关于在一次性键盘中重复使用密钥:假设我的密钥是7,您可以看到密文10和20,对应于明文3和13。仅从密文,你现在知道明文的区别是10。如果你以某种方式获得了一个纯文本的知识,你现在可以推导出另一个!如果这些数字对应于
#!/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
openssl enc -aes-256-cbc -in entropy.py -out entropy.py.enc