Notice
Recent Posts
Recent Comments
Link
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Tags
more
Archives
Today
Total
관리 메뉴

US0

CH.4 Openssl를 활용한 암호화 프로그래밍<EVP API를 활용한 DES_CBC 암.복호화 실습. OP2.> 본문

Security/Cryptography

CH.4 Openssl를 활용한 암호화 프로그래밍<EVP API를 활용한 DES_CBC 암.복호화 실습. OP2.>

us0 2018. 11. 8. 10:43

이전 Chapter 들!!!! 코드를 이해하지 못하겠다면 앞쪽 chapter들을 확인해보자!!!


2018/11/05 - [Security/Cryptography] - CH.0 Openssl를 활용한 암호화 프로그래밍 <기초지식>

2018/11/05 - [Security/Cryptography] - CH.1 Openssl를 활용한 암호화 프로그래밍 <암호화 구조체>

2018/11/05 - [Security/Cryptography] - CH.2 Openssl를 활용한 암호화 프로그래밍 <비밀키 암호화 순서>

2018/11/08 - [Security/Cryptography] - CH.3 Openssl를 활용한 암호화 프로그래밍




CH.4 Openssl를 활용한 암호화 프로그래밍

<EVP API를 활용한 DES_CBC 암.복호화 실습. OP2.>




이번 Chpater 4 는 저번시간에 했던 EVP API를 이용하여

EVP 순서인  초기화 -> 업데이트 -> 종료 이렇게 3가지 순서에 맞춰 진행 하였다.


이번 Chapter는 이것을 살짝 응용하여  약간 복잡하게(?) 16바이트 씩 암호화 시키는 실습이다!!!!

(이 전 chapter 3은 8바이트의 배수만큼 한번에 update시키고 나머지 패딩값이 있는 공간을 종료 과정을 거쳐 암호화 시켰다. 




각각 코드라인에 대한 자세한 설명은

2018/11/08 - [Security/Cryptography] - CH.3 Openssl를 활용한 암호화 프로그래밍


여기에 나와있으니 코드보다가 잘 모르는것 있으면 여기 참조하면서 보자!!! 



op1과  op2 과정은 약간 for문과 while문 정도의 차이 라고 생각하면서 보면 편하다!!!!!!

(op1은 8의 배수만큼 한번에 update!! op2는 16바이트 씩!! update!!!)



이번 chapter 에서는 저번 chapter와 비슷하니까 약간의 설명은 주석으로 하겠다 ㅎ.ㅎ



#include <stdio.h>

#include<stdlib.h>

#include<string.h>


#include<openssl/rand.h>

#include<openssl/evp.h>



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

    

    

    

    /*

     *

     * Enctypt

     *

     *

     */

    

    //EVP API를 써서 des_cbc를 하기위해 초가화 과정

    const EVP_CIPHER *c= EVP_des_cbc();

    EVP_CIPHER_CTX *ctx_enc=EVP_CIPHER_CTX_new();

    

    if(ctx_enc == NULL){

        printf("EVP_CIPHER_CTX_new is NULL error!!\n");

        return -1;

    }

    

    if(!(EVP_EncryptInit_ex(ctx_enc, c, NULL, NULL, NULL))){ //콘텍스트에 EVP_des_cbc를 사용한다고 말해준다!!

        printf("EVP_EncryptInit_ex error!!\n");                //그래서 초반에 EVP_EncryptInit_ex()함수를 실행해준다.

        return -1;

    }

    

    

    /**************************************************************************************************

     

     key, iv initialized

     Random key, iv use RAND_bytes()

     **************************************************************************************************/

    

    printf("\n");

    printf("****************************Key, IV initailized********************************\n");

    printf("\n");

    

    unsigned char *key = (unsigned char*)malloc(EVP_CIPHER_CTX_key_length(ctx_enc));    //key

    unsigned char *iv = (unsigned char*)malloc(EVP_CIPHER_CTX_iv_length(ctx_enc));      //iv

    

    if(!RAND_bytes(key, EVP_CIPHER_CTX_key_length(ctx_enc))){

        printf("RAND_bytes function error!!\n");

        return -1;

    }

    

    if(!RAND_bytes(iv, EVP_CIPHER_CTX_iv_length(ctx_enc))){

        printf("RAND_bytes function error!!\n");

        return -1;

    }

    

    printf("Use key value : ");

    for(int i=0; i<(int)strlen((const char*)key); i++)          //key값 출력

        printf("0x%X ", key[i]);

    printf("\n");

    

    printf("Use iv value : ");

    for(int i=0; i<(int)strlen((const char*)iv); i++)          //iv값 출력

        printf("0x%X ", iv[i]);

    printf("\n");

    

    /*****************************************EnCrypt Start!!*******************************************/

    printf("\n");

    printf("******************************Encrypyion**********************************\n");

    printf("\n");

    

    

    unsigned char *plain_txt= (unsigned char*)"Hello hihi my name is honggildong nice to meet you  nice to meet you too!!."//Plain_Text

    

    printf("input Plane_txt length = %d\n\n", (int)strlen((char*)plain_txt));

    

    unsigned char *cipher_txt= (unsigned char*)malloc(strlen((char*)plain_txt)+EVP_CIPHER_CTX_block_size(ctx_enc));        //cipher_txt

    

    printf("input plain_txt : \n \t\t%s   ", plain_txt);

    

    printf("\n");

    

    EVP_EncryptInit_ex(ctx_enc, c ,NULL,key,iv);     //초기화 아까 한번 선언했지만 지금 선언한 이유는 key와 iv값을 알려주기 위해서이다!!!!!

    

    int outl=0, numBytesWritten=0;      //인덱스 값이 되는out_length와 numBytesWritten 변수 설정!

    int lenOfPlaintxt= (int)strlen((char*)plain_txt);

    

    int numBytesToEnc = EVP_CIPHER_CTX_block_size(ctx_enc) * 2;

    //EVO_CIPHER_CTX_block_size = 8byte 이기 때문에 *2 하면 numBytesToEnc는 16바이트

    //이번(Option2) 방식은 16바이트씩 암호화를 진행하기 때문에 요렇게 설정해준거다. 그리고 무한반복!!!

    

    

    while(1) {

        

        //(lenOfPlaintxt - outl) 길이가 16바이트보다 작아질때까지 즉, 패딩된부분이 나타날떄까지 계속 무한반복 16byte씩 암호화!!!!

        if (outl < lenOfPlaintxt) {

            if ((lenOfPlaintxt -outl) >= numBytesToEnc) {

                EVP_EncryptUpdate(ctx_enc, &cipher_txt[outl], &numBytesWritten, &plain_txt[outl], numBytesToEnc);       //16Byte씩 계속 암호화를 진행!!!!

                outl += numBytesWritten;

            }

            else {

                EVP_EncryptUpdate(ctx_enc, &cipher_txt[outl], &numBytesWritten, &plain_txt[outl], (lenOfPlaintxt -outl));   //

                outl += numBytesWritten;

                break;

            }

        }

    }

    

    EVP_EncryptFinal_ex(ctx_enc, &cipher_txt[outl], &numBytesWritten);  //패딩된 부분까지 암호화 진행

    outl += numBytesWritten;

    

    

    

    EVP_CIPHER_CTX_free(ctx_enc);   //동적할당 해줬으니 할당 풀어주자

    

    printf("Cipher Text is : \n \t\t");

    

    printf("%s",cipher_txt);

    

    printf("\n");

    

    printf("\n");

    printf("******************************Decrypyion**********************************\n");

    printf("\n");

    

    

    

    /*

     *

     *  Decryption

     *

     */

    

    //Decrypyt 부분은 EVP API특성상 인터페이스가 같으니 여기서 설명생략 ^^ ㅎ.ㅎ

    

    const EVP_CIPHER *c_dec= EVP_des_cbc();

    EVP_CIPHER_CTX *ctx_dec = EVP_CIPHER_CTX_new();

    

    EVP_DecryptInit_ex(ctx_dec, c_dec, NULL, key, iv);

    

    int lenOfCiphertxt = outl;  //cipher_txt_length

    

    unsigned char *dec_plain_txt = (unsigned char*)malloc(lenOfCiphertxt + EVP_CIPHER_CTX_block_size(ctx_dec)+1);

    int outl_dec=0, tmp_dec=0 ;

    

    printf("lenOfCiphertxt : %d \n" , lenOfCiphertxt);

    

    

    int numBytesToDec = EVP_CIPHER_CTX_block_size(ctx_dec) * 2;

    

    for (;;) {

        if (outl_dec < lenOfCiphertxt) {

            if ((lenOfCiphertxt -outl_dec) >= numBytesToDec) {

                EVP_DecryptUpdate(ctx_dec, &dec_plain_txt[outl_dec], &tmp_dec, &cipher_txt[outl_dec], numBytesToDec);

                outl_dec += numBytesToDec;

            }

            else {

                EVP_DecryptUpdate(ctx_dec, &dec_plain_txt[outl_dec], &tmp_dec, &cipher_txt[outl_dec],(lenOfCiphertxt-outl_dec));

                outl_dec += (lenOfCiphertxt - outl_dec);

                break;

            }

        }

    }

    EVP_DecryptFinal_ex(ctx_dec, &dec_plain_txt[outl_dec], &tmp_dec);

    outl_dec += tmp_dec;

    

    

    

    dec_plain_txt[outl_dec] = '\0';

    

    printf("\n");

    printf("\n");

    

    printf("Decrypted: >>%s<<\n", dec_plain_txt);

    

    EVP_CIPHER_CTX_free(ctx_dec);   //동적할당 해줬으니 할당 풀어주자

    return 0;

}





