ℹ️ AES-128 수행시, 8비트마다 바이트 치환을 16번 수행함 (즉, 4x4 배열이 나옴)
def bytes2matrix(text):
""" Converts a 16-byte array into a 4x4 matrix. """
return [list(text[i:i+4]) for i in range(0, len(text), 4)]
def matrix2bytes(matrix):
""" Converts a 4x4 matrix into a 16-byte array. """
# 매트릭스의 행을 각각 가져와서, 행 내에 있는 각각의 원소들에 대해 chr 연산 수행
return ''.join(map(str, [''.join(map(str, chr(element))) for element in sum(matrix, [])]))
matrix = [
[99, 114, 121, 112],
[116, 111, 123, 105],
[110, 109, 97, 116],
[114, 105, 120, 125],
]
print(matrix2bytes(matrix))
ℹ️ Round Keys에서는 state와 round_key를 XOR 연산하여 비선형을 통해 암호의 강도를 높임
state = [
[206, 243, 61, 34],
[171, 11, 93, 31],
[16, 200, 91, 108],
[150, 3, 194, 51],
]
round_key = [
[173, 129, 68, 82],
[223, 100, 38, 109],
[32, 189, 53, 8],
[253, 48, 187, 78],
]
def add_round_key(s, k):
# state와 round_key의 각 원소를 XOR 연산을 수행하고, 줄지어 출력함
return ''.join(map(str, [ chr(s[y][x] ^ k[y][x]) for y in range(4) for x in range(4) ]))
print(add_round_key(state, round_key))
JACK11
은 11비트 길이의 해시함수이고, 조그마한 차이에도 엄청난 차이를 보인다고 한다.- 그래서,
JACK11
의 해시 알고리즘에 대해 아무런 정보가 없다고 할 때, (평균적으로) 잭의 비밀과 50%확률로 충돌하는 해시 값을 갖는 고유한 비밀의 수를 구하는 것이 문제이다.
import hashlib # SHA256을 위한 라이브러리
from Crypto.Util.number import bytes_to_long
N = ...
d = ...
# 해당 문장을 플래그 값으로 사용하라고 한다.
# 근데, sha256 함수에서 바이트 타입으로 매개변수를 받기 때문에 바이트로 변환한다.
sign = b"crypto{Immut4ble_m3ssag1ng}"
# hashlib에 있는 sha256 함수를 이용해서, 플래그를 바탕으로 해시 값을 생성함
sha = hashlib.sha256(sign).digest()
# 해시 값을 다시 암호화 해주는데, 그 전에 해시 값을 정수로 변환하고 작업을 진행함
print(pow(bytes_to_long(sha), d, N))
ℹ️ 문제는 중간에 제3자(해커)가 통신을 가로채 엘리스인 척, 밥인 척하며 통신할 수 있음
이번 차시에서 '프로토콜 5.0의 허점'에 대해서 생각하면서 떠올린 것인데, 암호학은 "방패를 뚫는 창, 그리고 그것을 막는 방패를 찾는 방안"의 무한 굴레라고 생각했다. 5.0 원리만 봤을 때에도 '완벽하다'고 생각했는데, 실질적으로 허점이 있다는 것을 들었을 때에는 생각하기 난감했었다. 그래도 배운 개념을 곱씹어보면서 "여기서 허점이 있겠구나"라고 떠올렸을 때 재미가 있었다. 약간 '해변가에서 반지 찾기', 혹은 '보물 찾기'와 비슷한 느낌이다. 아직 암호학을 새발의 피만큼 배워서 그렇게 느낀 것일지도 모르겠지만, 이러한 정신으로 계속해서 꾸준히 암호학에 도전해볼 생각이다.