결제 관련 API 연동(VAN, PG, 간편결제 등) 할 경우 RSA암복호화 과정을 거치게되는데
이 부분에 대한 샘플 코드를 작성해 보았다.
Apache Commons Codec 다운로드
commons.apache.org/proper/commons-codec/
프로젝트 라이브러리에 추가.
PublicKey와 PrivateKey 파일을 생성
package com.ubpay.keypair;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
//
// RSA Key 파일 생성
//
// Created by netcanis on 2019/04/29.
// Copyright © 2019 netcanis. All rights reserved.
//
// Download Apache Commons Codec
// https://commons.apache.org/proper/commons-codec/download_codec.cgi
public class GenKeys
{
private KeyPairGenerator keyGen;
private KeyPair pair;
private PrivateKey privateKey;
private PublicKey publicKey;
// RSA 초기화 및 키 생성
public GenKeys(int keysize) throws NoSuchAlgorithmException, NoSuchProviderException {
this.keyGen = KeyPairGenerator.getInstance("RSA");
this.keyGen.initialize(keysize);
this.pair = this.keyGen.generateKeyPair();
this.publicKey = pair.getPublic();
this.privateKey = pair.getPrivate();
}
public PublicKey getPublicKey() {
return this.publicKey;
}
public PrivateKey getPrivateKey() {
return this.privateKey;
}
public void writeToFile(String path, byte[] key) throws IOException {
File f = new File(path);
f.getParentFile().mkdirs();
FileOutputStream fos = new FileOutputStream(f);
fos.write(key);
fos.flush();
fos.close();
}
public static void main(String[] args) {
GenKeys genKeys;
try {
// 1024bit key pair 생성
genKeys = new GenKeys(1024);
System.out.println(genKeys.publicKey);
System.out.println(genKeys.privateKey);
// 바이너리 파일로 저장
genKeys.writeToFile("KeyPair/public.key", genKeys.getPublicKey().getEncoded());
genKeys.writeToFile("KeyPair/private.key", genKeys.getPrivateKey().getEncoded());
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
System.err.println(e.getMessage());
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
}
생성 결과
생성된 키를 이용하여 암복호화 테스트
package com.ubpay.rsaTest;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.DSAPrivateKeySpec;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.EncodedKeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.apache.commons.codec.binary.Base64;
//
// RSA 암복호화 및 테스트
//
// Created by netcanis on 2019/04/29.
// Copyright © 2019 netcanis. All rights reserved.
//
public class RSAEncryption
{
private Cipher cipher;
public RSAEncryption() throws NoSuchAlgorithmException, NoSuchPaddingException{
this.cipher = Cipher.getInstance("RSA");
}
// 주어진 파일을 byte array로 읽기
public byte[] getFileInBytes(File f) throws IOException{
FileInputStream fis = new FileInputStream(f);
byte[] fbytes = new byte[(int) f.length()];
fis.read(fbytes);
fis.close();
return fbytes;
}
// X509EncodedKey
public PublicKey getPublic(String filename) throws Exception {
byte[] keyBytes = Files.readAllBytes(new File(filename).toPath());
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
// PKCS8EncodedKeySpec
public PrivateKey getPrivate(String filename) throws Exception {
byte[] keyBytes = Files.readAllBytes(new File(filename).toPath());
//byte[] decoded = Base64.getDecoder().decode(keyBytes);
//println(new String(decoded)); // Outputs "Hello"
//Base64 codec = new Base64();
//byte[] decoded = codec.decode(keyBytes);
//System.out.println( new String(decoded) ); // Outputs "Hello"
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
// public key로 암호화
public String encrypt(String str, PublicKey key) throws NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException{
this.cipher.init(Cipher.ENCRYPT_MODE, key);
return Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
}
// private key로 복호화
public String decrypt(String str, PrivateKey key) throws InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException{
this.cipher.init(Cipher.DECRYPT_MODE, key);
return new String(cipher.doFinal(Base64.decodeBase64(str)), "UTF-8");
}
// hex to byte[]
public byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
// byte[] to hex
public String byteArrayToHexString(byte[] bytes){
StringBuilder sb = new StringBuilder();
for(byte b : bytes){
sb.append(String.format("%02X", b&0xff));
}
return sb.toString();
}
public static void main(String[] args) throws Exception {
RSAEncryption ac = new RSAEncryption();
// 공개키
PublicKey publicKey = ac.getPublic("KeyPair/public.key");
// 개인키
PrivateKey privateKey = ac.getPrivate("KeyPair/private.key");
// 원문
String msg = "test message";
System.out.println("----------------------------------------------------");
System.out.println(":::: TEST 암호화 및 복호화 ::::");
// 암호화 원문 BASE64
String encryptedString = ac.encrypt(msg, publicKey);
// 복호화
String decryptedString = ac.decrypt(encryptedString, privateKey);
System.out.println("----------------------------------------------------");
System.out.println(
"원문 = " + msg + "\n" +
"공개키 암호화 = " + encryptedString + "\n" +
"개인키 복호화 = " + decryptedString
);
System.out.println("----------------------------------------------------");
}
}
결과 :
--------------------------------------------------------------------------
:::: TEST 암호화 및 복호화 ::::
--------------------------------------------------------------------------
원문 = test message
공개키 암호화 = gz2WQHCyHxsPV5IB0xehk8RSbGrhGR86nQRGj09CphxiIAjRsCony8myWfRGJgDVyK6ixuK13gtL/20j4K5c1GcCKxPT9xqYaa6tBxTakho9klHNAO6KhQJK0nGeIQRDpZ1qecB6pPMsRqVVO5rb81NFqbjLKMoqi2tO1f55/iM=
개인키 복호화 = test message
--------------------------------------------------------------------------
2020/12/17 - [OS/Mac OS X] - OpenSSL을 이용한 Key 정보 Text 변환
2020/12/17 - [iOS/Tips] - URL query 파싱 및 json string 변환
2020/12/16 - [개발노트] - Code 128 Barcode의 Check Digit 계산방법
2020/12/15 - [iOS/Tips] - 디버깅 차단 처리 (Anti Debug)
2020/12/14 - [iOS/Tips] - bundle id 알아내기
2020/12/12 - [AI/Algorithm] - 2D 충돌처리
2020/12/11 - [iOS/Swift] - UIViewController 스위칭
2020/12/11 - [개발노트] - PlantUML 설치 (Mac OS X)
2020/12/10 - [iOS/Objective-C] - 웹뷰에서 javascript 함수 동기식 호출
2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (2/2)
2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (1/2)
2020/12/10 - [iOS/Tips] - Custom UserAgent 설정
2020/12/10 - [iOS/Tips] - CocoaPods 설치 및 제거
2020/12/10 - [iOS/Tips] - Clang diagnostic 경고 무시하기
2020/12/10 - [개발노트] - Bluetooth UUID
'개발 > Note' 카테고리의 다른 글
Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended (0) | 2020.12.17 |
---|---|
OpenSSL을 이용한 Key 정보 Text 변환 (0) | 2020.12.17 |
Code 128 Barcode의 Check Digit 계산방법 (0) | 2020.12.16 |
PlantUML 설치 (Mac OS X) (0) | 2020.12.11 |
특수문자 발음 (0) | 2020.12.11 |