http://suite.tistory.com/entry/AES-암호화-crypto-cbc-모드-샘플-by-openssl
openssl 라이브러리 함수 이용하여 aes cbc 함수 샘플 작성해봄
1. openssl 최신버전 2013.06 기준 다운로드
$>wget http://www.openssl.org/source/openssl-1.0.1e.tar.gz
2. 압축 풀기
$>tar fxz openssl-1.0.1e.tar.gz
3. libcrypto.a 생성
$>cd openssl-1.0.1e;make
-> $> ls 해서 libcrypto.a 파일 확인
4. openssl-1.0.1e/apps/speed.c 참고해서
build : $>gcc fs_aes_cbc.c libcrypto.a
/*
================================================================================
OpenSSL 1.0.1e 11 Feb 2013
Copyright (c) 1998-2011 The OpenSSL Project
Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson
All rights reserved.
DESCRIPTION
-----------
The OpenSSL Project is a collaborative effort to develop a robust,
commercial-grade, fully featured, and Open Source toolkit implementing the
Secure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS v1)
protocols as well as a full-strength general purpose cryptography library.
The project is managed by a worldwide community of volunteers that use the
Internet to communicate, plan, and develop the OpenSSL toolkit and its
related documentation.
OpenSSL is based on the excellent SSLeay library developed from Eric A. Young
and Tim J. Hudson. The OpenSSL toolkit is licensed under a dual-license (the
OpenSSL license plus the SSLeay license) situation, which basically means
that you are free to get and use it for commercial and non-commercial
purposes as long as you fulfill the conditions of both licenses.
================================================================================
* aes_cbc() mode sample by openssl
* openssl : wget http://www.openssl.org/source/openssl-1.0.1e.tar.gz
* reference source : openssl-1.0.1e/apps/speed.c
* build : $>gcc test_fs_aes_cbc.c libcrypto.a
* copyleft @http://suite.tistory.com fs
*/
#include <stdio.h>
#include <string.h>
#include <openssl/aes.h>
static const unsigned char key32[32]=
{0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,
0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,
0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34,
0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34,0x56};
#define BLOCK_SIZE 16
#define FREAD_COUNT 4096
#define KEY_BIT 256
#define IV_SIZE 16
#define RW_SIZE 1
#define SUCC 0
#define FAIL -1
AES_KEY aes_ks3;
unsigned char iv[IV_SIZE];
int fs_encrypt_aes(char *in_file,char *out_file)
{
int i=0;
int len=0;
int padding_len=0;
char buf[FREAD_COUNT+BLOCK_SIZE];
FILE *fp=fopen(in_file,"rb");
if( fp == NULL ){
fprintf(stderr,"[ERROR] %d can not fopen('%s')\n",__LINE__,in_file);
return FAIL;
}
FILE *wfp=fopen(out_file,"wb");
if( wfp == NULL ){
fprintf(stderr,"[ERROR] %d can not fopen('%s')\n",__LINE__,out_file);
return FAIL;
}
memset(iv,0,sizeof(iv)); // init iv
AES_set_encrypt_key(key32 ,KEY_BIT ,&aes_ks3);
while( len = fread( buf ,RW_SIZE ,FREAD_COUNT, fp) ){
if( FREAD_COUNT != len ){
break;
}
AES_cbc_encrypt(buf ,buf ,len ,&aes_ks3 ,iv ,AES_ENCRYPT);
fwrite(buf ,RW_SIZE ,len ,wfp);
}
// padding : pkcs5? pkcs7?? http://wiki.dgoon.net/doku.php?id=ssl:pkcs_5
padding_len=BLOCK_SIZE - len % BLOCK_SIZE;
printf("enc padding len:%d\n",padding_len);
memset(buf+len, padding_len, padding_len);
/**
for(i=len; i < len+padding_len ;i++){
buf[i]=padding_len;
}
**/
AES_cbc_encrypt(buf ,buf ,len+padding_len ,&aes_ks3, iv,AES_ENCRYPT);
fwrite(buf ,RW_SIZE ,len+padding_len ,wfp);
fclose(wfp);
fclose(fp);
return SUCC;
}
int fs_decrypt_aes(char *in_file,char *out_file)
{
char buf[FREAD_COUNT+BLOCK_SIZE];
int len=0;
int total_size=0;
int save_len=0;
int w_len=0;
FILE *fp=fopen(in_file,"rb");
if( fp == NULL ){
fprintf(stderr,"[ERROR] %d can not fopen('%s')\n",__LINE__,in_file);
return FAIL;
}
FILE *wfp=fopen(out_file,"wb");
if( wfp == NULL ){
fprintf(stderr,"[ERROR] %d can not fopen('%s')\n",__LINE__,out_file);
return FAIL;
}
memset(iv,0,sizeof(iv)); // the same iv
AES_set_decrypt_key(key32 ,KEY_BIT ,&aes_ks3);
fseek(fp ,0 ,SEEK_END);
total_size=ftell(fp);
fseek(fp ,0 ,SEEK_SET);
printf("total_size %d\n",total_size);
while( len = fread( buf ,RW_SIZE ,FREAD_COUNT ,fp) ){
if( FREAD_COUNT == 0 ){
break;
}
save_len+=len;
w_len=len;
AES_cbc_encrypt(buf ,buf ,len ,&aes_ks3 ,iv ,AES_DECRYPT);
if( save_len == total_size ){ // check last block
w_len=len - buf[len-1];
printf("dec padding size %d\n" ,buf[len-1]);
}
fwrite(buf ,RW_SIZE ,w_len ,wfp);
}
fclose(wfp);
fclose(fp);
return SUCC;
}
//copyleft @http://suite.tistory.com fs
int main(int argc, char *args[])
{
if( argc != 2 ){
printf("[Usage] %s fs_src_file\n",args[0]);
return FAIL;
}
if( fs_encrypt_aes(args[1],"fs_in.file") == SUCC){
fs_decrypt_aes("fs_in.file","fs_out.file");
printf("result:[fs_out.file]\n");
}
return 0;
}
* 실행 결과
$ vi fs_aes_cbc.c
$ make
gcc fs_aes_cbc.c libcrypto.a
$ ./a.out fs_aes_cbc.c
result:[out.file]
$ ls -ltr
합계 11512
-rw-rw-r--. 1 ir ir 3914268 2013-05-31 17:03 libcrypto.a
-rw-rw-r--. 1 ir ir 36 2013-06-04 15:10 Makefile
-rw-rw-r--. 1 i ir 2979 2013-06-04 15:10 fs_aes_cbc.c
-rwxrwxr-x. 1 ir i 23698 2013-06-04 16:21 a.out
-rw-rw-r--. 1 i ir 2992 2013-06-04 16:21 fs_in.file
-rw-rw-r--. 1 irtu irt 2979 2013-06-04 16:21 fs_out.file
실제 업무에서는 C++ 기반이면 class화 사용이 BEST!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 참고 링크 : http://misc-file.googlecode.com/svn/vm/aes_cbc_encrypt.cpp
* EVP? : openssl 암호화 관련 검색을 계속 해보면 EVP 관련 함수로 암호화 함수가 있다.
EVP 무슨약자인지는 찾지 못했고 "하이레벨 함수들" : http://www.openssl.org/docs/crypto/evp.html
fs/openssl-1.0.1e/test/evp*.c 보면
EVP_CIPHER_CTX_init() , EVP_EncryptUpdate() , EVP_EncryptFinal() 이용해서 암호화 알고리즘을 적용 하는 예제가 있음
출처: http://suite.tistory.com/entry/AES-암호화-crypto-cbc-모드-샘플-by-openssl [스토뤼~~]