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

(미완) [OpenSSL/ECDH] ECDH Cryptography Part1. (Serialization /Deserialization) 본문

Security/Cryptography

(미완) [OpenSSL/ECDH] ECDH Cryptography Part1. (Serialization /Deserialization)

us0 2018. 11. 29. 11:15


[OpenSSL/ECDH] ECDH Cryptography Part1.

 (Serialization /Deserialization)





이번 포스팅은 ECDH 에 대해서 알아보자!! (코드 한번에 나와있는곳은 맨 마지막 부분!!)


ECDH알고리즘이란??

타원 곡성 암호 blahblah... (추가시키기)


EVP API를 이용하기위해 <openssl/evp.h>

Random한 값을 얻기위해 <openssl/rand.h>

ECDH 를 이용할거니까 <openssl/ec.h>

이라는 각각의 헤더 파일을 선언 해준다!!!

#include<openssl/evp.h>

#include<openssl/ec.h>

#include<openssl/rand.h>





원활한 코드 설명을 위해 main공간에 모든코드 넣어보겠다 ❛˓◞˂̵✧  


int main(void){




먼저 ECDH를 계산을 하기위해 EC domain 을 생성(Generate ) 해보자!!


EC_Domain param Generate

언제나 그랬듯이 암/복호화와 관련된 값들을 저장해주는 EVP API 컨텍스트를 생성해준다!!
매개변수로 EVP_PKEY_EC 값이 들어왔는데 이는 뭐 이름 그대로 EVP_PKEY구조체에 EC와 관련된 정보들을 EVP_PKEY_CTX 에 할당 해준다 라는 뜻이 되겠다.
여기서 잠깐 TMI!!
<<EVP_PKEY_CTX 구조체는 EVP PublicKey Context의 줄임말!! 따라서 Public키를 보관하는 공간 정도라고 생각하면 된당>>

// Generate EC domain param(EC domainarameter 생성!!

    /* Create the context for parameter generation */

    EVP_PKEY_CTX *pctx = NULL;

    pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);  //컨텍스트에 EC를 이용한다 말해준다.

    //EVP_PKEY_CTX_new_id(<#int id#>, <#ENGINE *e#>)

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


EVP_PKEY_CTX_new_id의 정의를 보면    //EVP_PKEY_CTX_new_id(<int id>, <ENGINE *e>)      이렇게 매개변수가 2개이다
첫번째 매개변수는 Int id인데 아래 코드에선 미리 #Defined으로 선언된 EVP_PKEY_EC(408) 라는  id(숫자임!!)를 적어주면 된다 ㅇㅂㅇ!!
(EC<타원곡선>을  이용하기 때문에  이 정보를 컨텍스트에 넘겨줌!!)
 ENGINE은 하드웨어와 연관이 있다고 하니 일단 2번째 매개변수는 패수!!


<<output>>

EVP_PKEY_EC : 408



그리고 항상 컨텍스트 등 할당하는 코드가 있으면 해당 메모리가 잘 만들어졌는지 아래처럼 If문을 작성해주자!! 

그리고 키 생성 및 특정한 값을 할당 해주는 함수를 호출할때에도 if 문을 빼먹지 말자!!

<<이것은 당연하기 때문에 설명할 땐 잠시 생략하겠다. ❛˓◞˂̵✧ >>


Ex)

if(pctx == NULL){

        printf("EVP_PKEY_CTX_new_id error\n");

        return -1;

        

    }




--------------------------------------------다시 시작 ❛˓◞˂̵✧ ---------------------------------------------

타원곡선의 공식은 

y^2 = x^3 + ax + b (mod p) 이다!!

따라서 a, b,  p 값을 정해줘야 하는데 아래 코드가 이 a, b, p 를할당해주는 코드이다!!

 EVP_PKEY_paramgen_init(pctx);


ECDH는 위의 식을 이용하여 y값을 도출하면 y^2을 구했으니 y값은 2개가 나올것이다!! 이를 각각 P1, P2라고 해준다.

(why?? 예를 들어 4를 예로 들면 (+2)^2= 4  와 (-2)^2 = 4 가 나오듯!!) 

P3은   P3 = P1 + P2 인데 더하는 방법이 여러가지 이다 따라서 아래코드를 작성!!

 

EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1);

여기서 부터는 어떠한 곡선 그래프(방정식)를 이용할 것인지 방정식을 2번째 매개변수로 알려준다 .

여기서는  NID_X9_62_prime256v1   를 이용하고 있다.



지금까지 Param을 생성 해줬으니 이 소식을 알고있는 pctx 변수를 불러서  Key를 보관하는 EVP_PKEY 변수를 생성해줘서 보관해준다.

EVP_PKEY *params = NULL;

EVP_PKEY_paramgen(pctx, &params)



이렇게 하면 

y^2 = x^3 + ax + b (mod p) 에서 y, x, b, p 값이 모두 어떤 값인지 알게 된다!! 

그리고 P1, P2, P3 도 알게된다  이 모든 정보들은 pctx 변수에있고,

키에 관련된 정보들만 따로 EVP_PKEY *param 변수에 저장 된다.



여기서 잠깐!!!! =============================================


EVP_PKEY란?? 


EVP_PKEY 객체는 관련 알고리즘 및 매개 변수와 함께 공개 키 및 개인 키 (선택 사항)를 저장하는 데 사용됩니다. 그들은 또한 대칭 MAC 키를 저장할 수 있습니다.

