이번 포스트에서는 RSA 알고리즘에 대해서 알아보고, openssl 을 이용해서 RSA 키를 생성해보고, 몇몇 프로그래밍 언어에서 RSA 를 이용해서 encrypt / decrypt 하는 방법에 대해서 소개해 보겠습니다.
RSA 알고리즘
RSA 알고리즘은 비대칭키 알고리즘으로 두 개의 서로 다른 키를 사용해서 암호화와 복호화를 하는 방식입니다. 알고리즘을 개발했던 개발자들(Ron Rivest, Adi Shamir, Leonard Adleman)의 이름 이니셜을 따서 명명하였습니다. 자세한 알고리즘의 원리는 위키를 참고해 주세요.
OpenSSL로 RSA 키 생성하기
키 파일 생성하는 방법을 요약하면 다음과 같습니다.
# private key 파일 생성
openssl genrsa -out private-key.pem 4096
# 생성한 private key를 이용해서 public key 파일 생성
openssl rsa -in private-key.pem -pubout -out public-key.pem
# private key를 이용해서 (self-signed) 인증서 발급
openssl req -new -x509 -key private-key.pem -out cert.pem -days 360
# pem 파일을 pfx 파일로 변경
openssl pkcs12 -export -inkey private-key.pem -in cert.pem -out cert.pfx
위의 내용은 아래 사이트에서 가지고 왔습니다.
https://www.scottbrady91.com/openssl/creating-rsa-keys-using-openssl
RSA encrypt (with .net 8.0)
이번에는 .net8.0 라이브러리 (System.Security.Cryptography)를 이용해서 데이터를 encrypt 하는 코드 샘플입니다. 참고로 .net5.0 이후는 같은 코드로 동작하지만 .netframework에서는 작동하지 않습니다.
encrypt는 public key를 사용하게 됩니다. 미리 public key를 준비해 둡니다. 저는 위에서 설명한 openssl로 생성한 pem 파일을 열어서 PUB_KEY라는 이름으로 문자열 형태의 리소스를 등록해 두었습니다.
using System.Security.Cryptography;
...
byte[] rsaEncrypt(byte[] encodeData)
{
byte[] ret = null;
// rsa 객체 생성
using (var rsa = RSA.Create())
{
// resource에서 pem 형식의 public 키를 가지고 옵니다.
var pubKeyStr = Properties.Resources.ResourceManager.GetString("PUB_KEY");
// public 키를 import 합니다.
rsa.ImportFromPem(pubKeyStr);
// 데이터를 encrypt 합니다.
ret = rsa.Encrypt(encodeData, RSAEncryptionPadding.OaepSHA256);
}
return ret;
}
RSA decrypt (with .net 8.0)
이번에는 .net8.0 라이브러리 (System.Security.Cryptography)를 이용해서 데이터를 decrypt 하는 코드 샘플입니다. 참고로 .net5.0 이후는 같은 코드로 동작하지만 .netframework에서는 작동하지 않습니다.
decrypt는 private key를 사용하게 됩니다. 미리 private key를 준비해 둡니다. 저는 위에서 설명한 openssl로 생성한 pem 파일을 열어서 PRI_KEY라는 이름으로 문자열 형태의 리소스를 등록해 두었습니다.
using System.Security.Cryptography;
...
byte[] rsaDecrypt(byte[] encodedData)
{
byte[] ret = null;
// rsa 객체 생성
using (var rsa = RSA.Create())
{
// resource에 저장된 private 키를 가지고 옵니다.
var priKeyStr = Properties.Resources.ResourceManager.GetString("PRI_KEY");
// private 키를 import 합니다.
rsa.ImportFromPem(priKeyStr);
// decryhpt 합니다.
ret = rsa.Decrypt(encodedData, RSAEncryptionPadding.OaepSHA256);
}
return ret;
}
RSA 코드 테스트
아래 코드를 이용하면, encrypt / decrypt 결과를 테스트 할 수 있습니다.
public void test()
{
string str = "Hello";
// encrypt string data - string을 byte[] 형태로 변경해서 전달
byte[] buf = rsaEncrypt(Encoding.UTF8.GetBytes(str));
// buf를 base64 string 형태로 출력
Debug.WriteLine(Convert.ToBase64String(buf));
// decrypt encrypted data
buf = rsaDecrypt(buf);
// buf를 string 형태로 출력
Debug.WriteLine(Encoding.UTF8.GetString(buf));
}