JAVA 심화

[JAVA] 심화 - 양방향 암호화 기법, 비대칭 키 암호 알고리즘 (2)

beginner-in-coding 2024. 12. 30. 14:37

01. 비대칭 키 암호 알고리즘

  • 정의: 암호화를 위해 사용하는 키 != 복호화를 위해 사용하는 키
  • 공개 키: 모두에게 공개 가능
  • 비밀 키: 공개해서는 안됨
  • 공개 키 암호화 방식: 공개 키를 활용해 암호화 하는 것, 공개 키로 암호화 하면 함께 생성된 비밀키로만 복호화 가능해짐

비대칭 키 암호 알고리즘 소개


02. 비대칭 키 암호 알고리즘 사용 방법


(1) A가 데이터를 암호화해서 B에게 보내야한다고 가정

  1. 먼저 B가 자신의 공개 키를 A에게 전달
  2. B의 공개키를 받은 A가 A에서 B의 공개키를 이용해서 암호화하여 암호문을 만듬
  3. 만들어진 암호문을 B에게 전달
  4. 전달받은 A의 암호문을 B에서 자신의 비밀키를 이용해 복호화하여 데이터를 받음

  • 공개 키는 누구에게나 공개 할 수 있기 때문에 인터넷 망을 이용하여 전달이 가능해짐
  • 만들어진 암호문은내가 가진 비밀 키로만 복호화하여 평문을 얻을 수 있기 때문에 다른 사람은 풀 수 없음
  • 이런 과정을 통해 공개키와 달리 사람이 공용으로 사용하는 인터넷 망에서 키를 도난당하지 않고 전달 가능함

 (2) 반대로 보내려는 사람, 즉 A가 가지고 있는 비밀키로 암호화 하고 A의 공개 키로 복호화 하는 방법

  • 이 방법은 전자 서명을 할 때 사용하는 방법
  • A가 보낸 암호문은 A의 공개키로만 복호화가 가능하기 때문에, A가 문서를 암호화하여 보냈다는 것이 인증됨


03. 비대칭 키 암호 알고리즘을 JAVA로 구현하기


(1) 비대칭 키 암호 알고리즘 - 비대칭 키 생성하기

import javax.crypto.Cipher;
import java.security.*;
import java.util.Arrays;
import java.util.Base64;

public class RSAEncryption {
    private PrivateKey privateKey = null;
    private PublicKey publicKey = null;

    public RSAEncryption(){
        this.makeKey();
    }

    // 비대칭 키 생성 메서드
    public KeyPair makeKey(){
        KeyPairGenerator keyPairGenerator = null;
        KeyPair keyPair = null;

        try{
            // 비대칭 키 생성을 위한 객체 생성
            keyPairGenerator = KeyPairGenerator.getInstance("RSA");

            // RSA 알고리즘의 비트 수를 2048로 설정
            keyPairGenerator.initialize(2048);

            // 비대칭 키(공개 키, 비밀 키) 생성
            keyPair = keyPairGenerator.generateKeyPair();

            // 비밀 키 변수 할당
            privateKey = keyPair.getPrivate();

            // 공개 키 변수 할당
            publicKey = keyPair.getPublic();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        return keyPair;
    }

    
}

 

  • 비대칭 키 암호 알고리즘을 사용하려면 공개키-비밀키를 만들어야 함
  • KeypairGenerator와 Keypair을 이용하여 비대칭 키 생성을 위한 객체를 생성함
  • KeypairGenerator의 알고리즘은 RSA로 불러오고, 비트 수를 2048로 설정함
  • 그리고 keypair에 비대칭 키를 등록하고, 비밀키와 공개키에 생성된 값을 할당함

(2) 비대칭 키 암호 알고리즘 - 공개키로 암호화하기

// 암호화 함수
    public String encrypt(String plainText) throws Exception {
        byte[] cipherText = null;

        // 암호화 객체 생성
        Cipher cipher = Cipher.getInstance("RSA");

        // 암호화 모드, 공개키를 입력하여 암호화 객체 초기화
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        // 데이터 암호화 수행
        cipherText = cipher.doFinal(plainText.getBytes());
        System.out.println("cipherText = " + Arrays.toString(cipherText));
        // Base64로 인코딩하여 암호문 반환
        return Base64.getEncoder().encodeToString(cipherText);
    }
  • RSA: 전문가들이 권고하는 알고리즘, 알고리즘의 길이가 길기 때문에 보안적임
  • 암호 알고리즘을 ENCRYT_MODE로 지정하고, 공개 키 변수 publicKey를 지정하여 암호화 객체를 초기화함
  • 그리고 데이터 암호화를 위한 함수 doFinal()을 호출하여 암호화된 문장을 반환받음
  • 리턴값으로 base64 형식으로 인코딩하여 반환함

(3) 비대칭 키 암호 알고리즘 - 비밀키로 복호화하기

 // 복호화 함수
    public String decrypt(String cipherText) throws Exception {
        byte[] plainText = null;

        // 암호화 객체 생성
        Cipher cipher = Cipher.getInstance("RSA");

        // 복호화 모드, 비밀키를 입력하여 암호화 객체 초기화
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        // 데이터 복호화 수행
        plainText = cipher.doFinal(Base64.getDecoder().decode(cipherText));

        // 바이트 형식으로 복호화된 데이터를 문자열 형식으로 변환하여 반환
        return new String(plainText);
    }

(4) 결과

더보기

plain Text2: 123456
encrypted2: VAnkcLJjOiLrhpC7Cgyf1Vng+RzEupJBPfTVUjIE5a/N5Z8mDz3r/6biUXnd05bRVRbSr0vF/Qx3iDFey0hHbzFy4hNRDdSDSmXJ3PoGAXgZh3cCbrPFTO1uamuuyb8LwWRZA8MWQyDbBNnhCdz8K1YiOinfialMvx5KExpT0eINVlhRca01tk7MelZeaReD4xe7raHWfzRNdOzdwIDoq9VVX94vsr7YJY1yr8N0kY66FT+iJzaEl4eMGoOZ7krfMqT5v5KpMOm7Rk9SmkRyGsfWnoqOQYLae8ZkTUBMk3UJDXoVsBihc59DbPtA7ns3W/vUcNLM6L7JqD5GJoLfOg==
decrypted2: 123456

  • 실행 결과에서 plain Text2로 123456을 암호화 하면
  • encryted2에서처럼 긴 암호문이 나오는 것을 확인 할 수 있음
  • 이 encryted2를 다시 복호화를 진행하면 decryted2처럼 평문이 나오는 결과를 확인할 수 있음

(5) 번외 - 다른 쌍의 비밀키-공개키를 이용한 경우 

BadPaddingException 에러

  • 암호화 한 공개키의 쌍인 비밀키가 아닌 다른 암호키의 비밀키를 사용하면 다음과 같은 BadPaddingException Error가 발생함