我尝试打印时解密十六进制字符串并获取非十六进制字符

时间:2013-09-13 01:05:38

标签: python

在下面的代码中,我试图解密加密的消息,给出两条用相同密钥加密的消息(两次打击垫)。代码按照我的要求工作,直到最后一行我尝试打印出十六进制字符串为ascii。

我收到错误:

    print result.decode('hex')
  File "/usr/lib/python2.7/encodings/hex_codec.py", line 42, in hex_decode
    output = binascii.a2b_hex(input)
TypeError: Non-hexadecimal digit found

导致错误的十六进制字符串是:

ab51e67kba7<4:72fd`d

其中包含一些非十六进制字符。我不确定为什么它有非十六进制。或者从这里开始。

这是完整的代码:

# Messages
m1 = "31aa4573aa487946aa15"
m2 = "32510ba9babebbbefd00"

# Key
k = "6b6bdfa4rqggrgwereff"

guess = 'aa'
#guess = guess.encode('hex')
result = ''


def strxor(a, b):     # xor two strings of different lengths
    if len(a) > len(b):
        return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a[:len(b)], b)])
    else:
        return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b[:len(a)])])

# Make cipher texts
c1 = strxor(m1,k)
c2 = strxor(m2,k)

# xor of the two messages   
m1m2 = strxor(c1,c2)

# loop through each bit of the m1m2 message and xor against a test char or string
# see if any of the output makes sense
for e in range(0, len(m1), 2):
    subString = m1m2[e:e+2]
    try:
        result = result + "".join( strxor(subString, guess))
    except exception: 
        pass

#print hex and ascii results
print result
print result.decode('hex')

2 个答案:

答案 0 :(得分:1)

回顾一下,看看c1中的内容。

也就是说,通过

运行一切
# Messages
m1 = "31aa4573aa487946aa15"
m2 = "32510ba9babebbbefd00"

# Key
k = "6b6bdfa4rqggrgwereff"

guess = 'aa'
#guess = guess.encode('hex')
result = ''


def strxor(a, b):     # xor two strings of different lengths
    if len(a) > len(b):
        return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a[:len(b)], b)])
    else:
        return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b[:len(a)])])

# Make cipher texts
c1 = strxor(m1,k)

c1在这种情况下为'\x05SW\x03PSV\x07\x13\x10S_E^CS\x13\x04WS'

m1k被xor'ed时,两个 ascii十六进制数字字符串已被xored。结果肯定会超出您期望的范围。

事实上,这里只是通过xoring这些数字来结束整个字符集:

In[0]: set((chr(ord(i)^ord(j)) for j in "abcdef0123456789" for i in "abcdef0123456789"))

Out[0]: {'\x00',
         '\x01',
         '\x02',
         '\x03',
         '\x04',
         '\x05',
         '\x06',
         '\x07',
         '\x08',
         '\t',
         '\n',
         '\x0b',
         '\x0c',
         '\r',
         '\x0e',
         '\x0f',
         'P',
         'Q',
         'R',
         'S',
         'T',
         'U',
         'V',
         'W',
         'X',
         'Y',
         'Z',
         '[',
         '\\',
         ']',
         '^',
         '_'}

另一方面,请告诉我这是课堂作业或只是为了好玩。你不应该像这样滚动你自己的加密。

答案 1 :(得分:1)

如果我理解正确,你的意图是strxor遍历两个字符串,将每个字符转换为0-15范围内的数字,将每个字符串中的相应字符异或,然后将结果转换回来转换为字符并返回结果字符串。我不认为strxor正在这样做 - 例如,ord('6')不是6,而是54(字符的ASCII值)。我怀疑这就是你在输入中得到非十六进制字符的原因。

而不是chr(ord(x) ^ ord(y)),我认为你想要的是:

def toHexNum(c):
    n = ord(c)
    if n >= ord('0') and n <= ord('9'):
        return n - ord('0')
    elif n >= ord('A') and n <= ord('F'):
        return n - ord('A') + 10
    elif n >= ord('a') and n <= ord('f'):
        return n - ord('a') + 10
    else:
        return None

def fromHexNum(n):
    chars = "0123456789abcdef"
    return chars[n]

def strxor(a, b):     # xor two strings of different lengths
    if len(a) > len(b):
        return "".join([fromHexNum(toHexNum(x) ^ toHexNum(y)) for (x, y) in zip(a[:len(b)], b)])
    else:
        return "".join([fromHexNum(toHexNum(x) ^ toHexNum(y)) for (x, y) in zip(a, b[:len(a)])])

可能有一种更干净的方法可以做到这一点,但我似乎无法找到它 - 也许某人对Python库的了解比我强大的人可以在这个注释中插入。