다음과 같은 EVP_PKEY 유형이 지원됩니다.

  • EVP_PKEY_EC : 타원 곡선 키 (ECDSA 및 ECDH 용) - 서명 / 검증 작업 및 키 유도 지원
  • EVP_PKEY_RSA : RSA - 서명 / 확인 및 암호화 / 해독을 지원합니다.
  • EVP_PKEY_DH : Diffie Hellman - 키 유도 용
  • EVP_PKEY_DSA : 서명 / 확인을위한 DSA 키
  • EVP_PKEY_HMAC : 메시지 인증 코드를 생성하기위한 HMAC 키
  • EVP_PKEY_CMAC : 메시지 인증 코드를 생성하기위한 CMAC 키


출처 : OpensslWiki ( https://wiki.openssl.org/index.php/EVP )

=========================================================


Alice & Bob KeyPair(Public key, Private key) Generate


앨리스와 밥의 public key와 private Key 쌍인 KeyPair를 생성하는 시간이다 화팅 ❛˓◞˂̵✧ 


Alice KeyPair


먼저 키에관한 정보를 담을 수 있는 컨텍스트(EVP_PKEY_CTX 구조체) 를 생성 해준다. 

그리고 여기에 param << 아까 구했던 ECDH 키들 을 이용해 새로운 PKEY컨텍스트 생성!!

그럼 kctx는 param 정보를 담고 있는 컨텍스트가 된다!!


 EVP_PKEY_CTX *kctx = EVP_PKEY_CTX_new(params, NULL);

    if( kctx == NULL){

        printf("EVP_PKEY_CTX_new error\n");

        return -1;

    }



그럼 Param정보를 담고 있는 Kctx를    EVP_PKEY_keygen_init  이 함수를 통해 키 담을 공간을 초기화 시켜준다.


  /* Generate my EC key pair using kctx */

    if( EVP_PKEY_keygen_init(kctx) !=1 ){

        printf("EVP_PKEY_keygen_init error!!\n");

        return -1;

    }

    


그리고 kctx 컨텍스트에 저장된 정보를 EVP_PKEY_keygen(kctx, &alice_keypair)   함수를 통해 alice의 Keypair에 저장해준다.


    EVP_PKEY *alice_keypair = NULL;

    if(EVP_PKEY_keygen(kctx, &alice_keypair) != 1){

        printf("EVP_PKEY_keygen error!!\n");

        return -1;

    }

    


그럼 Alice의 Public Key와 Private Key 는 Alice_keyPair에 저장되었다!! 짞짞짞 
이거랑 똑같이 밥도 해주면 된닷


BOB_KeyPair

 /*********************************BOB*********************************/

    /*

     *  Generate Bob's private and public key pair

     */

    

    /* Create the context for key generation */

    kctx = EVP_PKEY_CTX_new(params, NULL);

    if( kctx == NULL){

        printf("EVP_PKEY_CTX_new error\n");

        return -1;

    }

    

    /* Generate my EC key pair using kctx */

    if( EVP_PKEY_keygen_init(kctx) !=1 ){

        printf("EVP_PKEY_keygen_init error!!\n");

        return -1;

    }

    EVP_PKEY *bob_keypair = NULL;

    if(EVP_PKEY_keygen(kctx, &bob_keypair) != 1){

        printf("EVP_PKEY_keygen error!!\n");

        return -1;

    }




그럼 각각의 KeyPair가 이루어 졌으니 Public Key와 Private Key를 갈라볼까?!?!?!?!!!!


Serialization


자 공개 키를 나누기 위해 EC(타원 곡선)는 어떤 과정을 거쳐야할까??


구조체,자료형 이름 (상태)  <변수명>


EVP_PKEY (key pair)  <peerkey>

|

|

EC_KEY (key pair) <peer_eckey>

|

|

EC_POINT (public key) <peer_pub_ecpoint>

|

|

char * (string) <peerPubkeyChar>




Alice_ECDH_Secret_Key생성을 위해 먼저 Bob의 Public Key를 도출해보자!!


여기서 잠깐!!!!!

Q.  Alice_ECDH_Secret_Key는 어떻게 만들어지나용??

A. <<Alice_ECDH_Secret_Key = Bob's_public_key * Alice_Private_key * P >>


bob_keypair는 위에서 만들어 줬으니 EC_KEY부터 생성해보자!!

 EC_KEY *bob_eckey = EVP_PKEY_get1_EC_KEY(bob_keypair);

이것은 EVP_PKEY_CTX인 bob_keypair에서 EC_KEY와 연관된 애들을 추출하는 과정!!


그리고 타원곡선에서의 Point(아까 말했던 P3!!) 를 알아내기 위해 EC_POINT를 추출해보자!! 

const EC_POINT *bob_pubkey_ecpoint = EC_KEY_get0_public_key(bob_eckey);



그리고  밥의 public_key 공간을 할당해주기위해 버퍼길이를 생성해주고 이를 사용해 메모리를 동적할당해준다!!

size_t bufLen = EC_POINT_point2oct(EC_KEY_get0_group(bob_eckey), bob_pubkey_ecpoint, POINT_CONVERSION_COMPRESSEDNULL0NULL);

unsigned char *bob_pub_char = (unsigned char *)malloc(bufLen);



그리고 이함수를 한번 더 호출해줘서 bob_pub_char에 저장 해준다.

EC_POINT_point2oct(EC_KEY_get0_group(bob_eckey), bob_pubkey_ecpoint, POINT_CONVERSION_COMPRESSED,bob_pub_char, bufLen, NULL);





Deserialization