본문 바로가기

개발/Java

암호화란? (ECB 샘플 코드)

암호화 분류
1. 대칭키 방식
-암호화키와 복호화키가 같음
-키 전송 필요
-키 관리 복잡
-인증 고속
-구현 방식 : 블록, 스트림
-알고리즘 DES, 3-DES, SEED, ARIA, RC-4, AES 등
2. 비대칭키 방식
-암호화키와 복호화키가 다름
-키 전송 불필요
-키 관리 단순
-인증 저속
-구현 방식 : 소인수분해, 이산대수
-알고리즘 : RSA, DSA 등
3. 해쉬함수

 


스트림 기반 암호화와 블록 기반 암호화
1. 스트림 기반 암호화
-비트단위로 암호화 하는 방식
-LFSR, MUX Generator 등의 알고리즘
-속도가 빠르고 오류 전파 현상이 없음.
-주로 오디오/비디오 스트리밍 시에 사용됨.
2. 블록 기반 암호화
-블록 단위로 암호화
-DES, AES, IDEA, SEED 등의 암호화 알고리즘
-데이터 전송, 스토리지 저장등에 이용.

 


암호화 알고리즘의 설계 원칙
혼돈과 확산
1. 혼돈
-평문의 작은 변화가 암호문에 어떤 변화를 줄 지 예측할 수 없어야 한다는 원칙. 평문 1bit의 변화가 암호문에 어떠한 영향을 가져올 지 예측 불가하다는 것을 의미함.

2. 확산
-평문을 구성하는 비트들이 여러 개의 암호문 비트들에 분산되어야 한다는 원칙, 평문의 특정 자리를 바꾸었을 때 암호문의 특정 자리가 바뀌어서는 안되다는 것을 의미.


암호화 방식의 운영 모드 종류
1.ECB Mode
블록 단위로 순차적 암호화하여 암호문들을 순차적으로 연결하는 방식
암호키가 동일한 경우 한개의 블록이 복호화 되면 나머지 블록도 복호화 할 수 있는 단점이 있다.
A를 암호화 -> 항상 B가 나와 역추적이 쉽고 보안에 취약


2.CBC Mode
ECB의 단점을 보완했고 암호화 키에 IV라는 값을 추가해 A를 암호화 하면 항상 B가 나오던 문제를 해결하여 역추적을 불가능하게 만듬. 그러나 중간자 공격에 취약해 A를 암호화 하여 B가 나왔는데 이게 진짜 A를 암호화 한건지 검증할 수 없다.


3.GCM Mode
CBC의 취약점을 보완했다.데이터 값의 HASH가 암호문에 포함되어 있어 복호화시 실제 그 데이터가 맞는지 검증하는 역할이 추가됨.

 


Cipher 클래스는 thread-safe하지 않기 때문에 암호화방식 하나당 하나의 클래스를 만들어서 사용해야한다.

아래는 ECB mode를 사용한 샘플입니다.

GCM은 제가 조금 더 공부를 한 뒤 코드를 올리겠습니다.

public class AesEcbUtils {
	private static Cipher cipher;
	private static SecretKey secretKey;
	private static String encryptKey;
	
	public AesEcbUtils(String encryptKey) throws NoSuchAlgorithmException, NoSuchPaddingException {
		AesEcbUtils.encryptKey = encryptKey;
		AesEcbUtils.secretKey = new SecretKeySpec(Arrays.copyOf(AesEcbUtils.encryptKey.getBytes(), 16), "AES");
		AesEcbUtils.cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
	}
	
	public byte[] encrypt(byte[] message) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
		cipher.init(Cipher.ENCRYPT_MODE, AesEcbUtils.secretKey);
		return cipher.doFinal(message);
	}
	
	public byte[] decrypt(byte[] message) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
		cipher.init(Cipher.DECRYPT_MODE, secretKey);
		return cipher.doFinal(message);
	}
}
public class AesTest {
	private static final String aesEncryptionKey = "encryptKey!@#";
	public static void main(String[] args) {
		try {
			String message = "aes encryption message test";
			AesEcbUtils aesEcbUtils = new AesEcbUtils(aesEncryptionKey);
			String encryptedMessage = Base64.getEncoder().encodeToString(aesEcbUtils.encrypt(message.getBytes("UTF-8")));
			System.out.println(encryptedMessage);
			String decryptedMessage = new String(aesEcbUtils.decrypt(Base64.getDecoder().decode(encryptedMessage)));
			System.out.println(decryptedMessage);
			
		}catch(Exception e) {
			e.printStackTrace();
		}
		
	}
}

'개발 > Java' 카테고리의 다른 글

Import vs Import static  (0) 2021.06.17
Shallow copy와 Deep copy  (0) 2021.03.25
Java 배열 정렬  (0) 2021.02.22
Scanner vs BufferedReader 비교  (0) 2021.02.10
로컬 java 프로세스를 jconsole로 모니터링  (0) 2020.06.23