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 알고리즘에 대해

windows에서 간단하게 크롬캐스트(Chromecast)를 통해 윈도우 화면 미러링 방법

Embedded Linux USB Ethernet Gadget 사용하기

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

python winsound를 이용한 윈도우 환경에서 소리 재생 예제