OpenSSL の証明書関連

readCert.cpp

環境は VC++ 2008 EE + Windows SDK + OpenSSL 0.9.8k.3つのファイルを読み込んでいる.

証明書検証においては,秘密鍵SHA-1 ハッシュを計算して,証明書に記載されている内容と一致するかみたらいいのだろうか.そういう関数 OpenSSL 自体にないかな.RSA_verify_PKCS1_PSS() を見つけた.これを使えばいいんだろうが,PSS自己署名証明書を OpenSSL コマンドラインで作れそうにない.pkeyutl(1) にあるけれど,これの Superseded とされている rsautl には PSS の情報がない.0.9.7h からの実装らしいし,0.9.8k は問題ないはずなのに.

  *) Minimal support for X9.31 signatures and PSS padding modes. This is
     mainly for FIPS compliance and not fully integrated at this stage.
     [Steve Henson]
Changes between 0.9.7g and 0.9.7h

自分で RSA 鍵を作って,RSA_padding_add_PKCS1_PSS() する必要があるのか.今回はパディング方法にこだわる必要があるかどうか分からないから「何も指定しない」ことにする.そうすると PKCS#1 v1.5 が採用されるんだろうな.

/** @brief Windows SDK の定義読み込みを回避する */
#define __WINCRYPT_H__

#include <stdio.h>
#include <errno.h>
/** @brief PEM ファイル読み込み関数有効化のため.詳細は不明. */
#undef SSLEAY_MACROS
#include <openssl/pem.h>
#include <openssl/x509v3.h>
#include <openssl/rsa.h>

// 参考文献は次のページがリンクしている
//   http://d.hatena.ne.jp/Guernsey/20091026/1256519352

/** 読み込むファイル
 * 証明書,秘密鍵,公開鍵,その他
 */
const char *FILES[] = {
	"C:/data/PEM/Signature/cert.pem",
	"C:/data/PEM/Signature/privatekey.pem",
	"C:/data/PEM/Signature/publickey.pem",
	NULL,
};

/** 証明書ファイルを読み込んでいろいろする
 */
int main(int argc, char **argv)
{
	/** 汎用ファイルポインタ */
	FILE *fp;
	/** ファイルオープン監視 */
	errno_t file_err;
	/** 証明書データ */
	X509 *x509;
	/** 秘密鍵 */
	RSA *prikey;
	/** 公開鍵 */
	EVP_PKEY *pubkey_pkey;
	RSA *pubkey;

	// =============================================================
	//   証明書
	// -------------------------------------------------------------
	puts("証明書");
	// 証明書ファイルを読み込む
	file_err = fopen_s( &fp, FILES[0], "r");
	if ( file_err == EINVAL )
	{
		perror("file");
		fclose( fp );
		return 0;
	}
	// -------------------------------------------------------------
	// 証明書を読み込む
	x509 = X509_new();
	//x509 = d2i_X509_fp( fp, NULL);
	x509 = PEM_read_X509( fp, NULL, NULL, NULL);
	fclose(fp);
	if ( x509 == NULL )
	{
		puts("証明書読み込みエラー");
		goto VARRELEASE;
	}
	// -------------------------------------------------------------
	// 証明書情報を画面表示
	// 等価なコマンドは
	//   x509 -in cert.pem -text -noout 
	X509_print_fp(stdout, x509);

	// =============================================================
	//   秘密鍵
	// -------------------------------------------------------------
	puts("秘密鍵");
	// 秘密鍵ファイルを読み込む
	file_err = fopen_s ( &fp, FILES[1], "r");
	if ( file_err == EINVAL )
	{
		perror("file");
		goto VARRELEASE;
	}
	// -------------------------------------------------------------
	// 秘密鍵を読み込む
	prikey = RSA_new();
	prikey = PEM_read_RSAPrivateKey( fp, NULL, NULL, NULL);
	fclose(fp);
	if ( prikey == NULL )
	{
		puts("秘密鍵読み込みエラー");
		goto VARRELEASE;
	}
	// -------------------------------------------------------------
	// 秘密鍵を画面表示
	// 等価なコマンドは
	//   TODO: ... 
	RSA_print_fp(stdout, prikey, NULL);

	// =============================================================
	//   公開鍵
	// -------------------------------------------------------------
	puts("公開鍵");
	// 証明書情報から公開鍵を取り出す
	pubkey_pkey = EVP_PKEY_new();
	pubkey_pkey = X509_get_pubkey( x509 );
	if ( pubkey_pkey == NULL )
	{
		puts("公開鍵取り出しエラー");
		goto VARRELEASE;
	}
	pubkey = RSA_new();
	pubkey = EVP_PKEY_get1_RSA( pubkey_pkey );
	if ( pubkey == NULL )
	{
		puts("公開鍵データ形式変換エラー");
		goto VARRELEASE;
	}
	EVP_PKEY_free( pubkey_pkey );

	// -------------------------------------------------------------
	// 公開鍵を画面表示
	// 等価なコマンドは
	//   TODO: ... 
	RSA_print_fp(stdout, pubkey, NULL);

	// =============================================================
	//   メモリ解放
	// -------------------------------------------------------------
VARRELEASE:
	X509_free( x509 );
	RSA_free( prikey );
	RSA_free( pubkey );

	return 0;
}