cdeclog

Crypto++ 사용하기, 예제 본문

Dev/Encryption

Crypto++ 사용하기, 예제

디클 2009.10.14 09:54
C++ 용 암호화 라이브러리

Crypto++ 컴파일 

우선 해당 사이트에서 라이브러리를 다운 받은 후 원하는 컴파일러로 컴파일을 하여 dll 이나 lib 파일을 생성한다.
VC++ 2008 버전의 경우 프로젝트 파일이 따로 있지는 않고 VC++2005 버전을 업그레이드 후 컴파일 하면 됨

컴파일을 하면 cryptopp560\Win32 디렉토리에 각각 파일이 생성되고, dll 의 경우는 cryptopp560\Win32\DLL_Output 폴더에, static library 의 경우는 cryptopp560\Win32\Output 폴더에 각각의 모듈이 생성 된다. 

내가 테스트 할때는 dll 의 버전의 경우 이상하게 링크에러가 발생을 하여,
static library 를 사용하여 테스트를 하고 어플리케이션의 경우도 static library 로 컴파일을 해야 문제가 없었다.

블록 알고리즘 고려사항 
알고리즘 종류, 블록 알고리즘 운영 모드, 패딩종류, 인코딩 (텍스트 암호화의 경우)

알고리즘 SEED, AES, DES, 3-DES 설명 

DES
가장 오래되고, 세계적으로 가장 널리 사용되는 고전적 암호화 알고리즘이다. 파일이나 패킷을 암호화할 때 많이 사용된다. 하지만, 64비트 입력 블록과 56비트 짧은 비밀키를 사용하기 때문에, 더 이상 안전하지 않다고 간주하고 있다. 그러나, 국가 기밀을 다룰 정도로 극히 중요한 보안이 아니라면, 여전히 가장 널리 사용되는 알고리즘이다.
 
3-DES
DES를 3번 반복해서 암호화한다. 보안성이 향상되고, 그 만큼 성능은 떨어진다.
 
AES
미국 NIST에서 공모해서 표준화한 새로운 알고리즘이다. 128비트 입력 블록을 도입함으로써, 보안성을 향상했으며, 최근에 세계적으로 널리 사용되는 알고리즘이다.
 
SEED
KISA 주관으로 ETRI와 함께 국내에서 만들어진 알고리즘이다. 역시, 128비트 입력 블록을 사용하고 있고, 국제 표준에 부합하는 알고리즘이다.



블록 알고리즘 운영 모드 
ECB(Electronic codebook) : 평문을 일정 크기의 블록으로 나누어서 처리, 각 블록은 동일한 키로 암호
CBC(Cipher-block chaining) : 평문 블록과 바로 직전의 암호블록을 XOR한 것. 첫번째 암호 블록을 위해 초기 벡터 IV 값 사용

기타..
PCBC(Propagating cipher-block chaining)
CFB(Cipher feedback)
OFB(Output feedback)
CTR(Counter)


패딩(Padding) 종류
enum BlockPaddingScheme 
{NO_PADDING, ZEROS_PADDING, PKCS_PADDING, ONE_AND_ZEROS_PADDING, DEFAULT_PADDING};

NO_PADDING : 패딩 없음
ZEROS_PADDING : NULL(0) 으로 패딩 
PKCS_PADDING : 패딩되는 바이트의 수의 같은 값으로 모두 패딩
ONE_AND_ZEROS_PADDING :  ONE_AND_ZEROS_PADDING to use 0x80 instead 0x01 as padding
DEFAULT_PADDING : DEFAULT_PADDING means PKCS_PADDING 
  if c.MandatoryBlockSize() > 1 && c.MinLastBlockSize() == 0 (e.g. ECB or CBC mode), otherwise NO_PADDING (OFB, CFB, CTR, CBC-CTS modes)

예제, 필요한 헤더파일 (SEED, AES, DES 사용시..)
#include <iostream>
using namespace std;

//#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1   

// Crypto++ Includes
#include "cryptlib.h"
#include "Base64.h"
#include "aes.h"        
#include "seed.h"
#include "des.h"
#include "modes.h"      
#include "filters.h"    

#pragma comment(lib, "cryptlib")  

