암호학을 위해 python을 사용하다보면 bytes 객체를 사용할 일이 굉장히 많다. python에서는 주로 기존의 문자열을 bytes 객체로 바꾸고 16진수 형으로 바꾸어서 xor, and, or 연산등을 한다.
a = b'ffff0000'
b = b'12341234'
다음과 같이 bytes 객체를 선언하고 and 연산을 한다고 가정해보자.
우리는 당연히 b'12340000'을 기대한다.
하지만 python을 이용해서 코드를 구동 시 예상과는 다른 결과에 당황한다.
_and = lambda a, b: bytes([i&j for i, j in zip(a, b)])
print(_and(a,b))
>>> b' ""$000 '
그렇다면 우리가 원하는 계산을 수행하기 위해서는 어떤 연산을 수행해줘야 할까.
a = bytes.fromhex(a.decode())
b = bytes.fromhex(b.decode())
print(a)
>>> b'\xff\xff\x00\x00'
print(b)
>>> b'\x124\x124'
temp = _and(a, b)
temp = bytes.hex(temp).encode()
print(temp)
>>> b'12340000'
다음과 같은 연산을 통해 temp로 원하는 계산을 받고, temp를 다시 우리가 기존에 이용했던 형태로 변환하는 것을 볼 수 있다.
결국, b'ffff0000' 과 b'\xff\xff\x00\x00'이 단순히 표현 방식만 다른 것이 아니라 객체 생성 방식이나 갖고 있는 값 자체가 다르다는 것이다.
b'ffff0000'과 b'\xff\xff\x00\x00' 뭐가 다른가?b'ffff0000'요 친구는 bytes 객체로 [102, 102, 102, 102, 48, 48, 48, 48]으로 저장된다. 102와 48은 각각 'f'와 '0'의 ASCII 코드로 b'ffff0000'이와 같은 표현은 단지 따옴표로 감싸고 있는 문자열을 ASCII 코드로 변환하여 bytes 포멧으로 저장한 것 뿐이다.
b'\xff\xff\x00\x00'요 친구는 동일하게 bytes 객체이지만, 이스케이프 문법을 이용하여 생성되었다. \x 이후에 표시되는 두 문자는 실제로 해당 헥스값을 바이트 값으로 가지는 친구이다. 그리고 만약 그 헥스 값(바이트 값)이 str으로 표현될 수 있는 값이 있다면 이는 그 값으로 표시된다.
a = b'ffff0000'
# b'ffff0000'에서 b'\xff\xff\x00\x00'으로
a = bytes.fromhex(a.decode())
>>> a = b'\xff\xff\x00\x00'
# b'\xff\xff\x00\x00'에서 b'ffff0000'으로
a = bytes.hex(a).encode()
>>> a = b'ffff0000'
하나만 알면 그거의 완전 역함수가 반대로 변환하는 것임을 유도할 수 있따!!