Unhexlify, кажется, дает мне int, когда я хочу строку

Мне нужно выполнить XOR двух шестнадцатеричных строк, чтобы каждый байт подвергался XOR отдельно, но это не работает, потому что функция ord(), которую я использую, похоже, получает int в качестве входных данных вместо предполагаемой строки. Сначала взгляните на его код, чтобы понять, что я имею в виду:

from binascii import hexlify, unhexlify

def xor_hexstr(s1, s2):
    if len(s1) > len(s2):
        q = zip(unhexlify(s1[:len(s2)]), unhexlify(s2))
        return hexlify("".join(chr(ord(c1) ^ ord(c2)) for c1, c2 in q))

    else:
        q = zip(unhexlify(s2[:len(s1)]), unhexlify(s1))
        return hexlify("".join(chr(ord(c1) ^ ord(c2)) for c1, c2 in q))


t1 = "0ec17c9dabb8955c5dfb9cef627ddb4d"
t2 = "4ca00ff4c898d61e1edbf1800618fb28"

xor_hexstr(t1, t2)

И ошибка, которую я получаю:

TypeError: ord() expected string of length 1, but int found

Затем я проверил значения q, и они действительно были целыми числами по какой-то причине. Я не понимаю, почему, потому что, согласно моей логике, они должны быть строками, потому что я дал ей строку в шестнадцатеричном кодировании, расшифровал ее, а затем вставил каждый символ в слот в q.


person Community    schedule 11.07.2013    source источник
comment
Почему вы передаете s1, s2 вместо t1, t2?   -  person falsetru    schedule 11.07.2013
comment
Извините, фальшиво, это была опечатка :D. Однако в моем исходном коде этого нет.   -  person    schedule 11.07.2013


Ответы (2)


Вы используете hexlify и unhexlify в Python 3, где они возвращают объект bytes. Затем вы архивируете эти объекты, которые перебирают bytes объектов для создания пар. Итерация по объекту bytes дает целые числа. См. документациюbytesтипа:

В то время как литералы и представления bytes основаны на тексте ASCII, объекты bytes на самом деле ведут себя как неизменяемые последовательности целых чисел, причем каждое значение в последовательности ограничено таким образом, что 0 <= x < 256.

Вам не нужно использовать ord() при переборе объекта bytes; у вас уже есть целые числа, представляющие отдельные байты.

Просто используйте объект bytes снова после XOR значений:

def xor_hexstr(s1, s2):
    if len(s1) > len(s2):
        q = zip(unhexlify(s1[:len(s2)]), unhexlify(s2))
    else:
        q = zip(unhexlify(s2[:len(s1)]), unhexlify(s1))

    return hexlify(bytes(c1 ^ c2 for c1, c2 in q))

Обратите внимание, что hexlify также возвращает объект bytes. Если вам нужно иметь строковый (юникодный) объект, декодируйте из ASCII:

xor_hexstr(t1, t2).decode('ASCII')

Демо:

>>> xor_hexstr(t1, t2)
b'426173696320434243206d6f64652065'
>>> xor_hexstr(t1, t2).decode('ASCII')
'426173696320434243206d6f64652065'
person Martijn Pieters    schedule 11.07.2013
comment
Благодарю вас! Ваше решение сработало, и ваше объяснение было хорошим: D. - person ; 11.07.2013

from binascii import hexlify, unhexlify

def xor_hexstr(s1, s2):
    q = zip(unhexlify(s1), unhexlify(s2))
    return "".join(chr(c1 ^ c2) for c1, c2 in q)


s1 = "0ec17c9dabb8955c5dfb9cef627ddb4d"
s2 = "4ca00ff4c898d61e1edbf1800618fb28"

print(xor_hexstr(s1, s2))

выход Basic CBC mode e

person falsetru    schedule 11.07.2013