Java

[Java] 공개키(Public Key) 와 개인키(Priviate Key)

예은파파 2020. 12. 10. 22:45

대칭키와 비대칭키란?

  • 대칭키는 암호화 / 복호화 시에 사용하는 키가 동일한 방식으로 1개의 키만 사용한다.
    전자문서(비밀편지)가 대칭키(열쇠)로 암호화 되면 똑같은 대칭키를 가지고 있는 상대방만이 이 전자문서를 복호화 할 수 있으며, 누군가가 암호화된 전자문서를 입수 하여도 이를 복호화하지 못하기 때문에 입수한 사람에게는 아무 의미가 없는 문서이다.

  • 비대칭키는 사용하는 키와 복호화 할 때 사용하는 키가 다른 경우를 말한다. 타인에게 절대 노출되어서는 안되는 비밀키(개인키), 비밀키를 토대로 만든 공개키가 쌍을 이룬 형태이다. 2개의 키를 사용한다.
  • 공개키 - 사람들에게 공개된 키이며 정보를 암호화 할 수 있다.
  • 비밀키 - 사용자만 알고 있는 암호를 풀 수 있는 키

  • Java RSA 암호화/복호화 Util 구현
public class RSAUtil {

    /**
     * 1024비트 RSA 키쌍을 생성
     */
    public static KeyPair genRSAKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
        gen.initialize(1024, new SecureRandom());
        return gen.genKeyPair();
    }

    /**
     * Public Key로 RSA 암호화를 수행
     */
    public static String encryptRSA(String plainText, PublicKey publicKey)
            throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException,
            BadPaddingException, IllegalBlockSizeException {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        byte[] bytePlain = cipher.doFinal(plainText.getBytes());
        return Base64.getEncoder().encodeToString(bytePlain);
    }

    /**
     * Private Key로 RSA 복호화를 수행
     */
    public static String decryptRSA(String encrypted, PrivateKey privateKey)
            throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException,
            BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {
        Cipher cipher = Cipher.getInstance("RSA");
        byte[] byteEncrypted = Base64.getDecoder().decode(encrypted.getBytes());

        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] bytePlain = cipher.doFinal(byteEncrypted);
        return new String(bytePlain, "utf-8");
    }

    public static PublicKey getPublicKeyFromBase64Encrypted(String base64PublicKey)
            throws NoSuchAlgorithmException, InvalidKeySpecException {
        byte[] decodedBase64PubKey = Base64.getDecoder().decode(base64PublicKey);

        return KeyFactory.getInstance("RSA")
                .generatePublic(new X509EncodedKeySpec(decodedBase64PubKey));
    }

    public static PrivateKey getPrivateKeyFromBase64Encrypted(String base64PrivateKey)
            throws NoSuchAlgorithmException, InvalidKeySpecException {
        byte[] decodedBase64PrivateKey = Base64.getDecoder().decode(base64PrivateKey);

        return KeyFactory.getInstance("RSA")
                .generatePrivate(new PKCS8EncodedKeySpec(decodedBase64PrivateKey));
    }
}

 

  • Java RSA Util을 이용한 Test Client
public class RSAUtilTest {

    public static void main(String[] args) throws Exception {
		
        // RSA 키쌍을 생성
        KeyPair keyPair = RSAUtil.genRSAKeyPair();

        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();

        String plainText = "RSA Encryption test";

        // Base64 인코딩된 암호화 문자열
        String encrypted = RSAUtil.encryptRSA(plainText, publicKey);

        // 복호화
        String decrypted = RSAUtil.decryptRSA(encrypted, privateKey);

        // 공개키를 Base64 인코딩한 문자일을 만듦
        byte[] bytePublicKey = publicKey.getEncoded();
        String base64PublicKey = Base64.getEncoder().encodeToString(bytePublicKey);

        // 개인키를 Base64 인코딩한 문자열을 만듦
        byte[] bytePrivateKey = privateKey.getEncoded();
        String base64PrivateKey = Base64.getEncoder().encodeToString(bytePrivateKey);

        // base64 암호화한 String 에서 Public Key 를 다시생성한후 암호화 테스트를 진행
        PublicKey rePublicKey = RSAUtil.getPublicKeyFromBase64Encrypted(base64PublicKey);
        String encryptedRe = RSAUtil.encryptRSA(plainText, rePublicKey);
        String decryptedRe = RSAUtil.decryptRSA(encryptedRe, privateKey);

        // base64 암호화한 String 에서 Private Key 를 다시생성한후 복호화 테스트를 진행
        PrivateKey privateKeyRe = RSAUtil.getPrivateKeyFromBase64Encrypted(base64PrivateKey);
        String decryptedReRe = RSAUtil.decryptRSA(encryptedRe, privateKeyRe);
	        
    }
}

 

 

 

'Java' 카테고리의 다른 글

[Java] Time Orderd UUID  (0) 2022.02.23
[Java] JMX를 통한 자원 모니터링  (0) 2021.06.11
[Java] 암호 알고리즘 / 운용 모드 / Padding  (0) 2020.11.28
[Java] Reflection  (0) 2020.11.19
[Java] Optional  (0) 2020.11.15