template <class TyMode>
std::string Encrypt(TyMode &Encryptor, const std::string &PlainText)
{
	std::string EncodedText;

	try {
		CryptoPP::StringSource(PlainText, true,
			new CryptoPP::StreamTransformationFilter(Encryptor,
				new CryptoPP::Base64Encoder(
					new CryptoPP::StringSink(EncodedText), false
					), CryptoPP::BlockPaddingSchemeDef::ZEROS_PADDING
				)
			);
	}
	catch (...) {}

	return EncodedText;
}

template <class TyMode>
std::string Decrypt(TyMode &Decryptor, const std::string &EncodedText)
{
	std::string RecoveredText;

	try {
		CryptoPP::StringSource(EncodedText, true,
			new CryptoPP::Base64Decoder(
				new CryptoPP::StreamTransformationFilter(Decryptor,
					new CryptoPP::StringSink(RecoveredText),
					CryptoPP::BlockPaddingSchemeDef::ZEROS_PADDING
					)
				)
			);
	}
	catch (...) {}

	return RecoveredText;
}

template <class Ty>
std::string CBC_Encrypt(byte *KEY, byte *IV, const std::string &PlainText)
{
	typename CryptoPP::CBC_Mode<Ty>::Encryption Encryptor(KEY, Ty::DEFAULT_KEYLENGTH, IV);
	return Encrypt(Encryptor, PlainText);
}


template <class Ty>
std::string CBC_Decrypt(byte *KEY, byte *IV, const std::string &PlainText)
{
	typename CryptoPP::CBC_Mode<Ty>::Decryption Decryptor(KEY, Ty::DEFAULT_KEYLENGTH, IV);
	return Decrypt(Decryptor, PlainText);
}

template <class Ty>
std::string ECB_Encrypt(byte *KEY, const std::string &PlainText)
{
	typename CryptoPP::ECB_Mode<Ty>::Encryption Encryptor(KEY, Ty::DEFAULT_KEYLENGTH);
	return Encrypt(Encryptor, PlainText);
}


template <class Ty>
std::string ECB_Decrypt(byte *KEY, const std::string &PlainText)
{
	typename CryptoPP::ECB_Mode<Ty>::Decryption Decryptor(KEY, Ty::DEFAULT_KEYLENGTH);
	return Decrypt(Decryptor, PlainText);
}


template <class CryptoType>
void Test()
{
	using namespace std;

	const std::string sText = "Plain Text";
	std::string sEnc, sDec;

	byte KEY[CryptoType::DEFAULT_KEYLENGTH] = { 0, };
	byte IV[CryptoType::BLOCKSIZE] = { 0x01, };

	// CBC 모드
	sEnc = CBC_Encrypt<CryptoType>(KEY, IV, sText);
	sDec = CBC_Decrypt<CryptoType>(KEY, IV, sEnc);

	cout << CryptoType::StaticAlgorithmName() << " : " << "CBC_MODE" << endl;
	cout << sText << "\n -> " << sEnc << "\n -> " << sDec << endl;


	// ECB 모드
	sEnc = ECB_Encrypt<CryptoType>(KEY, sText);
	sDec = ECB_Decrypt<CryptoType>(KEY, sEnc);

	cout << CryptoType::StaticAlgorithmName() << " : " << "ECB_MODE" << endl;
	cout << sText << "\n -> " << sEnc << "\n -> " << sDec << endl;
	cout << endl;
}


int main()
{
	using namespace std;

	// SEED 
	Test<CryptoPP::SEED>();

	// AES 
	Test<CryptoPP::AES>();

	// DES 
	Test<CryptoPP::DES>();

	return 0;
}
  


2 Comments
  • 프로필사진 lmg2738 2009.11.09 16:08 신고 ^^ 안녕하세요~ 이민규입니다.

    하도 오래 전에 떠나 어떻게 직책을 불러들여야 할지 모르겠네요. 팀장님 맞죠 ?ㅋ

    구글에서 Seed C# 이라고 검색했더니 팀장님 트위터 나오더라구요.. ㅋ

    링크타고 티스토리도 다녀갑니다. 좋은 하루 되세요~~
  • 프로필사진 imagej 2016.10.18 14:33 신고 안녕하세요 AES 다기종 암호화 서칭 중 정보를 얻어 갑니다.

    좋은 정보 감사드리구요.

    그런데 Base64Decoder 라는 함수가 존재를 않하는데 원인을 모르겠군요.

댓글쓰기 폼