openssl rsa encryption decryption 예제 코드

본 글은 openssl 라이브러 api를 사용하여 public / private key를 이용한 암호화/ 복호화 예제 코드를 싣고 있다.

RSA Key는 파일에서 불러오며, "hello openssl crypto!!" 문자를 public key를 사용하여 암호화 하였고, private key를 사용해 복호화 했다. 키를 파일에서 불러오고, 암호화/복호화 하는 기능은 별도의 API로 만들었으며, 사용 방법은 main 함수를 참조하면 된다.

[소스코드]
#include <stdio.h>
#include <string.h>

#include <openssl/bio.h>
#include <openssl/asn1.h>
#include <openssl/rsa.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/pem.h>

#define safe_free(x) if(x){free(x);x=NULL;}

#define rsa_public_key 0
#define rsa_private_key 1

typedef struct _rsa_ctx_t
{
RSA *rsa_key;
int key_type;
int ras_modulus_size;
}rsa_ctx_t;


RSA *ras_loadkey(char *key_path, int key_type);
rsa_ctx_t *rsa_init(char *key_path, int key_type);
int rsa_get_max_encryped_size(rsa_ctx_t *ctx);
int rsa_encryption(rsa_ctx_t *ctx, unsigned char *in, int inlen, unsigned char *out, int outsize);
int rsa_decryption(rsa_ctx_t *ctx, unsigned char *in, int inlen, unsigned char *out, int outsize);
void rsa_deinit(rsa_ctx_t *ctx);

/*파일에서 키를 불러오는 온다.
*/
RSA *ras_loadkey(char *key_path, int key_type)
{
#define MINBITS   1024
#define MAXBITS   8192

RSA *_rsa = NULL;
BIO *_bio = NULL;
EVP_PKEY *pkey = NULL;

if(!key_path) return NULL;

_bio = BIO_new(BIO_s_file());

if(!_bio) return NULL;

if (BIO_read_filename(_bio, key_path) == 1) 
{
if(key_type == rsa_public_key)
{
pkey = PEM_read_bio_PUBKEY(_bio, NULL, NULL, NULL);
}
else if(key_type == rsa_private_key)
{
pkey = PEM_read_bio_PrivateKey(_bio, NULL, NULL, NULL);
}

if(pkey) 
{
_rsa = EVP_PKEY_get1_RSA(pkey);
if (_rsa)
{
RSA_up_ref(_rsa);
}

EVP_PKEY_free(pkey);
pkey = NULL;
}

if (_rsa == NULL)
{
printf("[%s] Unable to get RSA key from file\n",__func__);
}
else
{
printf("[%s] BIO_read_filename %s fail  \n",__func__, key_path);
}

BIO_free(_bio);

if (_rsa)
{
int strength = BN_num_bits(_rsa->n);
if (strength < MINBITS || strength > MAXBITS)
{
RSA_free(_rsa);
_rsa = NULL;
printf("[%s] Invalid key\n",__func__);
}
}

return _rsa;
}


rsa_ctx_t *rsa_init(char *key_path, int key_type)
{
rsa_ctx_t *ctx = NULL;
if(!key_path) return NULL;

ctx = (rsa_ctx_t*)malloc(sizeof(rsa_ctx_t));
if(ctx)
{
memset(ctx,0,sizeof(rsa_ctx_t));

ctx->key_type = key_type;
ctx->rsa_key = ras_loadkey(key_path,key_type);
if(ctx->rsa_key == NULL)
{
rsa_deinit(ctx);
return NULL;
}

ctx->ras_modulus_size = RSA_size(ctx->rsa_key);
}

return ctx;
}


int rsa_get_max_encryped_size(rsa_ctx_t *ctx)
{
if(ctx)
{
return ctx->ras_modulus_size;
}
return 0;
}

int rsa_encryption(rsa_ctx_t *ctx, unsigned char *in, int inlen, unsigned char *out, int outsize)
{
int size = 0;
if(!ctx || inlen <= 0 || !in || !out || outsize <= 0) return -1;
if(outsize < ctx->ras_modulus_size)
{
printf("[%s] outsize %d < ctx->ras_modulus_size %d\n",__func__,outsize,ctx->ras_modulus_size);
return -1;
}

if(ctx->key_type == rsa_public_key)
{
size = RSA_public_encrypt(inlen, in, out, ctx->rsa_key, RSA_PKCS1_PADDING);
}
else if(ctx->key_type == rsa_private_key)
{
size = RSA_private_encrypt(inlen, in, out, ctx->rsa_key, RSA_PKCS1_PADDING);
}
return size;
}

int rsa_decryption(rsa_ctx_t *ctx, unsigned char *in, int inlen, unsigned char *out, int outsize)
{
int size = 0;
if(!ctx || inlen <= 0 || !in || !out || outsize <= 0) return -1;

if(ctx->key_type == rsa_public_key)
{
size = RSA_public_decrypt(inlen, in, out, ctx->rsa_key, RSA_PKCS1_PADDING);
}
else if(ctx->key_type == rsa_private_key)
{
size = RSA_private_decrypt(inlen, in, out, ctx->rsa_key, RSA_PKCS1_PADDING);
}
return size;
}

void rsa_deinit(rsa_ctx_t *ctx)
{
if(ctx)
{
if(ctx->rsa_key)
RSA_free(ctx->rsa_key);
ctx->rsa_key = NULL;
}

free(ctx);
}
}

