- AES
공개키, 대칭 알고리즘
128,192,256 비트 세 가지 종류가 AES 표준
알고리즘
- 평문을 128비트 또는 16바이트 블록화
- 열 우선 행렬 생성(state matrix)
- KeyExpansion: 암호화 키 가져와서 추가키 생성, 각 라운드마다 key 하나 생성 -> round key
- AddRoundKey: 라운트 키의 각 바이트 XOR 상태 행렬의 바이트,
( x_{i,j} = p_{i,j} \oplus k_{i,j} ) - 일련의 라운드 수행: SubBytes -> ShiftRows -> MixColumns(마지막 라운드 제외) -> AddRoundKey
#예제에서 쓰인 블록 암호 모드는 ECB, 해당 부분 설명으로 아래서...
import string
import random
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
#암호화
def aes_encrypt(key, plaintext):
cipher = AES.new(key, AES.MODE_ECB)
ciphertext = cipher.encrypt(pad(plaintext.encode('utf-8'), AES.block_size)) #AES 사이즈 지정
return ciphertext
#복호화
def aes_decrypt(key, ciphertext):
cipher = AES.new(key, AES.MODE_ECB) #이때 key는 대칭키
decrypted_data = unpad(cipher.decrypt(ciphertext), AES.block_size)
return decrypted_data.decode('utf-8')
- DES
비밀키, 대칭 암호 알고리즘
알고리즘
- Initial permutation: 각 비트 치환
- 라운드 함수로 서로 다른 서브키로 각 비트 치환
- 블록화
- Final permutation: 한 번 더 치환
from Crypto.Cipher import DES
from Crypto.Hash import SHA256 as SHA
class myDES():
# DES 초기화
def __init__(self, keytext, ivtext):
hash = SHA.new()
hash.update(keytext.encode('utf-8'))
# keytext를 해시화했을 때 첫 8byte를 key로 함
key = hash.digest()
self.key = key[:8]
hash.update(ivtext.encode('utf-8'))
iv = hash.digest()
# ivtext를 해시화했을때 첫 8byte를 iv로 함
# iv는 CBC 모드 운영을 위한 초기화벡터를 말함
self.iv = iv[:8]
# ECB 모드로 암호화
def encrypt_ECB(self, plaintext):
# 항상 8byte 단위로 끊어서 암호화하기 때문에 평문이 8byte로 끊기지 않는다면
# padding값을 추가해 8byte로 만들어줌
while(len(plaintext) % 8 != 0):
plaintext += ' '
des = DES.new(self.key, DES.MODE_ECB)
encryptMsg = des.encrypt(plaintext.encode())
return encryptMsg
# ECB 모드로 암호화된 암호문을 복호화
def decrypt_ECB(self, ciphertext):
des = DES.new(self.key, DES.MODE_ECB)
descryptMsg = des.decrypt(ciphertext)
return descryptMsg
# CBC 모드로 암호화
def encrypt_CBC(self, plaintext):
while(len(plaintext) % 8 != 0):
plaintext += ' '
# CBC 모드에서는 iv(초기화 벡터) 값이 필요
des = DES.new(self.key, DES.MODE_CBC, self.iv)
encryptMsg = des.encrypt(plaintext.encode())
return encryptMsg
# CBC 모드로 암호화된 암호문을 복호화
def decrypt_CBC(self, ciphertext):
des = DES.new(self.key, DES.MODE_CBC, self.iv)
descryptMsg = des.decrypt(ciphertext)
return descryptMsg
- RSA
비대칭 암호 알고리즘
공개키, 비밀키 모두 사용하는데, 공개키는 암호화할 때, 비밀키는 복호화할 때 사용
알고리즘
- 두 큰 소수를 곱해서 공개키 생성
- 이때 개인키는 (공개키X개인키)mod 오일러(p*q)=1인 숫자 -> ( (e * d) \mod \Phi(n) = 1 )
( n = p * q ) (p, q는 소수)
( \Phi(n) = (p — 1) * (q — 1) )
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
def generate_keys():
key = RSA.generate(2048)
# 개인키 생성
private_key = key.export_key()
# 공개키 생성, 이때 서로 소수
public_key = key.publickey().export_key()
return private_key, public_key
# 암호화
def encrypt_message(public_key, message):
rsa_key = RSA.import_key(public_key)
# OAEP는 RSA와 함께 사용되는 Padding
cipher = PKCS1_OAEP.new(rsa_key)
encrypted_message = cipher.encrypt(message.encode())
return encrypted_message
# 복호화
def decrypt_message(private_key, encrypted_message):
# key import(개인키)
rsa_key = RSA.import_key(private_key)
cipher = PKCS1_OAEP.new(rsa_key)
decrypted_message = cipher.decrypt(encrypted_message).decode()
return decrypted_message
- 해시 함수
해시 함수들은 복호화되지 않는다. 한 번 압축함수를 거치면 되돌릴 수 없다(예측 불가능성)
해시 암/복호화 툴 사이트 (CTF에서 필요할 때 들어가기..)
4-1. SHA256
SHA 해시 함수는 1, 256, 384 등.. 다양함
어떤 입력값이든 고정된 길이 n(SHA256에서는 256)으로 변환 처리한다.
알고리즘
1) 패딩 -> 512bit의 배수가 되도록
2) 파싱 -> 32bit씩 나눈다.
3) 해싱
import hashlib #이전 암호 라이브러리와 다르다
# SHA-256 해시 객체 생성
hash_object = hashlib.sha256()
# 데이터 업데이트
hash_object.update(data.encode())
# 해시 값 추출
hash_value = hash_object.hexdigest()
4-2. MD5
128비트 길이를 만들어주는 해시 함수
SHA1보다는 안전하나 지금은 원본을 찾을 수 있는 빠른 알고리즘이 나와 잘 사용하진 않는다.
알고리즘
- 데이터 비트 오른쪽에 1
- 비트 길이 448(mod 512)되도록 0 패딩(오른쪽에)
- 마지막 64비트에 padding되기 전 데이터 길이 저장(리틀 엔디언)
- 512비트 블록으로 쪼개기
- 각 블록에 대해 연산
import hashlib
result = hashlib.md5(data.encode()).hexdigest()
- 블록 암호
평문을 분할하여 m길이*n개 블록을 만드는 알고리즘이다.
운영모드는 5가지가 있는데 ECB, CBC, CFB, OFB, CTR
- 5-1. ECB
- 블록 단위로 나누고 각 블록마다 key로 암호화
반복 공격에 취약하다.

- 5-2. CBC
- iv로 첫 블록을 암호화하고 다음 블록은 이전 암호와 평문을 xor 후 key로 암호화
초기 iv가 동일하며 출력 결과가 동일한 취약점이 있다.

- 5-3. CFB
- iv로 첫 블록 암호화하고 이후 블록은 key와 암호화 후 평문과 xor
재전송 공격에 취약하다.

- 5-4. OFB
- CFB와 이전 블록의 결과를 가져다 쓰는 위치가 다르다(그림으로 확인하기)
OFB는 xor 전 암호화 결과를 다음 블록에서 사용한다.

- 5-5. CTR
- 암호화 할 때마다 증가하는 Counter 변수를 두고, 이것을 key와 암호화
