[목차]
1. Affine 암호 프로그래밍
* 아핀 암호(Affine Cipher)를 구현하기 위한 모듈러 연산 모듈
* 아핀 암호 암복호화 프로그램
* 아핀 암호 크랙 프로그램
2. Cryptodom
* AES 데이터 암복호화
* RSA 키 생성(Generate an RSA key) 및 PEM 파일 생성
3. 블럭 암호 (이론)
* DES
* 트리플DES
* AES
* Rijndael
* 정리
[Affine 암호 프로그래밍]
1. 아핀 암호(Affine Cipher)를 구현하기 위한 모듈러 연산 모듈
■ 시저 암호(Caesar Cipher) : C = (P + K) mod 26
■ 곱셈 암호(Multiplication Cipher) : C = (P * K) mod 26
■ 아핀 암호(Affine Cipher) : C = (P * K1 + K2) mod 26
여러 실습에서 사용할 cryptomath.py 파일을 작성해 보자.
아핀(Affine) 암호 = 곱셈암호 + 시저 암호(카이사르 암호)
아핀 암호 구현을 위한 필요 지식
나머지 연산(modular)
최대 공약수(GCD, Greatest Common Divisor)
1) 나머지 연산
(수 학) 10 mod 3 : 10을 3으로 나눈 나머지
(파이썬) 10 % 3
2) 최대 공약수를 찾는 유클리드 알고리즘
용어: 약수, 공약수, 최대공약수
2000년 전의 수학자 유클리드(Euclid)는 나머지 연산을 통해 두 수의 GCD를 찾는 간단한 알고리즘을 고안했다.
■ 파이썬으로 유클리드 알고리즘 구현 => 복수 할당문 사용
-------------------------------------
def gcd(a, b):
while a != 0:
a, b = b % a, a
return b
-------------------------------------
(예) 유클리드 알고리즘 확인(손으로 풀어 보기)
만약 a = 24, b =32 라면,
a의 약수 : 1, 2, 3, 4, 6, 8, 12, 24
b의 약수 : 1, 2, 4, 8, 16, 32
a, b의 공약수 : 1, 2, 8
a, b의 최대 공약수 : 8
(예) 유클리드 알고리즘 확인(프로그램으로 확인)
만약 a = 24, b =32 라면,
첫번째 loop 돌 때(a != 0)
a , b = b % a , a
a , b = 32 % 24 , 24
a , b = 8 , 24
두번째 loop 돌 때(a != 0)
a , b = b % a , a
a , b = 24 % 8 , 8
a , b = 0 , 8
따라서, return 8
■ 아핀 암호(Affine Cipher)의 암호화
C = (P * K1 + K2) mod len(symbols)
(조건) K1, len(symbols)는 서로소 관계이어야 한다.
암호화 과정:
(ㄱ) 평문을 K1으로 곱셈
(ㄴ) K2를 더함
(ㄷ) 심볼 집합 크기로 나머지 연산
■ 아핀 암호(Affine Cipher)의 복호화
P = {(C - K2) * K1-1} mod len(symbols)
(조건) K1, len(symbols)는 서로소 관계이어야 한다.
복호화 과정:
(ㄱ) 암호문에서 K2를 뺀다.
(ㄴ) K1의 모듈러 역수 연산
(ㄷ) 심볼 집합 크기로 나머지 연산
cryptoMath.py
def gcd(a, b):
# 유클리드 알고리즘으로 a와 b의 GCD(최대 공약수)를 return 한다.
while a != 0:
a, b = b % a, a
return b
def find_mod_inverse(a, m):
# "a * x % m = 1"을 만족하는 a와 m의 모듈러 역수를 return 한다.
if gcd(a, m) != 1:
return None # a와 m이 서로소 관계가 아니면 모듈러 역수가 없다.
# 확장 유클리디안 알고리즘으로 계산한다.
u1, u2, u3 = 1, 0, a
v1, v2, v3 = 0, 1, m
while v3 != 0:
q = u3 // v3 # "//"은 정수 나눗셈 연산자이다.
v1, v2, v3, u1, u2, u3 = (u1 - q * v1), (u2 - q * v2), (u3 - q * v3), v1, v2, v3
return u1 % m
2. 아핀 암호 암복호화 프로그램
affineChiper.py
#!/usr/bin/python3 # # 아핀 암호 # # (0) 준비 : cryptomath.py # (1) 입력 : 평문 메시지, 암호화 키, 모드(encrypt|decrypt) # (2) 출력 : 암호화문 또는 복호화문 # (3) 기능 : 아핀 암호를 사용하여 암호화하고 복호화 할 수 있는 프로그램을 제작한다. |
import os
import sys
import random
try:
import cryptomath
except Exception as e:
sys.exit('Error:', e)
SYMBOLS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890 !?.'
def main():
my_message = """A computer would deserve to be called intelligent if it could deceive a human into believing that it was human. -Alan Turing"""
my_key = 2894
enc_msg = encrypt_message(my_message, my_key)
print("Plaintext :", my_message)
print("Ciphertext: ", enc_msg)
dec_msg = decrypt_message(enc_msg, my_key)
print("Decrypted :", dec_msg)
def decrypt_message(msg, key):
key_a, key_b = get_key_parts(key)
check_keys(key_a, key_b, 'decrypt')
# P = ((C - K2) * K1(-1)) mod len(SYMBOLS)
plaintext = ''
for symbol in msg:
#print(symbol)
if symbol in SYMBOLS:
symbol_index = SYMBOLS.find(symbol)
mod_inverse_of_key_a = cryptomath.find_mod_inverse(key_a, key_b)
if mod_inverse_of_key_a is not None:
affine_index = (symbol_index - key_b) * mod_inverse_of_key_a % len(SYMBOLS)
#print(affine_index)
plaintext += SYMBOLS[affine_index]
else:
plaintext += symbol
return plaintext
def encrypt_message(msg, key):
# input : str(msg), int(key)
# output : str(enc_msg)
# function: affine cipher
key_a, key_b = get_key_parts(key)
#print(key_a, key_b)
check_keys(key_a, key_b, 'encrypt')
# * affine cipher : C = (P * K1 + K2) mod len(SYMBOLS)
ciphertext = ''
for symbol in msg:
if symbol in SYMBOLS:
symbol_index = SYMBOLS.find(symbol)
affine_index = (symbol_index * key_a + key_b) % len(SYMBOLS)
#print(symbol, symbol_index)
ciphertext += SYMBOLS[affine_index]
else:
ciphertext += symbol
return ciphertext
def check_keys(key1, key2, mode):
if key1 == 1 and mode == 'encrypt':
sys.exit('Cipher is weak if key A is 1. Choose a different key.')
if key2 == 0 and mode == 'encrypt':
sys.exit('Cipher is weak if key B is 0. Choose a different key.')
if key1 < 0 or key2 > len(SYMBOLS) -1:
sys.exit('Key A must be greater than 0 and key B must be between 0 and %d' % (len(SYMBOLS) - 1))
if cryptomath.gcd(key1, len(SYMBOLS)) != 1:
sys.exit('key A (%s) and the symbol set size (%s) are not relatively prime. Choose a different key.' % (key_a, len(SYMBOLS)))
def get_key_parts(key):
# input : int(key)
# output : int(key1), int(key2)
# funcrion :
key1 = key // len(SYMBOLS)
key2 = key % len(SYMBOLS)
return key1, key2
if __name__ == '__main__':
main()
3. 아핀 암호 크랙 프로그램
affineHack.py
#!/usr/bin/python3 # # 2. 아핀 암호 해킹 # # (0) 준비 : dictionary.txt, affineCiper.py, detectEnglish.py, cryptomath.py # (1) 입력 : 아핀 암호을 이용한 암호화된 메시지(my_message) # (2) 출력 : 아핀 암호 해킹을 통해 얻은 평문 # (3) 기능 : 암호문을 입력으로 받아서 아핀 암호 해킹을 통해 평문을 얻는다. |
import sys
import os
try:
import cryptomath
import detectEnglish
import affineCipher
except Exception as e :
sys.exit('Error :', e)
def main():
my_message = """5QG9ol3La6QI93!xQxaia6faQL9QdaQG1!!axQARLa!!AuaRLQADQALQG93!xQxaGaAfaQ1QX3o1RQARL9Qda!AafARuQLX1LQALQI1iQX3o1RNQ-5!1RQP36ARu"""
hack_affine(my_message)
def hack_affine(msg):
# input : str(msg)
# output : affine crack action
print('Hacking started.')
print('Press <CTRL + C> or <CTRL + D> to quit at any time.')
start_key = len(affineCipher.SYMBOLS)+1
end_key = len(affineCipher.SYMBOLS) ** 2
for key in range(start_key, end_key):
key_a = affineCipher.get_key_parts(key)[0]
if cryptomath.gcd(key_a, len(affineCipher.SYMBOLS)) != 1 :
continue
decrypted = affineCipher.decrypt_message(msg, key)
print('Tried key %s |%s|' % (key, decrypted[:40]))
if detectEnglish.is_english(decrypted):
print()
print('Possible encryption hack:')
print('Key: %s' % key)
print('Decrypted plaintext: ' + decrypted[:200])
print()
print('Enter D for done, or just press Enter to continue hacking.')
response = input('> ')
if response.strip().upper().startswith('D'):
return decrypted
return None
if __name__ == '__main__' :
main()
[Cryptodome]
https://www.pycryptodome.org/en/latest/
1. AES 데이터 암복호화
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
import os
data = 'hello world'.encode()
#print(get_random_bytes(16))
key = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_EAX)
#print(cipher.encrypt_and_digest(data))
ciphertext, tag = cipher.encrypt_and_digest(data)
fd = open('encrypted.bin', 'wb')
[fd.write(x) for x in (cipher.nonce, tag, ciphertext)]
fd.close()
print(open('encrypted.bin', 'rb').read())
print('----------------------------------------------------------')
fd2 = open('encrypted.bin', 'rb')
nonce, tag, ciphertext = [fd2.read(x) for x in (16, 16, -1)]
cipher2 = AES.new(key, AES.MODE_EAX, nonce)
data = cipher2.decrypt_and_verify(ciphertext, tag)
print(data.decode())
2. RSA 키 생성(Generate an RSA key) 및 PEM 파일 생성
RSA 키 쌍을 생성하여 비밀 번호로 보호되는 파일로 저장한다.
사전 공격을 막기 위해 암호화 키 파생 기능을 사용한다.
또한, RSA 공개키를 ASCII/PEM 형식으로 파일에 저장한다.
from Crypto.PublicKey import RSA
secret_code = "Unquessable"
key = RSA.generate(2048)
print('==================private key===================')
print(key)
encrypted_key = key.export_key(passphrase=secret_code, pkcs=8,
protection="scryptAndAES128-CBC")
print(encrypted_key) ; print()
fd = open('rsa_key.bin', 'wb')
fd.write(encrypted_key)
fd.close()
print('=================Public Key=====================')
print(key.publickey())
print(key.publickey().export_key())
[블럭 암호]
[DES]
1. DES(Data Encryption Standard)란?
DES/3DES(TDES) => AES
1) 대칭/비대칭, 대칭키/비밀키
대칭(Symmetric) 암호 알고리즘 <--> 비대칭(Asymmetric) 암호 알고리즘
비공개키 암호 알고리즘 <--> 공개키 암호 알고리즘
대칭키(Symmetric Key) <--> 비대칭키(Asymmetric Key)
= 비밀키(Secret Key)/공유키 <--> 공개키(Public Key)/개인키(Private Key)
DES 알고리즘은 암호문을 작성할 때 사용하는 암호키와 암호문을 해독할 때 사용하는 해독키가 같다. 따라서, 이 키는 절대로 외부에 유출되지 않도록 관리해야 하여 비밀키(Secret Key)라고 부른다.
또한, 양쪽 시스템이 동일 키를 사용한다고 해서 대칭키(Symmetric Key)라고도 한다. 이처럼 외부 사용자에게 노출되지 않아야 하는 암호키로 암호화하는 알고리즘을 비공개키 알고리즘이라고 한다.
2) DES(Data Encryption Standard)
https://en.wikipedia.org/wiki/Data_Encryption_Standard
DES(Data Encryption Standard)는 1977년에 미국의 연방 정보 처리 표준 규격(FIPS)으로 채택된 대칭
암호이다. DES는 64비트(8비트 parity, 56비트 + 8비트)의 키를 적용하여 64비트의 평문을 64비트의 암호문으로 암호화 시키는 대칭형 블록 암호이다. 이때, 암호문은 16번(16라운드)의 반복을 통해 만들어지는데, 이때 16번의 반복 동안 라운드 함수를 적용하고, 이때 라운드 함수에 적용되는 키는 라운트 키이다. 라운트 키는 키 스케줄에 의해 라운드 키를 발생시킨다. DES의 블록 암호 구조는 파이스텔(Feistel Cipher) 방식이다.
(AES의 블록 암호 구조는 SPN(Substitution Permutation Network) 구조이다.)
DES 알고리즘에서 사용하는 함수
- 대체(Substitution)
- 치환(Permutation)
대체와 치환은 1949년도에 클라우드 샤논(Claude Shanon)이 제시한 혼돈(Confusion)과 확산(Diffusion)이라는 두 가지 개념에 기반을 두고 있다.
전사 공격으로 해독 할 수 있는 수준
■ DES 콘테스트(DES Challenge)
1997년 DES Challenge I => 96일
1998년 DES Challenge II-1 => 41일
1998년 DES Challenge II-2 => 56시간
1999년 DES Challenge III => 22시간 15분
2. DES 암호화/복호화
64비트 평문을 64비트 암호문으로 암호화하는 대칭 암호 알고리즘
키의 비트 길이는 56비트(64비트 = 56비트 + 8비트 parity)
64비트 평문(비트열)을 하나의 단위로 모아서 암호화
DES 취약성 예제(출처: http://www.secmem.org/blog/2019/02/06/block-cipher/)
DES 알고리즘에서 활용되는 키는 56비트이고 암호를 만들 당시에는 충분한 길이였으나 컴퓨터의 성능이 점차 개선됨에 따라 DES는 자체적인 취약점이 발견되지 않았음에도 불구하고 키가 짧아 2016년에 들어서는 GeForce GTX 1080 Ti GPU로 모든 키를 30일 이내에 확인할 수 있는 상황이 되어 더 이상 제 기능을 할 수 없는 암호 알고리즘이 되었습니다. |
[참고] "3. 취약점"
[참고] NIST, TDES 암호알고리즘의 사용제한 권고 동향 - 금융보안원
http://www.fsec.or.kr/common/proc/fsec/bbs/42/fileDownLoad/1605.do
[참고] 차분공격
https://ko.wikipedia.org/wiki/차분_공격
[트리플 DES의 현황]
현재도 은행등에서 아직 사용
처리 속도는 빠르지 않고
안정성면에서도 풀려버린 사례가 있음
우리나라에서는 3-DES를 표준으로 정하지 않음
우리나라 국가표준은 SEED(Feistel 구조), ARIA(SPN 구조)
[참고] 국산 암호기술 - SEED(Feistel 구조)
https://seed.kisa.or.kr/kisa/algorithm/EgovSeedInfo.do
[참고] 국산 암호기술 - ARIA(SPN 구조)
https://seed.kisa.or.kr/kisa/algorithm/EgovAriaInfo.do
[AES]
1. AES 란?
AES(Advanced Encryption Standard)
DES를 대신한 새로운 표준 대칭 암호 알고리즘
AES의 후보로서 다수의 대칭 암호 알고리즘을 제안했지만, 그중에서 Rijndael 이라는 대칭 암호 알고리즘이 2000년에 AES로서 선정
2. AES 선정 과정
NIST(National Institute of Standard and Technology)에서
공모 경쟁방식에 의한 표준화(Standardization by competition)
조건
제한 없이 무료로 이용
ANSI C와 Java에 의한 구현
암호해독에 대한 강도의 평가
암호 알고리즘 설계 규격과 프로그램 공개
3. AES 최종 후보 및 선정
1차 심사 통과: 15개
CAST256, Crypton, DEAL, DFC, E2, Frog, HPC, LOKI97, Magenta, MARS, RC6, Rijndael, SAFER+, Serpent, Twofish
2차 심사 통과: 5개
MARS : IBM
RC6 : RSA
Rijndael : Daemen, Rijmen
Serpent : Anderson, Biham, Knudsen
Twofish : Counterpane
[Rijndael]
1. Rijndael 이란?
벨기에 연구자 Joan Daemen과 Vincent Rijmen이 설계한 블록 암호알고리즘
블록 길이 : 128비트
키의 비트 길이: 128비트(16 bytes), 192비트(24 bytes), 256비트(32 bytes)
2. Rijndael 암호화/복호화
SPN 구조 = (혼돈)Confusion + (확산)Diffusion
SPN 구조는 Substitution Layer와 Permutation Layer 이용하여 Confustion과 Diffusion을 만족시켜는 암호다.(http://reinliebe.tistory.com/76)
SPN(Substitution-Permutation Network) 구조 - 복수의 라운드(round)로 구성(10~14)
SubBytes - 바이트 대체
ShiftRows - 행 이동
MixColumns - 열 섞기
AddRoundKey - 라운트 키와 XOR 연산
3. Rijndael 해독
Rijndael 알고리즘의 수학적 구조
Rijndael 수식을 수학적인 조작에 의해 풀수 있다면, Rijndael을 수학적으로 해독할 수 있을 것이다.
Rijndael에 대한 유효한 공격은 현재로서는 발견되지 않았다.
[정리]
어떤 암호를 사용하면 좋은가?
(X) DES/3DES => (0) AES
DES는 사용하지 말 것!
단, 과거 소프트웨어와의 호환성 유지를 위해 필요.
트리플 DES는 호환성 때문에 앞으로도 당분간 사용,
점차 AES로 대체
AES(Rijndael)
고속
다양한 플랫폼
현재까지 안전
사용 권장
AES 최종 후보 5개도 사용가능
[참고] AES 관련 정보
http://index-of.co.uk/Cryptology/06-AES.pdf
http://huammmm1.tistory.com/381
대칭 암호
* 블록 암호 : DES/3DES(시험에 많이 나옴), AES
* 스트림 암호
비대칭 암호
* 공개키 암호
* 공개키 서명
해시 암호
1. 대칭키 암호
스트림 암호(ex: ARC4, chacha20, XchaCha20, Salsa20)
블록 암호(ex: DES/3DES, AES, SEED, ARIA)
2. DES(Data Encryption Standard) - Feistel 구조
키 : 56비트
* 키(56비트) => 키 스케줄 => 서브키(48비트 x 16)
암호시스템 : Feistel 구조, F함수, S-BOX
입력 : 64비트 평문블록
출력 : 64비트 암호문
3. 3DES(Triple DES) - Feistel 구조
DES-EDE2
DES-EDE3
4. AES(Advanced Encryption Standard) - SPN 구조
키 : 128비트, 192비트(128+64), 256비트(128+128)
암호시스템 : SPN 구조
입력 : 128비트 평문블록
출력 : 128비트 암호문
'정보보안공부 > 정보보안전문과정' 카테고리의 다른 글
정보보안 과정 Day80-1 : 3DES 실습 (0) | 2020.12.30 |
---|---|
정보보안 과정 Day80 : 암호학 5 (0) | 2020.12.30 |
정보보안 과정 Day78 : 암호학 3 (0) | 2020.12.28 |
정보보안 과정 Day77 : 암호학 2 (0) | 2020.12.27 |
정보보안 과정 Day 76-2 : 암호학 실습 (0) | 2020.12.23 |