Python 从SHA-1还原损坏的128位密钥

Python 从SHA-1还原损坏的128位密钥,python,encryption,aes,sha,Python,Encryption,Aes,Sha,免责声明:这是uni任务的一部分 我得到了以下AES-128-CBC密钥,并被告知密钥中最多有3位已更改/损坏 d9124e6bbc124029572d42937573bab4 提供原始密钥的SHA-1散列 439090331bd3fad8dc398a417264efe28dba1b60 我必须通过尝试3位翻转的所有组合来找到原始关键点 据推测,在349633次猜测中这是可能的,但我不知道这个数字来自何处;我假设它将接近128*127*126,这将是超过2M的组合,这是我的第一个问题所在。

免责声明:这是uni任务的一部分

我得到了以下AES-128-CBC密钥,并被告知密钥中最多有3位已更改/损坏

d9124e6bbc124029572d42937573bab4
提供原始密钥的SHA-1散列

439090331bd3fad8dc398a417264efe28dba1b60
我必须通过尝试3位翻转的所有组合来找到原始关键点

据推测,在349633次猜测中这是可能的,但我不知道这个数字来自何处;我假设它将接近128*127*126,这将是超过2M的组合,这是我的第一个问题所在。
其次,我创建了下面的python脚本,其中包含一个三重嵌套循环(我知道,远不是最好的代码…),以迭代所有2M的可能性,但是,在一小时后完成之后,它没有找到任何我真的不理解的匹配项

希望有人能给我指出正确的方向,干杯

#!/usr/bin/python2

import sys
import commands

global binary

def inverseBit(index):
    global binary
    if binary[index] == "0":
        return "1"
    return "0"

if __name__ == '__main__':
    if len(sys.argv) != 3:
        print "Usage: bitflip.py <hex> <sha-1>"
        sys.exit()

    global binary
    binary = ""

    sha = str(sys.argv[2])
    binary = str(bin(int(sys.argv[1], 16)))
    binary = binary[2:]
    print binary

    b2 = binary
    tries = 0
    file = open("shas", "w")

    for x in range(-2, 128):
        for y in range(-1,128):
            for z in range(0,128):
                if x >= 0:
                    b2 = b2[:x] + inverseBit(x) + b2[x+1:]
                if y >= 0:
                    b2 = b2[:y] + inverseBit(y) + b2[y+1:]
                b2 = b2[:z] + inverseBit(z) + b2[z+1:]
                #print b2
                hexOut = hex(int(b2,2))
                command = "echo -n \"" + hexOut + "\" | openssl sha1"
                cmdOut = str(commands.getstatusoutput(command))
                cmdOut = cmdOut[cmdOut.index('=')+2:]
                cmdOut = cmdOut[:cmdOut.index('\'')]
                file.write(str(hexOut) + " | " + str(cmdOut) + "\n")
                if len(cmdOut) != 40:
                    print cmdOut
                if cmdOut == sha:
                    print "Found bit reversals in " + str(tries) + " tries. Corrected key:"
                    print hexOut
                    sys.exit()
                b2 = binary
                tries = tries + 1
                if tries % 10000 == 0:
                    print tries

在(我想?)仍然覆盖整个空间的情况下,大幅减少猜测次数。仍然有一些重复的代码,但是仍然没有找到匹配的代码。

您的代码,如果不是很有效,看起来很好,除了一件事:

hexOut = hex(int(b2,2))
作为
hex的输出

>>> hex(int('01110110000101',2))
'0x1d85'
'Ox'
开头,它不应该是键的一部分。所以,删除这两个字符应该没问题

对于要尝试的可能键数,您有:

  • 1,无位翻转
  • 128,1位翻转
  • 128*127/2=8128,2位翻转(128种方式选择第一位,127种方式选择第二位,每对显示两次)
  • 128*127*126/6=341376,翻转3位(每个三元组显示6次)。这是一次取3的128位的组合数
所以,总数是1+128+8128+341376=349633

您的代码对它们进行了多次测试。通过这样的循环(3位),可以避免无用的重复:

您可以通过以下方式调整从-2开始的技巧:

for x in range (-2, 128):
    for y in range(x+1, 128):
        for z in range(y+1, 128):
            .... same code you used ...

您还可以生成以下组合:


但是在本例中,您需要做更多的工作来管理0、1、2和3翻转位的案例。

干杯,删除0x行得通。出于某种原因,还必须删除附加到所有十六进制值后面的“L”。看起来在你发表文章前不久,我找到了更好的循环方法,在一次编辑中添加了它,你可能错过了:)
for x in range (0, 128):
    for y in range(x+1, 128):
        for z in range(y+1, 128):
            .....
for x in range (-2, 128):
    for y in range(x+1, 128):
        for z in range(y+1, 128):
            .... same code you used ...
from itertools import combinations
for x, y, z in combinations(range(128), 3):  # for 3 bits
    ......