apache ssl enable problem

아파치에 ssl 설정을 하고 https 접속을 하려는데 다음의 오류가 나왔다.

Secure Connection Failed

An error occurred during a connection to pchero21.com. SSL received a record that exceeded the maximum permissible length. (Error code: ssl_error_rx_record_too_long)

The page you are trying to view cannot be shown because the authenticity of the received data could not be verified.
Please contact the website owners to inform them of this problem.

구글링을 해봐도 ssl 모듈을 활성화 시키라는 이야기만 나오고…. 단지 설정값을 이리저리 바꿔보고 테스트하는 삽질만 하고 있었다.

 

그러다가, 짚히는 부분이 있어서, ssl 인증서를 다시 만들고 테스트를 해봤더니 잘 되었다.

처음 SSL 인증서를 만들 때, 다음의 명령어를 사용했었다.

sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout ./postfix.key -out ./postfix.crt

문제가 되었던 부분은 rsa:2048 부분이었다.

다음의 명령어로 다시 ssl 인증서를 만들고 설정하니 잘 되었다.

sudo openssl req -x509 -nodes -days 3650 -newkey rsa:1024 -keyout ./postfix.key -out ./postfix.crt

undefined reference to `SSL_CTX_free’

 

사내에서 개발중인 제품을 테스트하기 위해 컴파일을 하던 도중, 아래의 오류를 발견했다. mysqlclient 라이브러리를 함께 사용하는 부분이 있었는데, Linking 을 하던 도중 에러가 발생한 것이다.

/usr/lib/mysql/libmysqlclient.a(client.o): In function `mysql_close_free_options’:
(.text+0xd7d): undefined reference to `SSL_CTX_free’
/usr/lib/mysql/libmysqlclient.a(client.o): In function `mysql_get_ssl_cipher’:
(.text+0x1081): undefined reference to `SSL_get_current_cipher’
/usr/lib/mysql/libmysqlclient.a(client.o): In function `mysql_real_connect’:
(.text+0x3a4c): undefined reference to `SSL_get_peer_certificate’
/usr/lib/mysql/libmysqlclient.a(client.o): In function `mysql_real_connect’:
(.text+0x3a60): undefined reference to `X509_get_subject_name’
/usr/lib/mysql/libmysqlclient.a(client.o): In function `mysql_real_connect’:
(.text+0x3a74): undefined reference to `X509_NAME_oneline’
/usr/lib/mysql/libmysqlclient.a(client.o): In function `mysql_real_connect’:
(.text+0x3a7c): undefined reference to `X509_free’
/usr/lib/mysql/libmysqlclient.a(client.o): In function `mysql_get_ssl_cipher’:
(.text+0x108a): undefined reference to `SSL_CIPHER_get_name’
/usr/lib/mysql/libmysqlclient.a(viossl.o): In function `report_errors’:
(.text+0x45): undefined reference to `ERR_get_error_line_data’
/usr/lib/mysql/libmysqlclient.a(viossl.o): In function `ssl_do’:
(.text+0x8c): undefined reference to `SSL_new’
/usr/lib/mysql/libmysqlclient.a(viossl.o): In function `ssl_do’:
(.text+0x9a): undefined reference to `SSL_clear’
/usr/lib/mysql/libmysqlclient.a(viossl.o): In function `ssl_do’:
(.text+0xa2): undefined reference to `SSL_get_session’
/usr/lib/mysql/libmysqlclient.a(viossl.o): In function `ssl_do’:
(.text+0xae): undefined reference to `SSL_SESSION_set_timeout’
/usr/lib/mysql/libmysqlclient.a(viossl.o): In function `ssl_do’:
(.text+0xbc): undefined reference to `SSL_set_fd’
/usr/lib/mysql/libmysqlclient.a(viossl.o): In function `ssl_do’:
(.text+0xd1): undefined reference to `SSL_get_fd’
/usr/lib/mysql/libmysqlclient.a(viossl.o): In function `ssl_do’:
(.text+0x14b): undefined reference to `SSL_free’
/usr/lib/mysql/libmysqlclient.a(viossl.o): In function `sslconnect’:
(.text+0x16f): undefined reference to `SSL_connect’
/usr/lib/mysql/libmysqlclient.a(viossl.o): In function `sslaccept’:
(.text+0x18f): undefined reference to `SSL_accept’
/usr/lib/mysql/libmysqlclient.a(viossl.o): In function `vio_ssl_close’:
(.text+0x1c5): undefined reference to `SSL_set_quiet_shutdown’
/usr/lib/mysql/libmysqlclient.a(viossl.o): In function `vio_ssl_close’:
(.text+0x1cd): undefined reference to `SSL_shutdown’
/usr/lib/mysql/libmysqlclient.a(viossl.o): In function `vio_ssl_delete’:
(.text+0x212): undefined reference to `SSL_free’
/usr/lib/mysql/libmysqlclient.a(viossl.o): In function `vio_ssl_write’:
(.text+0x261): undefined reference to `SSL_write’
/usr/lib/mysql/libmysqlclient.a(viossl.o): In function `vio_ssl_read’:
(.text+0x281): undefined reference to `SSL_read’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `report_errors’:
(.text+0x25): undefined reference to `ERR_get_error_line_data’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0x99): undefined reference to `SSL_CTX_new’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0xbc): undefined reference to `SSL_CTX_set_cipher_list’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0xd9): undefined reference to `SSL_CTX_load_verify_locations’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0xfb): undefined reference to `SSL_CTX_use_certificate_file’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0x125): undefined reference to `SSL_CTX_use_PrivateKey_file’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0x135): undefined reference to `SSL_CTX_check_private_key’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0x142): undefined reference to `DH_new’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0x166): undefined reference to `BN_bin2bn’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0x185): undefined reference to `BN_bin2bn’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0x1bb): undefined reference to `SSL_CTX_ctrl’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0x1c3): undefined reference to `DH_free’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0x1da): undefined reference to `SSL_load_error_strings’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0x1eb): undefined reference to `SSL_library_init’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0x1f0): undefined reference to `OPENSSL_add_all_algorithms_noconf’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0x206): undefined reference to `SSL_CTX_set_default_verify_paths’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0x21d): undefined reference to `SSL_CTX_free’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0x2bd): undefined reference to `DH_free’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLFd’:
(.text+0x2d6): undefined reference to `SSL_CTX_free’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLAcceptorFd’:
(.text+0x328): undefined reference to `TLSv1_server_method’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLAcceptorFd’:
(.text+0x36f): undefined reference to `SSL_CTX_ctrl’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLAcceptorFd’:
(.text+0x389): undefined reference to `SSL_CTX_set_verify’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLAcceptorFd’:
(.text+0x39f): undefined reference to `SSL_CTX_set_session_id_context’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLConnectorFd’:
(.text+0x3c6): undefined reference to `TLSv1_client_method’
/usr/lib/mysql/libmysqlclient.a(viosslfactories.o): In function `new_VioSSLConnectorFd’:
(.text+0x405): undefined reference to `SSL_CTX_set_verify’
/usr/lib/mysql/libmysqlclient.a(my_compress.o): In function `my_uncompress’:
(.text+0x60): undefined reference to `uncompress’
/usr/lib/mysql/libmysqlclient.a(my_compress.o): In function `my_compress_alloc’:
(.text+0x102): undefined reference to `compress’
collect2: ld returned 1 exit status
make: *** [nxstart] 오류 1

