해당 게시물에서 이용하는 실습환경은 다음과 같이 구축되었습니다.
- Source Authentication
- Message Integrity
Source Ahthentication: 이거 진짜 너가 보낸거 맞아?
Message Integrity: 이 메시지 내용 변조 안됐어?
어떻게 해야 메시지 인증을 보장할 수 있을까?
=> Source Authentication 보장.
=> Message Integrity 보장.
기밀성(Confidentiality)은 중요하지 않고 무결성(Integrity)만을 보장하기 위해서 사용하는 방법
=> 파일의 내용이 변조되지 않았나?가 더 중요할 때...
는 두 사람 A, B간에 공유된 키이다.
단방향 해시함수(One-way Hash Function)를 사용하여 MAC을 생성할 때, 키가 없는 경우 Source Authentication과 Message Integrity를 보장할 수 없다.
1번의 경우,
메시지를 해시 함수를 사용하여 생성된 해시코드를 대칭키를 이용하여 암호한다.
해당 암호문과 메시지를 함께 전달하여 해시 코드를 공격자로부터 보호함.
참고
메시지를 왜 해시 함수에 넣을까?
MAC을 생성하는 방법은 매우 많고 암호화하는 방식도 많지만, 대칭키 암호가 비대칭키 암호보다 빠르다
즉, 암호화를 할 메시지의 크기가 클 수록 비대칭키 암호를 사용하면 시간이 더 걸린다.
해시 함수의 특성 상, 임의 길이의 입력값이 들어와도 항상 같은 길이의 결과값을 가진다.
=> 메시지의 내용이 길수록 해시 함수를 거치면, 항상 일정한 길이로 유지하여 소요시간을 단축할 수 있다.
2번의 경우,
1번과 동일하지만, 송신자 측에서는 본인의 개인키로 암호를 진행하고 수신자 측에서는 송신자의 공개키로 복호화를 한다는 점에 유의하자.
참고
왜 송신자의 공개키가 아니라 개인키로 암호화를 진행할까?
MAC을 사용하는 이유 중 Source Authentication에 대해서 생각해보자.
'이거 정말 너가 보낸거니?'라는 질문에 두 가지 상황으로 빗대어보자.
1. 송신자의 공개키로 암호화
=> 누구나 공개키에 접근할 수 있다. (공격자가 송신자의 공개키로 생성하여 전달가능 (Forge, 위조 가능)
2. 송신자의 개인키로 암호화
=> 해당 개인키는 송신자만이 가지고 있다. (그럼? 당연히 이 메시지를 보낸 사람은 송신자가 맞구나!)
+ 수신자의 공개키를 사용하면 어떨까?
=> 수신자의 개인키는 접근할 수 없으니 제외.
=> 수신자의 공개키를 사용하는 것은 의미 없지..
(1번과 같은 이유 + 이거 정말 너가 보낸거니?에 대한 답이 될 수 없죠)
3번의 경우,
어떤 비밀값을 메시지와 함께 해시함수에 넣어서 해시코드를 생성한다는 점에 유의하자
해시함수의 산사태 효과(Avalanche effect)에 의해서 비밀값을 정확히 알지않는 한, 해시코드의 값이 전혀 달라짐을 이용한 방법
안전한 해시함수가 되려면 어떤 조건이 필요할까?
위 세 성질을 만족해야 한다.
즉, 해시값으로부터 원래의 입력값의 관계를 찾기 어려워야 한다.
자세한 설명은 생략..(귀찮음)
SHA(Secure Hash Algorithm)는 1993년 미국 NSA에서 개발한 암호학적 해시 함수들의 모음이다.
개발 시기와 종류에 따라서 SHA-0, SHA-1,..., SHA-3로 구분한다.
자세한 내용은 생략..(귀찮음2)
암호학적 해시 함수를 사용하여 MAC을 생성하는 방법이다.
자세한 내용은 생략..(귀찮음3)
설명 요청있으면 고민좀 해볼게요...
기본 사용법은 다음과 같다.
from Crypto.Hash import SHA512
# SHA512.new()를 사용하여 해시 오브젝트를 생성
hash_obj = SHA512.new(data = b'message')
# update()를 사용하여 해시할 메시지를 추가한다.
hash_obj.update(b'message2')
# digest()를 사용하여 해시값 확인
print(hash_obj.digest())
# hexdigest()를 사용하여 hex값으로 해시를 확인
print(hash_obj.hexdigest())
SHA512.new()를 활용하여 객체를 생성할 때, data의 type은 Byte String이어야 함에 유의해라.
SHA512를 사용하여 첫 24bits가 0이 나오는 입력값을 찾아라.
무차별 대입 공격(Brute-force attack)을 사용하도록 한다.
from Crypto.Hash import SHA512
iv = 0
while True:
hash_hexdigest = SHA512.new(data=str(iv).encode("utf-8")).hexdigest()
if hash_hexdigest.startswith("000000"):
print("END")
break
else:
iv += 1
정수형 0을 이용하여 1씩 더해가며 해시값을 찾으려고 했다.
hexdigest를 이용하여 16진수로 줄였기 때문에 0이 6개(24bits)로 시작하는 해시값이 나올때까지 무한 반복하며 해시를 생성한다.
프로그램은 1분 20초 가량 소요되는데, fork()를 활용하여 멀티 프로세싱하게 코드를 작성하면 10개의 프로세스를 생성할 경우 14초가량 소요된다.
멀티쓰레드 이용하면 얼마나 더 줄여지려나...
- message.txt를 읽어서 HMAC을 생성하여 HMAC.txt로 저장하는 코드를 작성하라.
- 해당 HMAC.txt를 읽어서 파일의 무결성을 검사하는 코드를 작성하라.
message.txt
Hi my name is glico...lol
1번 코드
from Crypto.Hash import HMAC
payload = b""
# message.txt 읽기
with open("message.txt", "rb") as f:
payload += f.read()
# HMAC생성 후, payload와 함께 HAMC.txt 생성
with open("HMAC.txt", "ab") as f:
h = HMAC.new(b"password")
h.update(payload)
f.write(payload)
f.write(h.hexdigest().encode("utf-8"))
HMAC.txt
Hi my name is glico...lol
0123456789abcdef..(대충 hash값 적혀있음)
2번 코드
from Crypto.Hash import HMAC
payload = b""
# HMAC.txt 읽기
with open("HMAC.txt", "rb") as f:
payload += f.read()
# 새롭게 HMAC 생성 (원래의 메시지 내용만 읽어서 HMAC생성)
h = HMAC.new(b"password")
h.update(payload[: filesize - 32])
# 새로운 HMAC과 기존의 HMAC 비교
original = payload[filesize - 32 : ]
new = h.hexdigest().encode("utf-8")
# 무결성 검사
if new == original:
print("OK")
else:
print("F**k")