EVP_PKEY * を経由しない RSA * 読み込み方法

rsaCodec.cpp ではPEMファイルからRSA *を取り出すために,EVP_PKEY *で取り出した後,変換していた.

	// 次2行 rsaCodec での処理
	EVP_PKEY *epubKey = PEM_read_PUBKEY( fp, NULL, NULL, NULL );
	RSA *rpubKey = EVP_PKEY_get1_RSA( epubKey );
	// 次2行 rsaCodec での処理
	EVP_PKEY *epKey = PEM_read_PrivateKey( fp, NULL, NULL, NULL );
	RSA *rpKey = EVP_PKEY_get1_RSA( epKey );

これは,RSA *を返す関数が,なぜだか働かないという問題があったからだ.この問題を解決する方法が見つかったから,ここに書き留める.

openssl/ssl.h の SSL_library_init() を事前に実行しておく

これから使おうとする巻数の接頭辞が PEM_ なのにと不思議に思うが,SSL_library_init() を実行する.

次,RSA * を返す関数が3つある.

  • PEM_read_RSAPublicKey()
  • PEM_read_RSA_PUBKEY()
  • PEM_read_RSAPrivateKey()

RSAPublicKey() がうまくいかない.2007-10-15 によれば PEM ファイルの構文に依存するとある.しかし手持ちの PEM ファイルに RSA との文字列を追加してもうまくいかなかった.PEM_read_RSA_PUBKEY() と PEM_read_RSAPrivateKey() は良い.

特に書くタイミングがなかったリンク.http://ml.tietew.jp/cppll/cppll_novice/thread_articles/446

rsaCodec2.cpp

sha256c は最近のエントリに書き出している.そちらを参照されたい.

//  http://www.wizard-limit.net/mt/pc/archives/001184.html
//  PEM_read_PrivateKeyは、SSL_library_init(); を事前に呼んでおかないと動作しないようでした。
// という情報から,この関数を事前に実行しておくとどうなるか,実験
// sha256c は rsaCodec プロジェクトのファイルにリンクしている

// RSA * を返す関数は3つ.
// -PEM_read_RSAPublicKey
// -PEM_read_RSA_PUBKEY
// -PEM_read_RSAPrivateKey
// PEM_read_RSAPublicKey は NULL を返し,下2つは RSA * を返してくれた.

#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include "../rsaCodec/sha256c.h"
#include <stdlib.h>
// openssl/applink.c 内の fopen() への warning C4996 の抑制
#ifdef _WIN32
#ifdef WIN32
#define WIN32_PREDEFINED
#else
#define WIN32
#endif
#pragma warning( disable: 4996 )
#endif
#include <openssl/applink.c>
#ifdef WIN32
#ifdef WIN32_PREDEFINED
#undef WIN32_PREDEFINED
#else
#undef WIN32
#endif
#pragma warning( default: 4996 )
#endif
// warning C4996 の抑制はここまで

const int RSABITNUM = 2048;
const int RSABYTENUM = RSABITNUM/8;
const char *pKeyFilename = "C:\\data\\PEM\\Private\\ossl100a_pKey.pem";
const char *pubKeyFilename = "C:\\data\\PEM\\Public\\ossl100a_pubKey.pem";

void showHash( unsigned char *hash, size_t sz )
{
	for ( size_t i = 0; i < sz; i++ )
	{
		printf("%02x", hash[i] );
	}
	printf("\n");
}


// 公開鍵で暗号化し,秘密鍵で復号化する
int main ( int argc, char *argv[] )
{
	SSL_library_init();

	sha256c s;
	char *textvector = "The quick brown fox jumps over the lazy dog";
	s.update( (unsigned char *)textvector, strlen(textvector) );
	s.showHash();

	// プレーンテキスト.暗号化対象
	unsigned char *planetext = s.getHash();

	// 公開鍵ファイルを読み込む
	FILE *fp;
	fopen_s( &fp, pubKeyFilename, "r");
	//RSA *rpubKey = PEM_read_RSAPublicKey( fp, NULL, NULL, NULL );
	RSA *rpubKey = PEM_read_RSA_PUBKEY( fp, NULL, NULL, NULL );
	// 次2行 rsaCodec での処理
	//EVP_PKEY *epubKey = PEM_read_PUBKEY( fp, NULL, NULL, NULL );
	//RSA *rpubKey = EVP_PKEY_get1_RSA( epubKey );
	RSA_print_fp( stdout, rpubKey, 0 );

	// 秘密鍵ファイルを読み込む
	fopen_s( &fp, pKeyFilename, "r" );
	RSA *rpKey = PEM_read_RSAPrivateKey( fp, NULL, NULL, NULL );
	// 次2行 rsaCodec での処理
	//EVP_PKEY *epKey = PEM_read_PrivateKey( fp, NULL, NULL, NULL );
	//RSA *rpKey = EVP_PKEY_get1_RSA( epKey );
	RSA_print_fp( stdout, rpKey, 0 );

	// 暗号化後のデータ
	unsigned char enctext[RSABYTENUM];

	// 暗号化
	int enclen = RSA_public_encrypt(
		SHA256_DIGEST_LENGTH, 
		planetext,
		enctext,
		rpubKey,
		RSA_PKCS1_OAEP_PADDING
		);

	// 暗号化成立時
	if ( enclen != -1 )
	{
		// 暗号データ表示
		showHash( enctext, enclen);
		// 復号化
		enclen = RSA_private_decrypt( 
			RSABYTENUM,
			enctext,
			planetext,
			rpKey,
			RSA_PKCS1_OAEP_PADDING
			);
		if ( enclen != -1 )
		{
			// 復号データ表示
			showHash( planetext, enclen );
		}
	}

	return 0;
}