본문 바로가기

개발 관련 기타/보안

[openssl] AES 암호화 / 복호화 (C++ 사용)

AES 짤막한 소개

  • AES는 Advanced Encryption Standard 라고 해서 요즘 보편적으로 쓰이는 암호화 방식이다.
  • AES는 사용하는 key size (bits) 에 따라 AES-128, AES-192, AES-256 으로 나뉜다.
  • AES에서 암호화할 데이터는 128 bits (16 bytes) 로 된 block 들로 나뉘게 된다. 마지막 블럭이 128 bits 로 딱 떨어지지 않으면 padding 되어 128 bits로 만든다.
  • AES와 같은 블럭 알고리즘은 여러 모드 (CBC, CFB, ECB 등) 가 존재하는데 CBC가 Chain 형식으로 꽤 안전하다.

 


openssl 유틸리티를 사용해서 암호화 (AES-256 CBC 방식)

$ openssl enc -aes-256-cbc -in (in파일 경로) -out (out파일 경로) -K (hex로된 key값) -iv (hex로된 iv값) -a

※이외에는 "man openssl" 또는 "man enc"를 통해 사용방법 참고 바람


복호화는 C++ 코드로 만든 바이너리를 사용해서 진행해보도록 하겠습니다.

바이너리를 만드는데 사용한 라이브러리는 Crypto++ (CryptoPP) 라는 라이브러리 입니다.

 

Crypto++ 은

  • OpenSSL과 같은 C 기반 Cryptography 모듈과 비교해 객체지향 개념을 적용하여 C++로 만든 Crytography 모듈 입니다.
  • 암복호화 외 해싱, RSA 서명/검증 함수를 제공합니다.

Decryption 클래스 인스턴스를 생성하여 복호화 (AES-256 CBC 방식)

#include <cryptopp/aes.h>
#include <cryptopp/filters.h>
#include <cryptopp/ccm.h>

const int DecryptKeySize = CryptoPP::AES::MAX_KEYLENGTH; // AES-256 사용

std::string decrypt(std::string encrypted, std::string key, std::string iv) {
	std::string decrypted;
    try {
    	if (key.length() < DecryptKeySize) return "";
        if (iv.length() != ) return "";
        CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decryption(
        	reinterpret_cast<const unsigned char*>(key.c_str()),
            key.length(), 
            reinterpret_cast<const unsigned char*>(IV.c_str())
        	);
    	CryptoPP::StringSource ss(encrypted, true,	// StringSource는 CryptoPP 에서 제공하는 String을 Source로 하는 객체를 Read하기 위한 클래스 입니다.
        	new CryptoPP::StreamTransformationFilter(decryption,	// StreamTransformationFilter는 들어오는 filter type (여기서는 decryption이라는 복호화) 에 따라 input 데이터를 처리합니다.
        		new CryptoPP::StringSink(decrypted), //	StringSink는 데이터를 String 형으로 저장 할 때 쓰이는 Sink 입니다. Sink는 데이터를 받아 저장하는데 쓰이는 클래스 입니다.
            	CryptoPP::StreamTransformationFilter::ZEROS_PADDING) // StreamTransformationFilter
       		);; // StringSource
	} catch (const CryptoPP::Exception& e) {
    	std::cerr << e.what();	// catch 구문으로 error를 catch하고 exception 클래스 멤버 함수인 what() 을 호출해서 에러 정보를 출력합니다.
	}
    return decrypted;
}