18.12.15 추가 ------------------------------------------------------------------------------------------


OP2. 방식은  16바이트씩  암/복호화를 시키고 있다. 

이렇게 할경우 Encryption은 DES 암호 특징상 16의 배수를 갖는 크기를 갖게되는데 

Decryption 경우 이를 복호화 시키는 과정이다 따라서 Decryption 과정 중 


for (;;) {

        if (outl_dec < lenOfCiphertxt) {

            if ((lenOfCiphertxt -outl_dec) >= numBytesToDec) {

                EVP_DecryptUpdate(ctx_dec, &dec_plain_txt[outl_dec], &tmp_dec, &cipher_txt[outl_dec], numBytesToDec);

                outl_dec += numBytesToDec;

            }

            else {

                EVP_DecryptUpdate(ctx_dec, &dec_plain_txt[outl_dec], &tmp_dec, &cipher_txt[outl_dec],(lenOfCiphertxt-outl_dec));

                outl_dec += (lenOfCiphertxt - outl_dec);

                break;

            }

        }

    }

   EVP_DecryptFinal_ex(ctx_dec, &dec_plain_txt[outl_dec], &tmp_dec);

    outl_dec += tmp_dec;



이 부분은 Update와 Final부분인데 여기서 또한 16의 배수만큼 EVP_DecryptUpdate  를 호출 함으로써 복호화를 시키고 있는 경우이니 굳이 EVP_DecryptFinal_ex  을 안해 줘도 된다. 하지만 EVP 인터페이스 특성상 Final을 안해주면 

'초기화 -> 업데이트 -> 종료 부분' 에서 종료 부분이 빠지게되니 써주는 거라 생각하면 된다. ❛˓◞˂̵✧