sha256c クラスは考え直すべき

書き直した.

SHA256_Final() を呼ぶ度にハッシュが変わってしまう.sha256c というクラスを作った - BiBoLoG を書き直した.assert() を使って,プログラムを書いて,デバッグしているときに止めるようにした.一旦 final したなら,再利用はできないよ,init から始めようねって.

rsaCodec.cpp は公開鍵で暗号化し,秘密鍵で復号化する.これはできてはいるんだけれど,その手前に問題がある.sha256c クラスの classtest() で,"The quick brown fox jumps over the lazy dog" から "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592" ができあがるのは良い.その後 getHash(),して showHash() すると "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" と表示されるの.どういう事.

今のところ,showHash() がまずいのかな,と考えている.memcpy_s の結果,キチンとコピーできているし.

sha256c.h

#pragma once

#ifdef _DEBUG
#pragma comment(lib, "libeay32MDd.lib")
#pragma comment(lib, "ssleay32MDd.lib")
#else
#pragma comment(lib, "libeay32MD.lib")
#pragma comment(lib, "ssleay32MD.lib")
#endif

#include <openssl/sha.h>
#include <stdio.h>
#include <string.h>

class sha256c{
private:
	unsigned char hash[SHA256_DIGEST_LENGTH];
	SHA256_CTX ctx;
	bool finalyet; // final() 未実行のとき true

public:
	sha256c( void );

	void init( void );

	void update( unsigned char *data, size_t len );

	unsigned char *getHash();

	void showHash( void );

	void classtest( void );
};

sha256c.cpp

#include "sha256c.h"
#include <assert.h>

sha256c::sha256c( void )
{
	init();
}

void sha256c::init( void )
{
	SHA256_Init(&ctx);
	finalyet = true;
}

void sha256c::update( unsigned char *data, size_t len )
{
	// 一旦 SHA256_Final() した後の SHA256_Update(() を認めない
	assert( finalyet ); // SHA256_Final() 実行済みのとき停止
	SHA256_Update( &ctx, data, len );
}

unsigned char *sha256c::getHash()
{
	if ( finalyet )
	{
		SHA256_Final( hash, &ctx );
		finalyet = false;
	}
	return hash;
}

void sha256c::showHash( void )
{
	if ( finalyet )
	{
		SHA256_Final( hash, &ctx );
		finalyet = false;
	}
	for ( size_t i = 0; i < SHA256_DIGEST_LENGTH; i++ )
	{
		printf("%02x", hash[i] );
	}
	printf("\n");
}

void sha256c::classtest( void )
{
	// ハッシュを求めたいデータ
	char *textvector = "The quick brown fox jumps over the lazy dog";
	printf("textvector: %s\n", textvector );

	// ハッシュ計算
	sha256c h;
	h.update( (unsigned char *)textvector, strlen(textvector) );
	printf("hash: ");
	h.showHash(); // 表示
	// d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592 と出れば良し
	// http://www.chilkatsoft.com/js-sha256-hash.asp

	// ハッシュを求めたいデータを逐次送る場合
	char *fragment[] = {"The ","quick ","brown ","fox ","jumps ","over ","the ","lazy ","dog"};
	size_t numword = sizeof(fragment) / sizeof(fragment[0]); // 分割個数

	// ハッシュ計算
	h.init();
	printf("fragment[]: ");
	for ( size_t i = 0; i < numword; i++ )
	{
		printf(fragment[i]);
		h.update( (unsigned char *)fragment[i], strlen(fragment[i]) );
	}
	printf("\nhash: ");
	h.showHash();
}

rsaCodec.cpp

#include <openssl/rsa.h>
#include <openssl/pem.h>
#include "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[] )
{
	sha256c s;
	s.classtest();

	// プレーンテキスト.暗号化対象
	unsigned char planetext[SHA256_DIGEST_LENGTH];
	// プレーンテキストに SHA256 ハッシュを選ぶ
	showHash( s.getHash(), SHA256_DIGEST_LENGTH );
	memcpy_s( (unsigned char *)planetext, SHA256_DIGEST_LENGTH, (unsigned char *)s.getHash(), SHA256_DIGEST_LENGTH );
	showHash( planetext, SHA256_DIGEST_LENGTH );
	unsigned char *a = s.getHash();

	// 公開鍵ファイルを読み込む
	FILE *fp;
	fopen_s( &fp, pubKeyFilename, "r");
	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" );
	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;
}