본문 바로가기

개발자료/Openssl

RSAES-OAEP encrypt / decrypt

RSAES-OAEP-ENCRYPT ((n, e), M, L)

RSAES-OAEP-DECRYPT

  defined by PKCS #1 v2.1: RSA Cryptography Standard


다음 함수들을 사용하면 위 작업 가능

  • https://www.openssl.org/docs/man1.0.2/crypto/RSA_private_decrypt.html
    • RSA_public_encrypt ()
    • RSA_private_decrypt ()
  • https://github.com/openssl/openssl/blob/master/crypto/rsa/rsa_oaep.c 
    • RSA_padding_add_PKCS1_OAEP_mgf1 ()
    • RSA_padding_check_PKCS1_OAEP_mgf1 ()

Encrypt 과정은 아래와 같이 풀어 쓸 수 있음

Input M 필요

{

  /*

   * RSAES-OAEP-ENCRYPT ((n, e), M, L)

   * Options:

   *   Hash   hash function 

   *          (hLen denotes the length in octets of the hash function output)

   *   MGF  mask generation function

   * Input:

   *   (n, e)  recipient’s RSA public key 

   *           (k denotes the length in octets of the RSA modulus n)

   *   M    message to be encrypted, an octet string of length mLen.

   *        where mLen > k – 2hLen – 2

   *   L    optional label to be associated with the message;

   *        the default value for L, if L is not provided, is the empty string

   * Output:

   *    C    ciphertext, an octet string of length k

   * Assumption: RSA public key (n, e) is valid

   */

  gint i;

  gboolean ret = FALSE;


  /* for EME-OAEP encoding */

  const EVP_MD *md = EVP_sha256 ();

  const EVP_MD *mgf1md = EVP_sha256 ();

  gint k = LEN_PUB_MOD_N;

  gint hlen = EVP_MD_size (md);

  gint mlen = LEN_M;

  guint8 em[k];

  guint8 *seed, *db;

  guint8 *dbmask = NULL, seedmask[EVP_MAX_MD_SIZE];


  // 1. Length checking

  if (mlen > k - 2 * hlen - 2) {

    g_error ("invalid param. message too long");

    goto exit;

  }


  // 2. EME-OAEP encoding

  {

    em[0] = 0;

    seed = em + 1;

    db = em + hlen + 1;


    // a. If the label L is not provided, let L be the empty string.

    //  Let lHash = Hash (L), an octet string of length hLen.

    SHA256 (NULL, 0, db); //get lHash value for empty string


    // b. Generate an octet string PS consisting of k – mLen – 2hLen – 2 zero octets.

    //    The length of PS may be zero.

    memset (db + hlen, 0x00, k - mlen - 2 * hlen - 2);


    // c. make DB = lHash || PS || 0x01 || M

    db[k - mlen - hlen - 2] = 0x01;

    memcpy (db + k - mlen - hlen - 1, M, mlen);  //set M


    // d. Generate a random octet string seed of length hLen.

    generate_random_number (seed, hlen);

    

    // e. Let dbMask = MGF (seed, k - hLen - 1)

    dbmask = g_malloc (k - hlen - 1);


    if (PKCS1_MGF1 (dbmask, k - hlen - 1, seed, hlen, mgf1md) < 0) {

      g_error ("fail 2.e step: %s", ERR_error_string (ERR_peek_last_error (), NULL));

      goto exit;

    }


    // f. Let maskedDB = DB XOR dbMask.

    for (i = 0; i < k - hlen - 1; i++)

      db[i] ^= dbmask[i];


    // g. Let seedMask = MGF (maskedDB, hLen).

    if (PKCS1_MGF1 (seedmask, hlen, db, k - hlen - 1, mgf1md) < 0) {

      g_error ("fail 2.g step: %s", ERR_error_string (ERR_peek_last_error (), NULL));

      goto exit;

    }


    // h. Let maskedSeed = seed XOR seedMask.

    for (i = 0; i < hlen; i++)

      seed[i] ^= seedmask[i];

  }


  // 3. RSA encryption

  {

    RSA *rsa;


    rsa = RSA_new ();

    rsa->n = BN_bin2bn (public_key_mon, LEN_PUB_MOD, NULL);

    rsa->e = BN_bin2bn (public_key_exp, LEN_PUB_EXP, NULL);


    // b. c = RSAEP ((n, e), m)

    if (RSA_public_encrypt (k, em, out_encrypted, rsa, RSA_NO_PADDING) == -1) {

      g_error ("fail 3. step: %s", ERR_error_string (ERR_peek_last_error (), NULL));

    }

    else

      ret = TRUE;


    RSA_free (rsa);

  }

  

exit:

  g_free (dbmask);

  return ret;

}


'개발자료 > Openssl' 카테고리의 다른 글

RSASSA PKCS1 v1.5  (0) 2018.01.24
HMAC-SHA256  (0) 2018.01.24
SHA256  (0) 2018.01.24
AES-CTR  (0) 2018.01.24