위의 오류는 ssl 관련 라이브러리를 찾지 못해서 발생되는 오류였다. 보통 SSL 라이브러리의 경우 MySQL 이 설치될때 같이 설치가 되는 것 같았는데 이번엔 조금 경우가 특이했다.

OS는 64비트 였지만 제품은 32 비트로 컴파일 해야 했던 것. 처음에는 약간 헤매었지만 결국 해결할 수 있었다.

OS:

Linux localhost.localdomain 2.6.18-238.el5 #1 SMP Thu Jan 13 15:51:15 EST 2011 x86_64 x86_64 x86_64 GNU/Linux

SSL 라이브러리 설치:

# yum install openssl-devel.i386

SSL 라이브러리 추가:

-lssl

 

OpenlSSL – RSA 패키지를 이용한 공개키 & 개인키 만들기

//      enc_rsa.c
//      
//      Copyright 2009 Kim Sung-tae <pchero21@gmail.com>
//      
//      This program is free software; you can redistribute it and/or modify
//      it under the terms of the GNU General Public License as published by
//      the Free Software Foundation; either version 2 of the License, or
//      (at your option) any later version.
//      
//      This program is distributed in the hope that it will be useful,
//      but WITHOUT ANY WARRANTY; without even the implied warranty of
//      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//      GNU General Public License for more details.
//      
//      You should have received a copy of the GNU General Public License
//      along with this program; if not, write to the Free Software
//      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
//      MA 02110-1301, USA.

