개발을 하면서 암호화에 대해 깊이 있게 생각하지 않고 필요한 스펙 대로만 구현 했었는데, 이번에 시간이 좀 있어 블로그에 정리를 해봅니다.
이 글은 Java 기준으로 작성하였습니다.
여러 글을 보면서 검색을 하다 보니 타 업체와 협의 할 때 적어도 아래와 같은 스펙을 서로 교환하는게 좋다고 합니다. (http://redutan.github.io/2015/11/20/about-crypto)
| 암호화 스펙
- 알고리즘: RSA-256
- 암호화 키: 2017201820192020wow2021202220232024202520262027202820292030
- 인코딩: UTF-8
public class RSAEncrypto { private static final String algorithm = "RSA/None/NoPadding"; private static final String provider = "BC"; public static void main(String[] args) { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); String plainText = "2017201820192020wow2021202220232024202520262027202820292030"; try { Cipher serverCipher = Cipher.getInstance(algorithm, provider); SecureRandom random = new SecureRandom(); KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", provider); generator.initialize(512, random); KeyPair pair = generator.generateKeyPair(); Key publicKey = pair.getPublic(); Key privateKey = pair.getPrivate(); // 개인키로 암호화 serverCipher.init(Cipher.ENCRYPT_MODE, privateKey); byte[] cipherText = serverCipher.doFinal(plainText.getBytes()); System.out.println("cipher: ("+ cipherText.length +")"+ new String(cipherText)); // 공개키로 복호화 serverCipher.init(Cipher.DECRYPT_MODE, publicKey); byte[] plainTextB = serverCipher.doFinal(cipherText); System.out.println("plain: " + new String(plainTextB)); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchProviderException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } } }
이렇게 하면 암호화 하고, 복호화 되는 것을 확인할 수 있습니다. 하지만 실무에서는 이렇게 사용하는 경우는 거의 없습니다. 그래서 추가로 필요한 부분이 있습니다. 바로 Base64로 인코딩을 해야 되는 것입니다. 이상한 문자로 나온 암호문을 통신 할 때나, DB에 저장해서 사용할 수 없기에 Base64로 인코딩 합니다. 그리고 복호화 할 때는 다시 디코딩을 해서 복호화를 진행합니다.
참고로 Base64는 8비트 바이너리 데이터를 문자 코드에 영향을 받지 않는 공통 ASCII 영역의 문자들로만 이루어진 일련의 스트링으로 바꾸는 인코딩 방식을 말합니다. 아래 그림을 보면 Base64로 인코딩 된 것은 우리가 알아볼 수 있는 문자로 출력 됩니다.
인코딩을 사용하여 적용한 소스는 다음과 같습니다.
public class RSAEncrypto { private static final String algorithm = "RSA/None/NoPadding"; private static final String provider = "BC"; public static void main(String[] args) { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); String plainText = "2017201820192020wow2021202220232024202520262027202820292030"; try { Cipher serverCipher = Cipher.getInstance(algorithm, provider); SecureRandom random = new SecureRandom(); KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", provider); generator.initialize(512, random); KeyPair pair = generator.generateKeyPair(); Key publicKey = pair.getPublic(); Key privateKey = pair.getPrivate(); // 개인키를 전달하여 암호화 serverCipher.init(Cipher.ENCRYPT_MODE, privateKey); byte[] cipherText = serverCipher.doFinal(plainText.getBytes("UTF-8")); System.out.println("cipher: ("+ cipherText.length +")"+ new String(cipherText)); // Base64로 인코딩 byte[] encodedBase64 = Base64.encode(cipherText); System.out.println("Base64Encoded: " + new String(encodedBase64)); // Base64로 디코딩 byte[] decodedBase64 = Base64.decode(encodedBase64); System.out.println("Base64Decoded: " + new String(decodedBase64)); // 공개키를 가지고있는쪽에서 복호화 serverCipher.init(Cipher.DECRYPT_MODE, publicKey); byte[] plainTextB = serverCipher.doFinal(decodedBase64); System.out.println("plain: " + new String((plainTextB), "UTF-8")); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchProviderException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
도움 되셨다면 아래 '공감' 클릭 한번 해주세요~ 감사합니다.
'프로그래밍 > JAVA' 카테고리의 다른 글
CLOSE_WAIT 해결 방법 (1) | 2017.01.13 |
---|---|
자바로 크롤링 구현 (0) | 2016.09.13 |
문자열을 나누거나 합치거나 (0) | 2016.09.13 |