OpenSSL에서는 인터페이스가 규격화 된 최상위 API를 제공한다.
처음 접하는 사람들은 쉽게 접근할 수 있도록 배려한 것 같다.
참고로 EVP란 EnVeloPe 의 약자로 하위의 api를 포장했다는 의미가 있다.
예제를 보며 설명하겠다.
void TestEVP_MessageDigest(const char *alg, const char *pP1, const char *pP2, const char *pP3) { EVP_MD_CTX *mctx; const EVP_MD *digest; digest = EVP_get_digestbyname(alg); unsigned char md[EVP_MAX_MD_SIZE]; unsigned int md_len; mctx = EVP_MD_CTX_new(); EVP_DigestInit_ex(mctx, digest, NULL); EVP_DigestUpdate(mctx, pP1, strlen(pP1)); EVP_DigestUpdate(mctx, pP2, strlen(pP3)); EVP_DigestUpdate(mctx, pP3, strlen(pP2)); EVP_DigestFinal(mctx, md, &md_len); EVP_MD_CTX_free(mctx); string strName = "EVP "; strName += alg; PrintByteBuffer(strName.c_str(), md, md_len); } void TestEVP_Cypher() { string strInput = "Yoda said, Do or do not. There is no try."; string strCyper, strOutput; SHA256_CTX c; const char *key = "This is my AES key by tebek... "\ "One Little Two Little Three Little Endian? Indian!"; unsigned char keyCipher[32], iv[16]; unsigned char m[SHA256_DIGEST_LENGTH]; EVP_CIPHER_CTX *pCtxCipher; const EVP_CIPHER *pCipher; CMyRand rand(MT19937, UNIFORM_INT, 1, 0xFF); unsigned char buf[128]; unsigned char bufEncrypted[128]; unsigned char bufOut[128]; int len_enc, len_dec, len_final; SHA256_Init(&c); SHA256_Update(&c, key, strlen(key)); SHA256_Final(m, &c); OPENSSL_cleanse(&c, sizeof(c)); memcpy(keyCipher, m, 32); memcpy(iv, m, 16); rand.Rand(buf, 78); pCtxCipher = EVP_CIPHER_CTX_new(); pCipher = EVP_get_cipherbyname("aes-256-cfb"); // Encrypt EVP_CipherInit(pCtxCipher, pCipher, keyCipher, iv, 1); EVP_CipherUpdate(pCtxCipher, bufEncrypted, &len_enc, buf, 78); len_final = len_enc; EVP_CipherFinal(pCtxCipher, bufEncrypted + len_enc, &len_enc); len_enc += len_final; // Decrypt EVP_CipherInit(pCtxCipher, pCipher, keyCipher, iv, 0); EVP_CipherUpdate(pCtxCipher, bufOut, &len_dec, bufEncrypted, len_enc); len_final = len_dec; EVP_CipherFinal(pCtxCipher, bufOut + len_dec, &len_dec); len_dec += len_final; EVP_CIPHER_CTX_free(pCtxCipher); PrintByteBuffer("aes-256-cfb input", buf, 78); PrintByteBuffer("aes-256-cfb encrypt", bufEncrypted, len_enc); PrintByteBuffer("aes-256-cfb decrypt", bufOut, len_dec); }
첫번째 것은 Message Digest이고 두번째 것은 대칭키 암복호화이다.
두 사용법에 규칙이 있다.
// 구조를 깔끔하게 보고 확인하기 위해서 세세한 코드부분은 삭제하였다. ctx = EVP_방식_CTX_new(); EVP_방식Init(ctx); EVP_방식Update(ctx); EVP_방식Update(ctx); EVP_방식Update(ctx); EVP_방식Final(ctx); EVP_방식_CTX_free(ctx);
Context 생성 -> Init -> Update -> Final -> Context 해제
기본 흐름이 똑같은 것을 소스에서 확인하자.
여기서 Update는 한번만 쓸수도 있고 여러번 쓸수도 있는데 입력값을 나눠서 넣는 기능이다.
일반적으로 stream 처리시 대용량 데이터 처리시에 나눠서 넣는다.
이번에 작성된 코드중 AES 256 CFB가 실행된 화면은 다음과 같다.
AES256의 특성상 16바이트의 패딩이 적용된 암호화 데이터가 생성되는데 위 결과는 그렇지 않다.
CFB 모드는 패딩을 하지 않기 때문인 것을 참고하자
전체 소스를 볼수 있는 경로는 다음과 같다.
https://github.com/tebeknet/TestOpenSSL/blob/master/TestOpenSSL/TestOpenSSL.cpp
OpenSSL은 앞으로도 계속 저 GitHub 위치에 업데이트 된다.
'Tech' 카테고리의 다른 글
Torch7를 사용하는 cpptorch의 Visual Studio 컴파일 방법 (0) | 2019.07.24 |
---|---|
[OpenSSL] EVP 방식으로 OpenSSL 사용하기 2/2 (0) | 2018.08.15 |
PKCS#5 패딩과 PKCS#7 패딩의 차이점 (0) | 2018.08.06 |
몇가지 Random Number Generation 예제 (0) | 2018.08.06 |
[OpenSSL] AES 암호화 복호화 (0) | 2018.08.05 |