mbed TLSでRSAを利用する「RSAの公開鍵と秘密鍵の作成」

# 記事の概要
mbet TLSを用いてRSAを利用します。
今回はRSAの公開鍵と秘密鍵の作成を行います。

サンプルプログラムは以下に置いてあります。
https://github.com/matsuikosuke/mbedTLSTest

# サンプルコード

```c
static int entropy_dummy_source( void *data, unsigned char *output,
                                 size_t len, size_t *olen )
{
    ((void) data);

    memset( output, 0x2a, len );
    *olen = len;

    return( 0 );
}

int mbedtls_rsa_key_generation_test(void)
{
  
    int ret = 1;

    size_t olen = msg_len;
    mbedtls_pk_context p_pk;
    mbedtls_rsa_context *p_rsa;
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    const char* pers = "rsa_genkey";

    mbedtls_entropy_init(&entropy);    
    mbedtls_ctr_drbg_init(&ctr_drbg); 
    mbedtls_entropy_add_source( &entropy, entropy_dummy_source, NULL,
                                           32, MBEDTLS_ENTROPY_SOURCE_STRONG );

    ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
                    (const unsigned char*)pers,
                    strlen(pers));
    if (ret != 0)
        return ret;

    mbedtls_rsa_init( p_rsa, MBEDTLS_RSA_PKCS_V15, 0 );
    mbedtls_pk_init(&p_pk);
    ret = mbedtls_pk_setup( &p_pk, mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) );    
    if (ret != 0)
        return ret;
            
    p_rsa = mbedtls_pk_rsa( p_pk );
    ret = mbedtls_rsa_gen_key(p_rsa, mbedtls_ctr_drbg_random, &ctr_drbg, 2048, 0x010001);
    if (ret != 0)
        return ret;

    uint8_t private_key_pem[8000];
    uint8_t publick_key_pem[8000];

    ret = mbedtls_pk_write_key_pem(&p_pk, private_key_pem, sizeof(private_key_pem));
    if (ret != 0)
        return ret;

    ret = mbedtls_pk_write_pubkey_pem(&p_pk, publick_key_pem, sizeof(publick_key_pem));
    if (ret != 0)
        return ret;

    return ret;
}
```

## 乱数の作成
乱数を作成します。

```c
    mbedtls_entropy_init(&entropy);    
    mbedtls_ctr_drbg_init(&ctr_drbg); 
    mbedtls_entropy_add_source( &entropy, entropy_dummy_source, NULL,
                                           32, MBEDTLS_ENTROPY_SOURCE_STRONG );

    ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
                    (const unsigned char*)pers,
                    strlen(pers));
    if (ret != 0)
        return ret;
```

## 公開鍵と秘密鍵の作成


```c
    mbedtls_rsa_init( p_rsa, MBEDTLS_RSA_PKCS_V15, 0 );
    mbedtls_pk_init(&p_pk);
    ret = mbedtls_pk_setup( &p_pk, mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) );    
    if (ret != 0)
        return ret;
            
    p_rsa = mbedtls_pk_rsa( p_pk );
    ret = mbedtls_rsa_gen_key(p_rsa, mbedtls_ctr_drbg_random, &ctr_drbg, 2048, 0x010001);
    if (ret != 0)
        return ret;
```

`mbedtls_rsa_gen_key()`の第4引数で生成するbit数を指定します。2048bit(256byte)の場合、かなり長い時間を要します。
第5引数は公開指数です。

## PEM形式への変換
作成した公開鍵と秘密鍵は、そのままでは外部に渡せるデータ形式になっていないので、PEM形式に変換します。

```c
    uint8_t private_key_pem[8000];
    uint8_t publick_key_pem[8000];

    ret = mbedtls_pk_write_key_pem(&p_pk, private_key_pem, sizeof(private_key_pem));
    if (ret != 0)
        return ret;

    ret = mbedtls_pk_write_pubkey_pem(&p_pk, publick_key_pem, sizeof(publick_key_pem));
    if (ret != 0)
        return ret;
```

DER形式に変換する関数もあります。
詳細は以下をご参照ください
https://tls.mbed.org/api/pk_8h.html#af5b7c3953ad6fe8be09d35508ee569f6

## 暗号化と復号
余談ですが、サンプルコードで作成したcontext`p_rsa`を暗号化と復号の関数に代入すれば、暗号化と復号を実行できます

```c
    ret = mbedtls_rsa_rsaes_pkcs1_v15_encrypt(p_rsa, 
                        mbedtls_ctr_drbg_random, &ctr_drbg,
                        MBEDTLS_RSA_PUBLIC,
                        32, &g_plaintext[0], &rsa_encrypted_buf[0]);
    if (ret != 0)
        return ret;


    ret = mbedtls_rsa_rsaes_pkcs1_v15_decrypt(p_rsa, 
                        mbedtls_ctr_drbg_random, &ctr_drbg,
                        MBEDTLS_RSA_PRIVATE,
                        &olen, rsa_encrypted_buf, rsa_decrypted_buf, 32);
    if (ret != 0)
        return ret;
```

# 参照
[mbed TLSでAES-GCMを利用する](https://qiita.com/Kosuke_Matsui/items/340c6b906fed2c6ea40b)
[mbed TLSでRSAを利用する「RSA-OAEPの暗号化と復号」](https://qiita.com/Kosuke_Matsui/items/4c64c993e5979a65620d)
[mbed TLSでRSAを利用する「RSAの公開鍵と秘密鍵の作成」](https://qiita.com/Kosuke_Matsui/items/786e88eace7646c8a7e6)
[mbed TLSおよびOberonでECDHを利用する](https://qiita.com/Kosuke_Matsui/items/4390f5e58339e95dcdae)
[mbed TLSでHKDFを利用する](https://qiita.com/Kosuke_Matsui/items/93f25f47a6171fe94d30)
[mbed TLSでJWTを利用する](https://qiita.com/Kosuke_Matsui/private/915e6607b2b81de7f55d)