암호화와 복호화, AesBytesEncryptor

수정이·2022년 11월 1일
0

Spring

목록 보기
14/16
post-thumbnail

암호화, 복호화

  • 암호화 : 평문을 암호문으로 변환하는 과정이다.
    • "1234" -> "aEewkd"
  • 복호화 : 암호문을 평문으로 변환하는 과정이다.
    • "aEewkd" -> "1234"

암호화 종류

  • 단방향 암호화 : 평문을 암호문으로 변환 후 복호화를 할 수 없다.
    • 예시 : 사용자가 회원가입을 진행할 시, 비밀번호를 암호화하여 DB에 저장할 때, 모든 접근자는 암호화된 비밀번호를 복호화할 수 없다.
    • 알고리즘 : 대표적으로 SHA-1, SHA-2 등이 있지만, SHA-2를 권고한다.
  • 양방향 암호화 : 평문을 암호문으로 변환 후 복호화를 할 수 있다.
    • 예시 : 사용자의 이메일, 번호 등 재사용성이 있는 정보는 암호화, 복호화 모두 이루어져야 한다.
    • 알고리즘 : 대칭키 방식, 비대칭키 방식으로 나뉜다. 대칭키는 같은 키를 사용하여 암호화, 복호화 하는 방식이고, 비대칭키는 다른 키를 사용하는 방식이다.

AesBytesEncryptor

AesBytesEncryptorSpring Security가 제공하는 양방향 암호화 클래스이다. 그 중 대칭키 방식을 사용하고, 256-bit AES 알고리즘을 사용한다.

AesBytesEncryptor bean 등록

AesBytesEncryptor를 사용하기 위해서는 Bean등록을 먼저 해줘야한다.
Spring Security를 설정한 Config 파일에 등록을 해주었다.

@Bean
public AesBytesEncryptor aesBytesEncryptor() {
    return new AesBytesEncryptor(secret, "70726574657374");
}

secret은 암호화와 복호화를 해줄 때 필요한 키이다. 키 값은 yml파일에 저장한다음 꺼내 사용하였다.
그리고 뒤에 숫자로 되어있는 문자열은 salt이다. salt는 암호화해줄 문자열에 저런 임의의 문자열을 덧붙이는걸 의미한다.
만약 비밀번호가 같은 두 사람이 있다고 생각해보자. 만약 한 사람의 비밀번호가 뚫렸다면, 다른 한 사람의 비밀번호도 같기 때문에 똑같이 뚫릴 것이다. 하지만 salt를 사용하면 한 사람이 뚫려도 다른 사람의 비밀번호는 안전하다.

EncryptService

빈 등록한 AesBytesEncryptor를 사용하기 위해 EncryptService를 만들어 주었다.

@Service
@RequiredArgsConstructor
public class EncryptService {

    private final AesBytesEncryptor encryptor;

    public String encryptEmail(String email) {
        byte[] encrypt = encryptor.encrypt(email.getBytes(StandardCharsets.UTF_8));
        return byteArrayToString(encrypt);
    }

    public String decryptEmail(String encryptString) {
        byte[] decryptBytes = stringToByteArray(encryptString);
        byte[] decrypt = encryptor.decrypt(decryptBytes);
        return new String(decrypt, StandardCharsets.UTF_8);
    }

    public String byteArrayToString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte abyte :bytes){
            sb.append(abyte);
            sb.append(" ");
        }
        return sb.toString();
    }

    public byte[] stringToByteArray(String byteString) {
        String[] split = byteString.split("\\s");
        ByteBuffer buffer = ByteBuffer.allocate(split.length);
        for (String s : split) {
            buffer.put((byte) Integer.parseInt(s));
        }
        return buffer.array();
    }
}

메소드 하나하나 살펴보자.

public String encryptEmail(String email) {
    byte[] encrypt = encryptor.encrypt(email.getBytes(StandardCharsets.UTF_8));
    return byteArrayToString(encrypt);
}

이메일만 암호화해주기 때문에 String email을 받는다.
암호화를 해주기 위해서는 byte 배열을 넣어줘야한다.
그리고 암호화를 해주면 byte 배열을 반환해준다. 배열 형태는 BD에 저장을 못 하기 때문에 byte 배열을 String으로 만들어주는 메소드를 구현했다.

public String byteArrayToString(byte[] bytes) {
    StringBuilder sb = new StringBuilder();
    for (byte abyte :bytes){
        sb.append(abyte);
        sb.append(" ");
    }
    return sb.toString();
}

StringBuilder를 사용하여 byte값들을 String으로 만들어주었다.

public String decryptEmail(String encryptString) {
    byte[] decryptBytes = stringToByteArray(encryptString);
    byte[] decrypt = encryptor.decrypt(decryptBytes);
    return new String(decrypt, StandardCharsets.UTF_8);
}

복호화를 하기 위해서는 암호화와 똑같이 byte 배열이 필요하다. 그렇기때문에 String을 byte 배열로 바꿔주는 메소드를 구현하였다.
그리고 중요한점은 복호화를 해준 다음에 반환 받은 byte 배열을 new String()해서 String 형태로 만들어야한다. toString()을 사용하면 byte 배열의 주소가 반환된다.

public byte[] stringToByteArray(String byteString) {
    String[] split = byteString.split("\\s");
    ByteBuffer buffer = ByteBuffer.allocate(split.length);
    for (String s : split) {
        buffer.put((byte) Integer.parseInt(s));
    }
    return buffer.array();
}

ByteBuffer을 사용하여 String을 byte 배열로 변환해주었다.


참고

지혜의 개발공부로그
패스워드의 암호화와 저장 - Hash(해시)와 Salt(솔트)

profile
공부는 꾸준히... 글쓰기도 꾸준히...

0개의 댓글