개발

openssl, java에서 RSA 개인키, 공개키 생성, 전자서명 방법

개미v 2021. 1. 24. 15:02

 

RSA 암호화 알고리즘 사용을 위한 개인키, 공개키 생성 방법입니다.

자바에서 사용하기 위해서는 PEM + PKCS#8 형식으로 하는 것이 간편해 보입니다.

 

■ PEM vs DER

공개키 기반 알고리즘의 키 파일 인코딩 방식은 PEM, DER이 있습니다.

- PEM : BASE64로 인코딩된 아스키 형식

- DER : 바이너리 형식

 

■ PKCS#1 vs PKCS#8

PEM형식은 PKCS#1, PKCS#8 형식이 있습니다.

무늬만 차이를 보면 이렇습니다.

 

- PKCS#1

헤더가 BEGIN RSA PRIVATE KEY 으로 시작

자바에서 지원 안함

 

- PKCS#8 :

헤더가 BEGIN PRIVATE KEY 으로 시작

자바에서 지원함

 

■ openssl에서 RSA 개인키, 공개키 생성방법

# 개인키 pkcs#1 형식으로 생성

genrsa -out private_key1.pem 2048

 

# 개인키 pkcs#1에서 pkcs#8 형식으로 변환

pkcs8 -in private_key1.pem -inform PEM -out private_key8.pem -outform PEM -topk8 -nocrypt

 

# 공개키 pkcs#8 형식으로 생성

rsa -in private_key8.pem -out public_key8.pem -pubout

 

※ 자바에서 PKCS#1 형식은 지원 안하기 때문에 PKCS#8으로 변환함

 

■ JAVA에서 RSA 개인키, 공개키 생성

아래 링크에 잘 정리된 예제가 있어서 가져다가 사용했습니다.

https://gist.github.com/stunstunstun/8dbc82bd86f38c9232139e0ba9a7d8ad

 

public class Main {

	public static void main(String[] args) throws Exception {

		KeyPair keyPair = Security.generateKeyPair();
		Encoder base64Encoder = Base64.getEncoder(); 
			
		// 개인키 생성
		PrivateKey privateKey = keyPair.getPrivate();
		byte[] privateKeyByte = privateKey.getEncoded();
		String privateKeyBase64 = new String(base64Encoder.encode(privateKeyByte));
		System.out.println(privateKeyBase64);
			
		// 공개키 생성
		PublicKey publicKey = keyPair.getPublic();
		byte[] publicKeyByte = publicKey.getEncoded();
		String publicKeyBase64 = new String(base64Encoder.encode(publicKeyByte));
		System.out.println(publicKeyBase64);
	}
}

 

■ JAVA에서 전자서명

public class Main {

	public static void main(String[] args) throws Exception {
		
		// 평문
		String plainText = "Hello World";
			
		KeyPair keyPair = Security.generateKeyPair();
			
		// 개인키
		PrivateKey privateKey = keyPair.getPrivate();
		byte[] privateKeyByte = privateKey.getEncoded();
			
		// 공개키
		PublicKey publicKey = keyPair.getPublic();
		byte[] publicKeyByte = publicKey.getEncoded();
			
		// 개인키로 전자서명
		String signatureText = Security.sign(plainText, privateKeyByte);
			
		// 공개키로 전자서명 검증
		boolean ret = Security.verify(plainText, signatureText, publicKeyByte);
		System.out.println(ret);
	}
}