#include <stdio.h>
#include <string.h>

#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/rand.h>

#define true 1
#define false 0

// 콜백 함수 정의
static void genrsa_cb(int p, int n, void *arb);

int main(int argc, char** argv)
{
    
    int keyLenInput = 512;    // 키 길이
    char outPublicKeyFile[50];    // 공개키를 저장
    char outPrivateKeyFile[50];    // 개인키를 저장
    
    int isPem = true;    // PEM 형식으로…
    
    BIO *publicOut = NULL;    // 공개키가 저장되는 파일 BIO
    BIO *privateOut = NULL;    // 개인키가 저장되는 파일 BIO
    BIO *bio_stdout = NULL;    // 화면에 출력할 stdout BIO
    
    RSA *rsa = NULL;    // RSA 구조체
    
    printf(“키 길이 입력 :”);    // 키 길이 입력
    scanf(“%d”, &keyLenInput);
    
    printf(“저장할 공개키 파일 이름 입력: “);    // 공개키를 저장할 파일명 입력
    scanf(“%s”, outPublicKeyFile);
    
    printf(“저장할 개인키 파일 이름 입력: “);    // 개인키를 저장할 파일명 입력
    scanf(“%s”, outPrivateKeyFile);
    
    // 표준 화면 출력 BIO 생성
    if((bio_stdout = BIO_new(BIO_s_file())) != NULL) {
        BIO_set_fp(bio_stdout, stdout, BIO_NOCLOSE | BIO_FP_TEXT);
    }
    
     //공개키를 저장할 파일 BIO 생성
     if((publicOut = BIO_new(BIO_s_file())) == NULL) {
         printf(“BIO 생성 에러. %s”, outPublicKeyFile);
         exit(1);
     }
    
     // 개인키를 저장할 파일 BIO 생성
     if((privateOut = BIO_new(BIO_s_file())) == NULL) {
         printf(“BIO 생성 에러. %s”, outPublicKeyFile);
         exit(1);
     }
    
     // 파일 BIO와 해당 공개키 저장할 파일 연결
     if(BIO_write_filename(publicOut, outPublicKeyFile) <= 0) {
         printf(“BIO 생성 에러. %s”, outPublicKeyFile);
         exit(1);
     }
    
     // 파일 BIO와 해당 개인키 저장할 파일 연결
     if(BIO_write_filename(privateOut, outPrivateKeyFile) <= 0) {
         printf(“BIO 생성 에러. %s”, outPrivateKeyFile);
         exit(1);
     }
    
     RAND_status();    // seed 생성, 공급
    
     // 키 생성
     rsa = RSA_generate_key(keyLenInput, RSA_F4, genrsa_cb, NULL);
    
     if(isPem) {
         // PEM 포멧으로 표준 화면 출력 BIO에 공개키 출력
         if(!PEM_write_bio_RSA_PUBKEY(bio_stdout, rsa)) {
             printf(“PEM 파일 생성 에러 %s”, outPrivateKeyFile);
             exit(1);
         }
         printf(“nn”);
        
         // PEM 포멧으로 표준 화면 출력 BIO에 개인키 출력
         if(!PEM_write_bio_RSAPrivateKey(bio_stdout, rsa, NULL, NULL, 0, NULL, NULL)) {
             printf(“PEM 파일 생성 에러 %s”, outPrivateKeyFile);
             exit(1);
         }
        
         // PEM 포멧으로 파일 BIO에 공개키 출력
         if(!PEM_write_bio_RSA_PUBKEY(publicOut, rsa)) {
             printf(“PEM 파일 생성 에러 %s”, outPrivateKeyFile);
             exit(1);
         }
        
         // PEM 포멧으로 파일 BIO에 개인키 출력
         if(!PEM_write_bio_RSAPrivateKey(privateOut, rsa, NULL, NULL, 0, NULL, NULL)) {
             printf(“PEM 파일 생성 에러 %s”, outPrivateKeyFile);
             exit(1);
         }
     }
     else {    // 만약 DEM 포멧으로 키 쌍을 출력 한다면..
        printf(“DEM PUBLIC KEYn”);
        
        // DEM 포멧으로 표준 화면 출력 BIO에 공개키 출력
        if(!i2d_RSA_PUBKEY_bio(bio_stdout, rsa)) {
            printf(“DEM 파일 생성 에러 %s”, outPrivateKeyFile);
            exit(1);
        }
        
        printf(“nn”);
        printf(“DER PRIVATE KEYn”);
        printf(“n”);
        
        // DEM 포멧으로 표준 화면 출력 BIO에 개인키 출력
        if(!i2d_RSAPrivateKey_bio(bio_stdout, rsa)) {
            printf(“DEM 파일 생성 에러 %s”, outPrivateKeyFile);
            exit(1);
        }
        
        // DEM 포멧으로 파일 BIO에 공개키 출력
        if(!i2d_RSA_PUBKEY_bio(publicOut, rsa)) {
            printf(“DEM 파일 생성 에러 %s”, outPrivateKeyFile);
            exit(1);
        }
        
        // DEM 포멧으로 파일 BIO에 개인키 출력
        if(!i2d_RSAPrivateKey_bio(privateOut, rsa)) {
            printf(“DEM 파일 생성 에러 %s”, outPrivateKeyFile);
            exit(1);
        }
    }
    
    // RSA 구조체 메모리에서 삭제
    if(rsa != NULL)
        RSA_free(rsa);
        
    // BIO를 메모리에서 삭제
    if(publicOut != NULL) BIO_free_all(publicOut);
    if(privateOut != NULL) BIO_free_all(privateOut);
    
    
    return 0;
}

