6.8 Java 암호화 방법 공부(AES-256 등)

김용희·2023년 7월 18일

자바 암호화 방법 공부 (주민번호, 비밀번호 보안)

1. 주민번호 (단방향)

주민번호를 복호화(복구할 때 '복')를 할 필요는 없으므로 단방향으로 처리해도 될 듯??

개요

참조 사이트들

  1. ★ [JAVA] SHA-256 암호화 예제코드 (SALT 사용)
    https://cocoon1787.tistory.com/832
    https://cceeun.tistory.com/241

  1. 개인정보 보호법과 JAVA를 이용한 암호화 구현(SHA256, AES256)
    https://18281818.tistory.com/83

  1. 자바 MD5, SHA-256, AES256 암호화 하기
    https://offbyone.tistory.com/286

전체 코드

package com.shinhan.assetManager.user;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import org.springframework.stereotype.Component;

// 주민번호 암호화를 위한 클래스 (비밀번호는 양방향이라서 ㄴㄴ)
// 단방향 해시 함수 (One-way Hash Function) 사용
// ex. SHA-256
@Component
public class SHA256 {

	public static void main(String[] args) {
		SHA256 en = new SHA256();
		
		String pwd = "내가 암호화 하고 싶은 놈";
		System.out.println("pwd : " + pwd);
		
		// Salt 생성
		String salt = en.getSalt();
		System.out.println("salt : " + salt);
		
		// 최종 pwd 생성
		String res = en.getEncrypt(pwd, salt);
	}
	
	public String getSalt() {
		// 1. Random, byte 객체 생성
		SecureRandom r = new SecureRandom();
		byte[] salt = new byte[3];
		
		// 2. 난수 생성
		r.nextBytes(salt);
		
		// 3. byte to String (10진수의 문자열로 변경)
		StringBuffer sb = new StringBuffer();
		for(byte b : salt) {
			sb.append(String.format("%02x", b));
		}
		
		return sb.toString();
	}
	
	public String getEncrypt(String pwd, String salt) {
		String result = "";
		try {
			// 1. SHA256 알고리즘 객체 생성
			MessageDigest md;
			md = MessageDigest.getInstance("SHA-256");
			
			// 2. pwd와 salt 합친 문자열에 SHA-256 적용
			//System.out.println("pwd + salt 적용 전 : " + pwd+salt);
			md.update((pwd+salt).getBytes());
			byte[] pwdsalt = md.digest();
			
			// 3. byte to String (10진수의 문자열로 변경)
			StringBuffer sb = new StringBuffer();
			for(byte b : pwdsalt) {
				sb.append(String.format("%02x", b));
			}
			
			result = sb.toString();
			//System.out.println("pwd + salt 적용 후 : " + result);
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return result;
	}
}

2. 비밀번호 (양방향)

'비밀번호 찾기'를 했을 때 복호화(=복구)가 필요하므로 양방향으로 해줄 생각.

개요

참조 : ★
Java AES-256 양방향 암호화 제대로 알고 사용하기
https://wildeveloperetrain.tistory.com/98

전체 코드

package com.shinhan.assetManager.user;

import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.springframework.stereotype.Component;

// 비밀번호 암호화를 위한 클래스
// 단방향 해시 함수 (One-way Hash Function) 사용
// ex. AES256
// 참조 : https://wildeveloperetrain.tistory.com/98
@Component
public class AES256 {

	public static void main(String[] args) throws Exception {
		AES256 en = new AES256();
		 
		// 암호화
		String text = "암호화 하고 싶은 텍스트?";
		String encryptedText = en.encryptAES256(text);
		System.out.println(encryptedText);
		
		// 복호화
		String decryptedText = en.decryptAES256(encryptedText);
		System.out.println(decryptedText);
		
	}
	
	public static String alg = "AES/CBC/PKCS5Padding";
    private final String key = "abcdefghabcdefghabcdefghabcdefgh"; // 32byte
    private String iv = "0123456789abcdef"; // 16byte
	
	// 암호화
    public String encryptAES256(String text) throws Exception {
        Cipher cipher = Cipher.getInstance(alg);
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
        IvParameterSpec ivParamSpec = new IvParameterSpec(iv.getBytes());
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParamSpec);

        byte[] encrypted = cipher.doFinal(text.getBytes("UTF-8"));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    // 복호화
    public String decryptAES256(String cipherText) throws Exception {
        Cipher cipher = Cipher.getInstance(alg);
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
        IvParameterSpec ivParamSpec = new IvParameterSpec(iv.getBytes());
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParamSpec);

        byte[] decodedBytes = Base64.getDecoder().decode(cipherText);
        byte[] decrypted = cipher.doFinal(decodedBytes);
        return new String(decrypted, "UTF-8");
    }

}

JPA

Specified key was too long; max key length is 3072 bytes 에러

참조 :

5개 칼럼을 복합키로 하려니까 생긴 에러 (MySQL)
디폴트로 varchar2(255)인데, 이 5개를 묶어서 사용하려니 byte가 너무 길다는 에러가 떴음.
해결 방법은 간단함.
varchar2의 길이를 어느정도 줄여주면 되는 것

줄이는 방법은 다음과 같다.

profile
쓰용

1개의 댓글

comment-user-thumbnail
2023년 7월 18일

좋은 글 감사합니다!

답글 달기