RSA 암호화 알고리즘 사용하기
Crypto++ 라이브러리로 RSA 개인키, 공개키를 생성하고 생성한 키로 암호화, 복호화하는 방법을 알아보겠습니다.
개인키, 공개키를 바이너리 키파일로 생성하기
샘플 코드
AutoSeededRandomPool rng;
RSA::PrivateKey privKey;
RSA::PublicKey pubKey;
privKey.GenerateRandomWithKeySize(rng, 2048);
pubKey = RSA::PublicKey(privKey);
ofstream privFile("private.key", ios::binary);
privKey.Save(FileSink(privFile).Ref() );
privFile.close();
ofstream pubFile("public.key", ios::binary);
pubKey.Save(FileSink(pubFile).Ref());
pubFile.close();
코드 설명
AutoSeededRandomPool rng;
RNG가 제공하는 OS를 사용하여 자체적으로 시드를 생성하는 함수입니다.
RSA::PrivateKey privKey;
RSA::PublicKey pubKey;
개인키, 공개키 객체를 생성합니다.
privKey.GenerateRandomWithKeySize(rng, 2048);
생성한 시드와 키 길이를 전달하여 개인키를 생성합니다.
pubKey = RSA::PublicKey(privKey);
개인키를 이용하여 공개키를 생성합니다.
ofstream privFile("private.key", ios::binary);
privKey.Save(FileSink(privFile).Ref() );
privFile.close();
ofstream pubFile("public.key", ios::binary);
pubKey.Save(FileSink(pubFile).Ref());
pubFile.close();
개인키와 공개키를 파일로 저장합니다.
개인키, 공개키를 Base64 키파일로 생성하기
샘플 코드
AutoSeededRandomPool rng;
RSA::PrivateKey privKey;
RSA::PublicKey pubKey;
privKey.GenerateRandomWithKeySize(rng, 2048);
pubKey = RSA::PublicKey(privKey);
ofstream privFile("private.key", ios::binary);
Base64Encoder privKeySink(new FileSink(privFile), true);
privKey.Save(privKeySink);
privKeySink.MessageEnd();
privFile.close();
ofstream pubFile("public.key", ios::binary);
Base64Encoder pubKeySink(new FileSink(pubFile), true);
pubKey.Save(pubKeySink);
pubKeySink.MessageEnd();
pubFile.close();
코드 설명
개인키, 공개키 생성 코드는 위와 동일하므로 설명을 생략하겠습니다.
ofstream privFile("private.key", ios::binary);
Base64Encoder privKeySink(new FileSink(privFile), true);
privKey.Save(privKeySink);
privKeySink.MessageEnd();
privFile.close();
ofstream pubFile("public.key", ios::binary);
Base64Encoder pubKeySink(new FileSink(pubFile), true);
pubKey.Save(pubKeySink);
pubKeySink.MessageEnd();
pubFile.close();
개인키와 공개키를 Base64로 인코딩하여 파일로 저장합니다.
Base64Encoder를 사용을 하면 반드시 MessageEnd() 함수를 사용해야합니다.
인코딩만 할때는 사용을 안해도 문제가 없었는데 나중에 디코딩할때 비정상적으로 디코딩이 되는 문제가 있었습니다. (이것때문에 엄청난 고생을.. ㅠㅠ)
개인키, 공개키를 바이너리 문자열로 생성하기
샘플 코드
AutoSeededRandomPool rng;
RSA::PrivateKey privKey;
RSA::PublicKey pubKey;
privKey.GenerateRandomWithKeySize(rng, 2048);
pubKey = RSA::PublicKey(privKey);
string priv;
string pub;
privKey.Save(StringSink(priv).Ref());
pubKey.Save(StringSink(pub).Ref());
코드 설명
개인키, 공개키 생성 코드는 위와 동일하므로 설명을 생략하겠습니다.
string priv;
string pub;
privKey.Save(StringSink(priv).Ref());
pubKey.Save(StringSink(pub).Ref());
개인키와 공개키를 바이너리 문자열로 저장합니다.
string 타입의 변수이지만 바이너리 값이 들어갑니다.
개인키, 공개키를 Base64 문자열로 생성하기
샘플 코드
AutoSeededRandomPool rng;
RSA::PrivateKey privKey;
RSA::PublicKey pubKey;
privKey.GenerateRandomWithKeySize(rng, 2048);
pubKey = RSA::PublicKey(privKey);
string priv;
string pub;
Base64Encoder privKeySink(new StringSink(keyBuf.priv));
privKey.Save(privKeySink);
privKeySink.MessageEnd();
Base64Encoder pubKeySink(new StringSink(keyBuf.pub));
pubKey.Save(pubKeySink);
pubKeySink.MessageEnd();
코드 설명
개인키, 공개키 생성 코드는 위와 동일하므로 설명을 생략하겠습니다.
string priv;
string pub;
Base64Encoder privKeySink(new StringSink(keyBuf.priv));
privKey.Save(privKeySink);
privKeySink.MessageEnd();
Base64Encoder pubKeySink(new StringSink(keyBuf.pub));
pubKey.Save(pubKeySink);
pubKeySink.MessageEnd();
개인키와 공개키를 Base64 문자열로 저장합니다.
파일 생성때와 같은 이유로 꼭 MessageEnd() 함수를 사용해야합니다.
전체 예제 코드
#include <iostream>
using std::cout;
using std::endl;
using std::ofstream;
using std::ifstream;
using std::ios;
#include <string>
using std::string;
#include "rsa.h"
using CryptoPP::RSA;
#include "osrng.h"
using CryptoPP::AutoSeededRandomPool;
#include <files.h>
using CryptoPP::FileSink;
using CryptoPP::FileSource;
#include <filters.h>
using CryptoPP::StringSink;
using CryptoPP::StringSource;
#include <base64.h>
using CryptoPP::Base64Encoder;
using CryptoPP::Base64Decoder;
struct KeyString
{
string priv;
string pub;
};
void GenKeyFile(string fileName)
{
AutoSeededRandomPool rng;
RSA::PrivateKey privKey;
RSA::PublicKey pubKey;
/* 개인키 생성 */
privKey.GenerateRandomWithKeySize(rng, 2048);
/* 공개키 생성 */
pubKey = RSA::PublicKey(privKey);
/* 개인키 가져오기 */
ofstream privFile(fileName + "_private.key", ios::binary);
privKey.Save(FileSink(privFile).Ref());
privFile.close();
/* 공개키 가져오기 */
ofstream pubFile(fileName + "_public.key", ios::binary);
pubKey.Save(FileSink(pubFile).Ref());
pubFile.close();
}
void GenKeyFileBase64(string fileName)
{
AutoSeededRandomPool rng;
RSA::PrivateKey privKey;
RSA::PublicKey pubKey;
/* 개인키 생성 */
privKey.GenerateRandomWithKeySize(rng, 2048);
/* 공개키 생성 */
pubKey = RSA::PublicKey(privKey);
/* 개인키 가져오기 */
ofstream privFile(fileName + "_private.key", ios::binary);
Base64Encoder privKeySink(new FileSink(privFile), true);
privKey.Save(privKeySink);
privKeySink.MessageEnd();
privFile.close();
/* 공개키 가져오기 */
ofstream pubFile(fileName + "_public.key", ios::binary);
Base64Encoder pubKeySink(new FileSink(pubFile), true);
pubKey.Save(pubKeySink);
pubKeySink.MessageEnd();
pubFile.close();
}
KeyString GenKey()
{
AutoSeededRandomPool rng;
RSA::PrivateKey privKey;
RSA::PublicKey pubKey;
/* 개인키 생성 */
privKey.GenerateRandomWithKeySize(rng, 2048);
/* 공개키 생성 */
pubKey = RSA::PublicKey(privKey);
KeyString keyBuf;
/* 개인키 가져오기 */
privKey.Save(StringSink(keyBuf.priv).Ref());
/* 공개키 가져오기 */
pubKey.Save(StringSink(keyBuf.pub).Ref());
return keyBuf;
}
KeyString GenKeyBase64()
{
AutoSeededRandomPool rng;
RSA::PrivateKey privKey;
RSA::PublicKey pubKey;
/* 개인키 생성 */
privKey.GenerateRandomWithKeySize(rng, 2048);
/* 공개키 생성 */
pubKey = RSA::PublicKey(privKey);
KeyString keyBuf;
/* 개인키 가져오기 */
Base64Encoder privKeySink(new StringSink(keyBuf.priv));
privKey.Save(privKeySink);
privKeySink.MessageEnd();
/* 공개키 가져오기 */
Base64Encoder pubKeySink(new StringSink(keyBuf.pub));
pubKey.Save(pubKeySink);
pubKeySink.MessageEnd();
return keyBuf;
}
int main()
{
cout << "\n###############################\n" << endl;
/* Binary 키파일 */
cout << "Binary KeyFile Start" << endl;
GenKeyFile("RuruTest");
cout << "\n###############################\n" << endl;
/* Base64 키파일 */
cout << "Base64 KeyFile Start" << endl;
GenKeyFileBase64("RuruTest_Base64");
cout << "\n###############################\n" << endl;
/* Binary 문자열 키 */
cout << "Binary Key Start" << endl;
cout << endl;
KeyString key;
key = GenKey();
cout << "PrivateKey:" << endl << key.priv << endl;
cout << endl;
cout << "PublicKey:" << endl << key.pub << endl;
cout << "\n###############################\n" << endl;
/* Base64 문자열 키 */
cout << "Base64 Key Start" << endl;
cout << endl;
KeyString keyBase64;
keyBase64 = GenKeyBase64();
cout << "PrivateKey:" << endl << keyBase64.priv << endl;
cout << endl;
cout << "PublicKey:" << endl << keyBase64.pub << endl;
cout << "\n###############################\n" << endl;
return 0;
}
마무리
지금까지 Crypto++ 라이브러리로 RSA 개인키, 공개키 생성하는 방법이였습니다. 다음에는 개인키와 공개키가지고 암호화 복호화하는 방법을 작성 할 예정입니다.
잘못된 점이 있거나 궁금한 점이 있다면 언제든지 문의해주시기 바랍니다!
'프로그래밍 > C++' 카테고리의 다른 글
[C++] 클래스를 DLL로 만들고 사용하기 (0) | 2024.03.07 |
---|---|
[C++] Crypto++ 암호화 오픈 라이브러리 (0) | 2024.02.26 |
[C++] 정적 라이브러리(Static Link Library)와 동적 라이브러리(Dynamic Link Library) (0) | 2024.02.22 |
[C++] extern "C"와 네임 맹글링 (0) | 2024.02.21 |
[C++] 클래스 기본적인 사용법 (0) | 2024.02.21 |