// 콜백 함수
static void genrsa_cb(int p, int n, void *arg)
{
    char c = ‘*’;
    
    // prime number e 의 생성 과정을 표시
    if(p == 0) c = ‘.’;
    if(p == 1) c = ‘+’;
    if(p == 2) c = ‘*’;
    if(p == 3) c = ‘n’;
    
    printf(“%c”, c);
}

OpenSSL – 데이터 암호화



#include <stdio.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/rand.h>
#include <openssl/pem.h>


 


#define IN_FILE “./plain.txt”   // plain file
#define OUT_FILE “./encrypt.txt”        // cipher file


 


unsigned char* readFile(char *file, int *readLen);
unsigned char *readFileBio(BIO *fileBIO, int *readLen);
unsigned char *addString(unsigned char *destString, int destLen, const unsigned char *addString, int addLen);


 


int main(int argc, char* argv[])
{
        // 키와 IV값은 편의를 위해 직접 만든다.


        unsigned char key[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
        unsigned char iv[] = {1, 2, 3, 4, 5, 6, 7, 8};


        int len;
        unsigned char *readBuffer, *outbuf;
        int outlen, tmplen;



        BIO *errBIO = NULL;
        BIO *outBIO = NULL;


 


        // 에러 발생의 경우 해당 에러 스트링 출력을 위해 미리 에러 스트링들을 로딩.
        ERR_load_crypto_strings();


 


        // 표준 화면 출력 BIO 생성
        if((errBIO = BIO_new(BIO_s_file())) != NULL)
                BIO_set_fp(errBIO, stderr, BIO_NOCLOSE|BIO_FP_TEXT);


 


        // 파일 출력 BIO 생성
        outBIO = BIO_new_file(OUT_FILE, “wb”);
        if(!outBIO) {
                BIO_printf(errBIO, “Can not create file [%s]!”, OUT_FILE);
                ERR_print_errors(errBIO);
                exit(1);
        }


 


        // 파일에서 데이터 읽어오기
        readBuffer = readFile(IN_FILE, &len);


 


        // 암호화 컨텍스트 EVP_CIPHER_CTX 생성, 초기화
        EVP_CIPHER_CTX ctx;
        EVP_CIPHER_CTX_init(&ctx);


 


        // 초기화
        EVP_EncryptInit_ex(&ctx, EVP_bf_cbc(), NULL, key, iv);


 


        // 초기화가 끝난후에 해야 한다. 암호문 저장할 버퍼 생성
        outbuf = (unsigned char*)malloc(sizeof(unsigned char) * (len + EVP_CIPHER_CTX_block_size(&ctx)));


 


        // 업데이트. 마지막 블록을 제외하고 모두 암호화.
        if(!EVP_EncryptUpdate(&ctx, outbuf, &outlen, readBuffer, strlen((char *)readBuffer))) {
                return 0;
        }


 


        // 종료. 마지막 블록을 암호화
        if(!EVP_EncryptFinal_ex(&ctx, outbuf + outlen, &tmplen)) {
                return 0;
        }


 


        // 암호문 길이는 업데이트. 종료 과정에서 나온 결과의 합
        outlen += tmplen;
        EVP_CIPHER_CTX_cleanup(&ctx);


        BIO_printf(errBIO, “Create Cipher Complete.nSaving [%s] filen”, OUT_FILE);


 


        // 파일에 같은 내용을 출력한다.
        BIO_write(outBIO, outbuf, outlen);


 


        // 객체 제거
        BIO_free(outBIO);


 


        return 0;
}


 


 


unsigned char* readFile(char *file, int *readLen)
{
        unsigned char *retBuffer = NULL;
        unsigned char *buffer = NULL;
        int length = 0;


 


        // 파일 BIO 정의
        BIO *fileBIO = NULL;


 


        // 인자로 넘어온 파일을 열고, 파일 BIO 생성
        fileBIO = BIO_new_file(file, “rb”);
        if(!fileBIO) {
                printf(“file open(%s) error!n”, file);
                exit(1);
        }


 


        // 임시로 1000 바이트 만큼의 읽은 데이터를 저장할 버퍼 생성.
        buffer = (unsigned char*)malloc(1001);
        *readLen = 0;


 


        while(1) {


                // 파일 BIO에서 1000 바이트 만큼 읽어서 buffer에 저장 한다.
                length = BIO_read(fileBIO, buffer, 1000);


 


                // 안전을 위해 버퍼의 끝은 NULL로 채운다.
                buffer[length] = 0;


 


                // 임시로 읽은 1000 바이트의 데이터를 리턴 버퍼에 더한다.
                retBuffer = addString(retBuffer, *readLen, buffer, length);


 


                // 지금까지 읽은 데이터의 길이를 더한다.
                *readLen = *readLen + length;


                // 만약 지금 파일에서 읽은 데이터의 길이가 꼭 1000 바이트라면 앞으로 더 읽을


                // 데이터가 있을 것이다. 하지만 1000 바이트보다 작다면 더 이상 읽을 데이터가


                // 없을 것이므로 종료한다.


                if(length == 1000)


                      // 파일 포인터를 1000 바이트 뒤로 옮긴다.
                      BIO_seek(fileBIO, 1000);
                else
                      break;
        }


 


        // 객체 삭제


        BIO_free(fileBIO);


        free(buffer);


 


        return retBuffer;
}


 



unsigned char* addString(unsigned char* destString, int destLen, const unsigned char *addString, int addLen)
{


        // 리턴할 버퍼 정의
        unsigned char *retString;
        int i;


 


        // 만약 덧붙일 대상 버퍼가 NULL, 이거나 길이가 0이면 덧붙일 대상버퍼가 없는 경우


        // 이므로 새로 생성하고, 덧붙일 버퍼의 내용을 복사 한다.


        if((destString == NULL) || (destLen == 0)) {


                // 덧붙일 버퍼 길이 만큼의 버퍼 생성
                retString = (unsigned char*)malloc(sizeof(unsigned char) * (addLen + 1));


 


                // 덧붙일 버퍼의 내용을 새로운 버퍼에 복사
                for(i = 0; i < addLen; i++) {
                      retString[i] = addString[i];
                }


                // 안전을 위해 버퍼의 마지막에 NULL 바이트를 뭍인다.
                retString[i] = NULL;
        }


        // 덧붙일 대상 버퍼가 있는 경우이므로 덧붙일 대상 버퍼의 길이를


        // 더한 만큼의 버퍼를 새로 생성하고, 두 버퍼의 내용을 새로운 버퍼에 복사한다.
        else {


                // 대상 버퍼의 길이와 덧붙일 길이를 더한 만큼의 버퍼 생성
                retString = (unsigned char*)malloc(sizeof(unsigned char) * (destLen + addLen + 1));


                // 덧붙일 대상 버퍼 내용을 새로운 버퍼에 복사
                for(i = 0; i < destLen; i++) {
                      retString[i] = destString[i];
                }


                // 덧붙일 버퍼의 내용을 새로운 버퍼에 복사
                for(i = 0; i < addLen; i++) {
                      retString[i + destLen] = addString[i];
                }


                // 안전을 위해 버퍼의 마지막에 NULL 바이트를 붙인다.
                retString[i + destLen] = NULL;
        }


 


        // 메모리에서 삭제


        free(destString);


        return retString;
}


OpenSSL- 키와 IV 생성 프로그램

 


 


#include <stdio.h>


#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/rand.h>


 


int main(int argc, char* argv[])
{
        int i;


 


        // salt bufer length = 8
        unsigned char salt[8];
        // EVP_CIPHER = Cipher structure
        const EVP_CIPHER *cipher = NULL;
        // password pointer. password = “aaaa”
        char *password = “aaaa”;


        // 키와 IV가 저장될 변수를 정의하고 길이는 OpenSSL에서 알아서 정해준다.
        unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];


 


        int ret = 0;


        // PRNG를 통해 랜덤 수를 만들고 그 값을 Salt에 저장한다. 길이는 8
        ret = RAND_pseudo_bytes(salt, 8);


        // PRNG에서 에러가 발생할 경우 에러 메시지를 출력하고 프로그램을 종료한다.
        if(ret < 0) {
                printf(“Can’t generate random number.n”);
                return 0;
        }


 


        // 암호화 구조체의 인스턴스를 생성. 여기서는 DES의 ECB 모드의 암호화 구조체 생성
        cipher = EVP_des_ecb();


 


        // 키와 IV를 생성함. 인자는 암호화 구조체, 다이제스트 구조체, salt 값, 패스워드


        // 카운트는 생성될 키와 IV를 저장할 변수


        // 다이제스트 구조체는 EVP_md5() 함수를 통해 생성. 카운트는 한번
        EVP_BytesToKey(cipher, EVP_md5(), salt, (unsigned char *)password, strlen(password), 1, key, iv);


        // display salt
        for(i = 0; i < sizeof(salt); i++) {
                printf(“%02X”, salt[i]);
        }


        // Display key
        if(cipher->key_len > 0) {
                for(i = 0; i < cipher->key_len; i++) {
                        printf(“%02X”, key[i]);
                }
        }


 


        // Display IV
        if(cipher->iv_len > 0) {
                for(i = 0; i < cipher->iv_len; i++) {
                        printf(“%02X”, iv[i]);
                }
        }


 


        return 0;
}