본문 바로가기

카테고리 없음

[펌] [OpenSSL 프로그래밍] RSA (비 대칭키) 암호화

프로젝트를 위해서 일단 퍼오기로 한다.


1. OpenSSL 이란

Secure Sockets Layer (SSL v2/v3)  Transport Layer Security (TLS v1) 프로토콜 뿐만 아니라 보다 강력한 암호화 라이브러리 제공을 위한 오픈 소스 toolkit 이다.

 

현재(2007버전은 OpenSSL 0.9.8e 까지 나와 있는 상태이며http://openssl.org/source 에서 소스를 받아 설치 할 수 있다.

 

2. 함수 설명

2.1 RSA(3) - RSA public key 암호화시스템

- RSA  public key 기반의 암호화 알고리즘으로현재 가장 널리 사용되는 암고리즘 중의 하나이다.

 

- RSA 구조체

        struct
        {
        BIGNUM *n;              // public modulus
        BIGNUM *e;              // public exponent
        BIGNUM *d;              // private exponent
        BIGNUM *p;              // secret prime factor
        BIGNUM *q;              // secret prime factor
        BIGNUM *dmp1;           // d mod (p-1)
        BIGNUM *dmq1;           // d mod (q-1)
        BIGNUM *iqmp;           // q^-1 mod p
        // ...
        } RSA;

RSA 구조체는 BIGNUM components 로 구성되어 있으며, public key  private key 모두를 가지고 있다.

 

주요 함수 프로토 타입

 #include <openssl/rsa.h>
 #include <openssl/engine.h>

 

 // 객체 생성삭제

 RSA * RSA_new(void);
 void RSA_free(RSA *rsa);

 

 // RSA 복호화 

 int RSA_public_encrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding);
 int RSA_private_decrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding);
 int RSA_private_encrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa,int padding);
 int RSA_public_decrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa,int padding);

 

 // RSA 서명 및 검증

 int RSA_sign(int type, unsigned char *m, unsigned int m_len, unsigned char *sigret, unsigned int *siglen, RSA *rsa);
 int RSA_verify(int type, unsigned char *m, unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, RSA *rsa);

 

 int RSA_size(const RSA *rsa);

 

  // RSA 키 생성 및 검사

 RSA *RSA_generate_key(int num, unsigned long e, void (*callback)(int,int,void *), void *cb_arg);

 int RSA_check_key(RSA *rsa);

 

 int RSA_blinding_on(RSA *rsa, BN_CTX *ctx);
 void RSA_blinding_off(RSA *rsa);

 

 void RSA_set_default_method(const RSA_METHOD *meth);
 const RSA_METHOD *RSA_get_default_method(void);
 int RSA_set_method(RSA *rsa, const RSA_METHOD *meth);
 const RSA_METHOD *RSA_get_method(const RSA *rsa);
 RSA_METHOD *RSA_PKCS1_SSLeay(void);
 RSA_METHOD *RSA_null_method(void);
 int RSA_flags(const RSA *rsa);
 RSA *RSA_new_method(ENGINE *engine);

 

 // RSA context 출력

 int RSA_print(BIO *bp, RSA *x, int offset);
 int RSA_print_fp(FILE *fp, RSA *x, int offset);

 

 int RSA_get_ex_new_index(long argl, char *argp, int (*new_func)(), int (*dup_func)(), void (*free_func)());
 int RSA_set_ex_data(RSA *r,int idx,char *arg);
 char *RSA_get_ex_data(RSA *r, int idx);

 

 int RSA_sign_ASN1_OCTET_STRING(int dummy, unsigned char *m, unsigned int m_len, unsigned char *sigret, unsigned int *siglen, RSA *rsa);
 int RSA_verify_ASN1_OCTET_STRING(int dummy, unsigned char *m, unsigned int m_len, unsigned char *sigbuf, 
unsigned int siglen, RSA *rsa);

전부 사용할 일도 없거니와 사용하기도 싫으니 설명은 생략.. (http://openssl.org  document 탭에서 찾아 볼 수 있다.)

 

 

2.2 테스트 프로그램

- RSA 알고리즘을 활용하여 간단한 테스트 프로그램을 작성해 보자.

아래 코드는 텍스트를 암복호화 하는 코드이다.

 

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <openssl/rsa.h>
 #include <openssl/evp.h>

 int main(int argc, char *argv[])
 {
        RSA *rsa;
        int len, ret;
        unsigned char *cipherText;
        unsigned char *plainText = "Hello RSA!";
        unsigned char *originText;

       

        rsa = RSA_generate_key(1024, 3, NULL, NULL);

       

        if (RSA_check_key(rsa) != 1)
        {
              perror("not gnerate RSA key");
              exit(0);
         }

       

        cipherText = (unsigned char *) calloc (1, (size_t) RSA_size(rsa));

       

        len = RSA_public_encrypt(strlen(plainText), plainText, cipherText, rsa, RSA_PKCS1_PADDING);

 

        if (len == -1)
       {
              perror("not encrypt data");
              exit(0);
        }

       

        printf("plain text: %s\n", plainText);
        printf("ciper text: %s\n", cipherText);

 

        originText = (unsigned char *) calloc(1, strlen(plainText)+1);
 
        ret = RSA_private_decrypt(len, cipherText, originText, rsa, RSA_PKCS1_PADDING);

 

        if (ret == -1)
        {
              perror("not decrypt data");
              exit(0);
        }

 

        printf("origin text: %s\n", originText);
 

        free(cipherText);
        free(originText);
        RSA_free(rsa);

 

        return 0;
}

 

 

3. 에러 체크

- OpenSSL 라이브러리는 에러 상황에 대한 print out 에 대한 함수를 제공한다.

자세한 내용은 http://www.openssl.org/support/faq.html 에 나와 있다.

 

에러 메시지 확인 방법은 다음과 같다.

 

  /* errlog.c */ 

 

 #include ...

 

 int main(int arg, char** argv)

 {

    .....

    pPubKey = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL);

   

    if (pPubKey == NULL)

    {

        err_log();

        exit(0);

    }

    .....

 }

 

 void err_log()

 {

    FILE* err;

 

    err = fopen("err.log", "wb");

 

    ERR_load_crypto_strings();

    ERR_print_errors_fp(err);

 

    fclose(err);

 }

 

에러 메시지를 확인해도 모르겠다면, openssl-users 에서 에러 메시지를 검색해 보거나 질문을 한다면 개발자가 답변을 해줄 것이다.





위에 소스코드도 있고 다 좋다.. 근데..  컴파일은 어떻게 하는걸까?? 

user@ubuntu:~$ gcc -o test testrsa.c -lcrypto
/usr/bin/ld: cannot find -lcrypto
collect2: ld returned 1 exit status

--> 헉.. 에러메시지다.. ㅡ,.ㅡ 구글링.. 

user@ubuntu:~$ sudo apt-get install libssl-dev

user@ubuntu:~$ gcc -o test testrsa.c -lcrypto

user@ubuntu:~$ ./test 

하핫.. 잘된다.. 

근데.. 윈도우에서는 어떻게 쓰는거지?