1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

openssl を使ったRSA暗号化のサンプル

Last updated at Posted at 2021-02-16

継続的にやらせていただいている仕事で、RSA暗号化を使用するケースがあったんだけど、対向システムの仕様変更でRAS暗号化が不要になったので、gitのリポジトリからは削除して、ここに退避した。
パディングで、ちょいとハマった記憶があったので、コメント参照。
openssl のバージョンは 1.1.1b です。

# include <openssl/rsa.h>
# include <openssl/engine.h>
# include <boost/algorithm/hex.hpp>

void rsaEncryption(
  const std::string modulus,
  const std::string exponent,
  std::istream& srcs, /* 入力ストリーム */  
  std::ostream& dsts  /* 出力ストリーム */
  )
{
  RSA* rsa = ::RSA_new();
  ::BN_hex2bn(&rsa->n, modulus.c_str());
  ::BN_hex2bn(&rsa->e, exponent.c_str());
  const auto blockSize = ::RSA_size(rsa);
  /*
    RSA_PKCS1_PADDINGの場合、ソースの最大バイト数は RSA_size() -11 にしなければならない。
    https://www.openssl.org/docs/man1.0.2/crypto/RSA_public_encrypt.html
    */
  std::vector<uint8_t> raw(blockSize - 11);
  std::vector<uint8_t> enc(blockSize);
  
  while(!srcs.eof()){
    srcs.read(reinterpret_cast<char*>(raw.data()), raw.size());
    const auto readBytes = srcs.gcount();
    
    const auto writtenBytes = ::RSA_public_encrypt(
      static_cast<int>(readBytes),
      raw.data(),
      enc.data(),
      rsa,
      RSA_PKCS1_PADDING);
    if(writtenBytes == -1){
      ::RSA_free(rsa);
      /*
        例外が嫌なら、rsaEncryption() にエラー値入れるなりなんなりと。
        throw_error_internal はウチで作ったエラーライブラリに含まれているので、
        他で使うなら std::exception を派生したオブジェクトかなんかを投げてくだされ。
      */
      throw_error_internal(::ERR_error_string(::ERR_get_error(), nullptr));
    }
    /*
      バイナリ->hex文字列変換
      不要なら、encをそのままdstsに放り込めばOK
    */
    boost::algorithm::hex
    (
      enc.begin(),
      enc.begin() + writtenBytes,
      std::ostream_iterator<char>(dsts));
  }
  ::RSA_free(rsa);
}

openssl 1.1.1l

最近、 openssl を更新する機会があって、若干コードを変更する必要が出てきたのでメモ。

RSA 構造体へはアクセス関数を使用することになった

旧コード
  RSA* rsa = ::RSA_new();
  ::BN_hex2bn(&rsa->n, modulus.c_str());
  ::BN_hex2bn(&rsa->e, exponent.c_str());
新コード
  BIGNUM* bn_n = ::BN_new();
  BIGNUM* bn_e = ::BN_new();
  ::BN_hex2bn(&bn_n, modulus.c_str());
  ::BN_hex2bn(&bn_e, exponent.c_str());
  ::RSA_set0_key(rsa, bn_n, bn_e, nullptr);

ERR_XXX はヘッダが分割された

追加ヘッダ
# include <openssl/err.h>

そんな事より

何年前のソースなのか知らんが、生ポを使っているので面倒がらずに std::unique_ptrcustom deleter 使いましょうね。

こんな感じかな?
struct rsa_deleter {
  void operator() (RSA* p) { ::RSA_free(p); }
};
auto rsa = std::unique_ptr<RSA, rsa_deleter>(::RSA_new());
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?