팀프로젝트/SpringBoot

스프링 부트 팀플) 20240309_암호화와 복호화

일일일코_장민기 2024. 3. 9. 22:51
728x90
오늘 이전 작업 올리고 6시간이 흘렀다...
그동안 암호화와 복호화만 열심히 했다...

원래는 스프링 세큐리티를 사용한 암호화/복호화를 해보려고 했었다.

https://hou27.tistory.com/entry/Spring-Boot-Spring-Security-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%95%94%ED%98%B8%ED%99%94

 

[Spring Boot] Spring Security 적용하기 - 암호화

프로젝트를 진행하면서 사용자 시스템을 구축한다면 필연적으로 인증 로직도 구현해야한다. 이 과정에서 만약 사용자의 비밀번호를 평문(Plain Text)으로 저장한다면, 심각한 보안상 문제를 초래

hou27.tistory.com

https://goddaehee.tistory.com/321

 

[스프링부트] Spring Boot 설정파일(yaml, properties) 암호화 (with Jasypt)

[스프링부트] Spring Boot 설정파일 암호화 (with Jasypt) 안녕하세요. 갓대희 입니다. 이번 포스팅은 [ Spring Boot 설정파일 암호화 하기 ] 입니다. : ) ※ application.yml 이나 application.properties 파일에 DB의 비

goddaehee.tistory.com

https://ye-geeee.tistory.com/74

 

[Spring Boot] Jasypt으로 암호화 적용하기

