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; }