developer/c++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 사용시..)
#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1   // 컴파일러에서 정의하라고 나온다.

// Crypto++ Includes
#include "cryptlib.h"
#include "osrng.h" 
#include "hex.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)
{
	CryptoPP::CBC_Mode<typename Ty>::Encryption Encryptor(KEY, typename Ty::DEFAULT_KEYLENGTH, IV);
	return Encrypt(Encryptor, PlainText);
}


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

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


template <class Ty>
std::string ECB_Decrypt(byte *KEY, const std::string &PlainText)
{
	CryptoPP::ECB_Mode<typename Ty>::Decryption Decryptor(KEY, typename 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 _tmain(int argc, _TCHAR* argv[])
{
	using namespace std;

	// SEED 알고리즘 
	Test<CryptoPP::SEED>();

	// AES 알고리즘 
	Test<CryptoPP::AES>();

	// DES 알고리즘 
	Test<CryptoPP::DES>();

	return 0;
}


저작자 표시
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 디클
developer/nt2009/09/22 18:57

 패키지 활성화   JIT 활성화  멤버변수 상태 유지  전역변수 상태
 1. 서버 응용 프로그램  활성  유지 않함  유지 (활성화 개체 단위)
 2. 서버 응용 프로그램  비 활성  유지  유지 (활성화 개체 단위)
 3. 라이브러리 응용 프로그램  활성  유지 않함  유지 (세션 단위)
 4. 라이브러리 응용 프로그램  비 활성  유지  유지 (세션 단위)

* JIT 활성화가 있는경우 Method 단위로 m_spObjectContext->SetComplete() 를 호출 하여 테스트
* 풀링의 세팅의 경우 위의 결과와 틀리게 멤버변수의 상태가 달라 질 수 있음 
* CreateObject 이후 Nothing 까지의 상태 


내용 
- JIT 활성화인 경우 Method 단위로 클래스의 생성자 및 소멸자 호출 
- 풀링 설정의 경우 패키지가 시작할때 풀링된 구성요소 만큼 생성자를 호출하여 인스턴스 생성해 놓음 
- 라이브러리 응용 프로그램의 경우 인프로세스로 실행 되므로 전역변수값은 세션별로만 유지함
- regsvr32 로 등록되어 있는 컴포넌트랑 같은 효과를 내기 위해서는 "라이브러리 응용 프로그램, JIT 비활성화"로 운영

결론
내가 만들지 않은 컴포넌트의 경우 내부적으로 개체의 상태값 유지를 위해서,
멤버변수를 사용했는지, 지역 변수를 사용했는지 알 수 없기 때문에 regsvr32 로 등록하여 사용 하는것으로 권장

허나 COM+에 등록하여 사용 하려면 위의 내용 참고



저작자 표시
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 디클