メインコンテンツ

RSA アルゴリズムのパディングが見つかりません

暗号化または署名操作で使用されるコンテキストがパディングと関連付けられていない

説明

この欠陥は、パディング スキームに関連付けられていないコンテキスト オブジェクトを使用して RSA 暗号化または署名を実行した場合に発生します。

たとえば、特定のパディングに最初から関連付けていないコンテキスト オブジェクトを使用して、暗号化を実行します。

ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING);
...
ret = EVP_PKEY_encrypt(ctx, out, &out_len, in, in_len)

リスク

パディング スキームは RSA アルゴリズムから確定性を排除し、特定の種類の攻撃から RSA 演算を保護します。パディングにより、特定のメッセージが暗号化されるたびに同じ暗号文にならないようにします。パディングを使用しないと、攻撃者が暗号システムに対して選択平文攻撃を仕掛けることができます。

修正方法

RSA 演算を実行する前に、この演算と互換性のあるパディング スキームにコンテキスト オブジェクトを関連付けます。

  • 暗号化: OAEP パディング スキームを使用します。

    たとえば、引数 RSA_PKCS1_OAEP_PADDING を指定して関数 EVP_PKEY_CTX_set_rsa_padding を使用するか、関数 RSA_padding_add_PKCS1_OAEP を使用します。

    ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING);
    
    PKCS#1v1.5 または SSLv23 スキームを使用することもできます。これらのスキームは安全ではないと見なされていることに注意してください。

    次に、コンテキストに対して、EVP_PKEY_encrypt/EVP_PKEY_decryptRSA_public_encrypt/RSA_private_decrypt などの関数を使用することができます。

  • 署名: RSA-PSS パディング スキームを使用します。

    たとえば、引数 RSA_PKCS1_PSS_PADDING を指定して関数 EVP_PKEY_CTX_set_rsa_padding を使用します。

    ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING);
    ANSI X9.31、PKCS#1v1.5、または SSLv23 スキームを使用することもできます。これらのスキームは安全ではないと見なされていることに注意してください。

    次に、コンテキストに対して、EVP_PKEY_sign-EVP_PKEY_verify ペアや RSA_private_encrypt-RSA_public_decrypt ペアなどの関数を使用できます。

同じコンテキストを使用して 2 種類の操作を実行する場合、最初の操作後、2 番目の操作の前にコンテキストのパディング スキームをリセットします。

すべて展開する

#include <stddef.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>

#define fatal_error() exit(-1)

int ret;
unsigned char *out_buf;
size_t out_len;


int func(unsigned char *src, size_t len){
  EVP_PKEY_CTX *ctx;
  EVP_PKEY* pkey;

  /* Key generation */
  ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA,NULL); 
  if (ctx == NULL) fatal_error();

  ret = EVP_PKEY_keygen_init(ctx);
  if (ret <= 0) fatal_error();
  ret = EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048);
  if (ret <= 0) fatal_error();
  ret = EVP_PKEY_keygen(ctx, &pkey);  
  if (ret <= 0) fatal_error();

  /* Encryption */
  EVP_PKEY_CTX_free(ctx);
  ctx = EVP_PKEY_CTX_new(pkey,NULL); 
  if (ctx == NULL) fatal_error();

  ret = EVP_PKEY_encrypt_init(ctx);
  if (ret <= 0) fatal_error();
  return EVP_PKEY_encrypt(ctx, out_buf, &out_len, src, len); 
}

この例では、EVP_PKEY_encrypt による暗号化の前に、特定のパディングがコンテキスト オブジェクト ctx に関連付けられていません。

修正 — 暗号化の前にコンテキストにパディングを設定

1 つの修正方法として、OAEP パディング スキームをコンテキストに設定します。

#include <stddef.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>

#define fatal_error() exit(-1)

int ret;
unsigned char *out_buf;
size_t out_len;


int func(unsigned char *src, size_t len){
  EVP_PKEY_CTX *ctx;
  EVP_PKEY* pkey;

  /* Key generation */
  ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA,NULL); 
  if (ctx == NULL) fatal_error();

  ret = EVP_PKEY_keygen_init(ctx);
  if (ret <= 0) fatal_error();
  ret = EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048);
  if (ret <= 0) fatal_error();
  ret = EVP_PKEY_keygen(ctx, &pkey);  
  if (ret <= 0) fatal_error();

  /* Encryption */
  EVP_PKEY_CTX_free(ctx);
  ctx = EVP_PKEY_CTX_new(pkey,NULL); 
  if (ctx == NULL) fatal_error();

  ret = EVP_PKEY_encrypt_init(ctx);
  ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING); 
  if (ret <= 0) fatal_error();
  if (ret <= 0) fatal_error();
  return EVP_PKEY_encrypt(ctx, out_buf, &out_len, src, len); 
}

結果情報

グループ: 暗号化
言語: C | C++
既定値: オフ
コマンド ライン構文: CRYPTO_RSA_NO_PADDING
影響度: Medium

バージョン履歴

R2018a で導入