개발 환경 - gradle version: 7.4.1 - spring boot version: 2.6.13 - 언어: Kotlin Spring Boot에 Jasypt library 적용 프로젝트에 Jayspt를 적용해 봅시다! Dependency 추가 Spring boot에서는 jasypt-spring-boot-starter(maven repository 링

ye-geeee.tistory.com

https://derveljunit.tistory.com/339

 

[Spring & Boot][2.6.2] 스프링 프로퍼티 암복호화 Jasypt 예제

스프링부트 2.6.2 버전을 기준으로 작성되었습니다. 예제 Github 주소 https://github.com/Derveljun/derveljun-jasypt-example GitHub - Derveljun/derveljun-jasypt-example Contribute to Derveljun/derveljun-jasypt-example development by creat

derveljunit.tistory.com

특히 이대로 만들었다면 마지막 링크처럼 만들어졌을 듯하다.

 

그러다가 이 포스팅을 보았다.

 

https://jin0904.medium.com/springboot-%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%EC%95%94%ED%98%B8%ED%99%94-%EB%B0%8F-%EB%B3%B5%ED%98%B8%ED%99%94-a2bbb498cb40

 

[SpringBoot] 비밀번호 암호화 및 복호화

한국인터넷진흥원(KISA)에서 제공하는 KISA_SEED_CBC 알고리즘 소스 코드 기준으로 작성했습니다.

jin0904.medium.com

 

캬~! 국내 전문가가 만든 128비트 블록 암호 알고리즘이라니
이쪽으로 만들어 보기로 했다.
(앞에 스프링 세큐리티로 2시간이 날아갔다)

 

https://seed.kisa.or.kr/kisa/Board/17/detailView.do

113페이지의 매뉴얼도 같이 딸려왔다. 이런 젠장
방법 1을 쓰면 되겠군
솔직히 뭐가 좋은지는 잘 모르겠다. 사람들이 CBC를 많이 쓰니 따라가기로 했다.

메뉴얼曰  pbszUserKey랑 pbszIV는 반드시 16 Bytes.
그런데 시험해보니 16 Bytes를 넘겨도 잘 작동됐다.
아무튼 소스코드를 집어넣었다.

 

어찌어찌 해석한 암호화와 복호화

 

SEED_CBC_Encrypt 메서드

- 사용자키(pbszUserKey), 초기화 벡터(pbszIV), 암호화할 메세지(message), 메세지 오프셋과 길이를 입력한다. 
- 메시지를 패딩하여 블록 크기의 배수로 만들고, SEED_CBC 초기화 및 처리를 통해 암호화한다.

 

SEED_CBC_Decrypt 메서드

- 사용자키(pbszUserKey), 초기화 벡터(pbszIV), 복화할 메세지(message), 메세지 오프셋과 길이를 입력한다. 

- 복호화를 수행하기 전에 패딩을 확인하고, 패딩이 올바르지 않으면 null을 반환한다.

- SEED_CBC 초기화 및 처리를 통해 복호화를 수행하고, 결과로 원문을 반환한다.

 

그렇게 만들어진 컨트롤러

 

package com.moonBam.controller.member;

import java.nio.charset.StandardCharsets;

import org.springframework.stereotype.Controller;

import com.moonBam.config.KISA_SEED_CBC;

@Controller
public class TestTest {
    private static final byte[] pbszUserKey = "jthe!minthe@kee#".getBytes();	//반드시 16바이트(메뉴얼 44pg)
    private static final byte[] pbszIV = "hetalpsuemekete!".getBytes();			//반드시 16바이트(메뉴얼 44pg)
 
    public static byte[] encrypt(String rawMessage) {
        byte[] message = rawMessage.getBytes(StandardCharsets.UTF_8);
        byte[] encryptedMessage = KISA_SEED_CBC.SEED_CBC_Encrypt(pbszUserKey, pbszIV, message, 0, message.length);
        return encryptedMessage;
    }
 
    public static String decrypt(byte[] encryptedMessage) {
        byte[] decryptedMessage = KISA_SEED_CBC.SEED_CBC_Decrypt(pbszUserKey, pbszIV, encryptedMessage, 0, encryptedMessage.length);
        return new String(decryptedMessage);
    }
}

 

매번 암호화 결과가 다르게 출력되는 것이 인상적이다.

 

현재 회원가입 시스템은 메일 전송을 통한 인증이 된다는 전제 하에 이루어지고 있다.
메일 시스템은 암호화보다는 쉬울 것 같으니 내일하고 암호화/복호화 시스템을 마저 구현해야겠다.

아마도 이런 시스템으로 구축할 듯 싶다.
1. 회원가입 시 암호화된 비밀번호 저장
2. 로그인 시 비밀번호를 입력하면 다르게 암호화된 비밀번호로 전송
3. 양쪽 암호를 동시에 복호화하여 일치를 확인

 

 

 

++++

포스트 마치려는 순간, 암호화된 데이터가 Bytes로 출력된다는 것을 깨달았다.

그러면 기존 코드가 많이 꼬이지 않을까???
간단하게 암호화된 결과를 new String으로 변환시켜서 넘겨보았다...라고 하기 전에

기존 함수의 return 값이 변형되자 에러를 사정없이 쏟았다.

그래서 함수를 하나 더 끼워넣는 꼼수를 써보니 넘어가긴 하더라

넘어간 데이터는 암호가 아니라 외계어가 되어버렸다.

 

깨지는 모습으로 보아 변환 방식이 잘못되지 않았을까? 하는 생각이 들어 Base64로 바꾸기로 했다.

 

휴...

 

잘 바뀌는 걸 확인할 수 있었다.

내일 메일 시스템 넣고 적용해보면서 고칠 부분이 생길 수도 있겠지만 일단 만족

package com.moonBam.controller.member;

import java.nio.charset.StandardCharsets;
import java.util.Base64;

import org.springframework.stereotype.Controller;

import com.moonBam.config.KISA_SEED_CBC;

@Controller
public class SecurityController {
    private static final byte[] pbszUserKey = "jthe!minthe@kee#".getBytes();	//반드시 16바이트(메뉴얼 44pg)
    private static final byte[] pbszIV = "hetalpsuemekete!".getBytes();			//반드시 16바이트(메뉴얼 44pg)
 
    //암호화 시작(String 타입으로 출력)
    public String encrypt(String mesg) {
    	byte[] byteMesg = doEncrypt(mesg);
    	String resultString = Base64.getEncoder().encodeToString(byteMesg);
    	return resultString;
    }
    
    //암호화 시스템
    public static byte[] doEncrypt(String StringMessage) {
        byte[] message = StringMessage.getBytes(StandardCharsets.UTF_8);
        byte[] byteEncryptedMessage = KISA_SEED_CBC.SEED_CBC_Encrypt(pbszUserKey, pbszIV, message, 0, message.length);
        String encryptedMessage = new String(byteEncryptedMessage);
        return byteEncryptedMessage;
    }
    
    //복호화 시작(String 타입으로 암호를 받음)
    public String decrypt(String mesg) {
    	byte[] resultByteArray = Base64.getDecoder().decode(mesg);
    	String decryptedMessage = doDecrypt(resultByteArray);
    	return decryptedMessage;
    }
 
    //복호화 시스템
    public static String doDecrypt(byte[] encryptedMessage) {
    	byte[] decryptedMessage = KISA_SEED_CBC.SEED_CBC_Decrypt(pbszUserKey, pbszIV, encryptedMessage, 0, encryptedMessage.length);
        return new String(decryptedMessage);
    }
}