int main(int argc, char** argv)
{
rsa_ctx_t *public_rsa = rsa_init("./PublicKey.pem",rsa_public_key);
rsa_ctx_t *private_rsa = rsa_init("./PrivateKey.pem",rsa_private_key); 
int max_encryped_data_size = 0;
int i = 0;
unsigned char test_msg[] = "hello openssl crypto!!";
unsigned char *crypted_msg = NULL;
unsigned char *decrypted_msg = NULL;

if( public_rsa!= NULL && private_rsa != NULL)
{
max_encryped_data_size = rsa_get_max_encryped_size(public_rsa);

crypted_msg = (unsigned char*) malloc(sizeof(unsigned char)*max_encryped_data_size);
decrypted_msg = (unsigned char*) malloc(sizeof(unsigned char)*max_encryped_data_size);
if(crypted_msg && decrypted_msg)
{
int crypted_len = 0;
int decrypted_len = 0;
memset(crypted_msg,0,sizeof(unsigned char)*max_encryped_data_size);
memset(decrypted_msg,0,sizeof(unsigned char)*max_encryped_data_size);

crypted_len = rsa_encryption(public_rsa,test_msg,strlen((char*)test_msg),crypted_msg,max_encryped_data_size);
if( crypted_len > 0)
{
printf("rsa_encryption using public key\n");
printf("in : %s\n",test_msg);
printf("out : ");
for(i=0;i<crypted_len;i++) printf("%x",crypted_msg[i]);
printf("\n");
}
else
{
printf("rsa_encryption using public key fail\n");
}

decrypted_len = rsa_decryption(private_rsa,crypted_msg,crypted_len,decrypted_msg,max_encryped_data_size);
if(decrypted_len > 0)
{
printf("\nrsa_decryption using private key\n");
printf("in : ");
for(i=0;i<crypted_len;i++) printf("%x",crypted_msg[i]);
printf("\n");
printf("out : %s\n",decrypted_msg);
}
else
{
printf("rsa_decryption using private key fail\n");
}

}
}
safe_free(decrypted_msg);
safe_free(crypted_msg);
if (public_rsa)
{
rsa_deinit(public_rsa);
public_rsa = NULL;
}

if (private_rsa) 
{
rsa_deinit(private_rsa);
private_rsa = NULL;
}
    return 0;
}

[빌드]
gcc -o rsacrypto rsacrypt.c -lssl -lcrypto


[실행 결과]

이전에 올린적 있는 rsakeygen을 사용하여 생성된 키를 사용하였다.



[관련 포스트]

댓글

이 블로그의 인기 게시물

간단한 cfar 알고리즘에 대해

python ctypes LoadLibrary로 windows dll 로드 및 함수 호출 예제

base64 인코딩 디코딩 예제 c 소스

쉽게 설명한 파티클 필터(particle filter) 동작 원리와 예제

mkfs.fat Device or resource busy 에러 해결법