#define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #include #include #include // OpenSSLエラーを標準エラー出力に出力するヘルパー関数 void handle_openssl_error() { // エラー情報を標準エラー出力にプリントする ERR_print_errors_fp(stderr); } // OpenSSLの初期化を行う関数 void initialize_openssl() { // OpenSSLライブラリの初期化を行う if (!OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)) { // 指定されたファイルストリームに書き込むためのフォーマットされた出力を行う fprintf(stderr, "OpenSSL initialization failed.\n"); // エラーが発生した場合に、エラー情報を取得して標準エラー出力に表示する handle_openssl_error(); // プログラムが正常に終了せずエラーが発生したことを示す exit(EXIT_FAILURE); } } // データのSHA-256ハッシュを計算する関数 unsigned char* sha256_hash(const unsigned char* data, size_t data_len, unsigned int* hash_len) { // メッセージダイジェスト操作のための新しいコンテキストを作成 EVP_MD_CTX* md_ctx = EVP_MD_CTX_new(); if (!md_ctx) { perror("Failed to create EVP_MD_CTX"); handle_openssl_error(); exit(EXIT_FAILURE); } // SHA-256メッセージダイジェストの初期化 if (!EVP_DigestInit(md_ctx, EVP_sha256())) { perror("Failed to initialize SHA256 digest"); handle_openssl_error(); // OpenSSLのメッセージダイジェストコンテキスト(EVP_MD_CTX)に関連するメモリを解放する EVP_MD_CTX_free(md_ctx); exit(EXIT_FAILURE); } // メッセージダイジェストの更新 if (!EVP_DigestUpdate(md_ctx, data, (unsigned int)data_len)) { perror("Failed to update SHA256 digest"); handle_openssl_error(); EVP_MD_CTX_free(md_ctx); exit(EXIT_FAILURE); } // SHA-256ハッシュ値を格納するために、動的にメモリを確保 unsigned char* hash = (unsigned char*)malloc(SHA256_DIGEST_LENGTH); if (!hash) { perror("Failed to allocate memory for hash"); handle_openssl_error(); EVP_MD_CTX_free(md_ctx); exit(EXIT_FAILURE); } // メッセージダイジェストの最終化 if (!EVP_DigestFinal(md_ctx, hash, hash_len)) { perror("Failed to finalize SHA256 digest"); handle_openssl_error(); free(hash); EVP_MD_CTX_free(md_ctx); exit(EXIT_FAILURE); } EVP_MD_CTX_free(md_ctx); // ハッシュを計算し、その結果を返す return hash; } // データをプライベートキーで署名する関数 unsigned char* sign_data(const unsigned char* data, size_t data_len, EVP_PKEY* private_key, unsigned int* signature_len) { // データのSHA-256ハッシュを計算し、その結果を格納するためにメモリを動的に確保 unsigned char* hash = sha256_hash(data, data_len, signature_len); if (!hash) { return NULL; } // プライベートキーを使用してデータに署名するために、署名を格納するためのメモリを動的に確保 unsigned char* signature = (unsigned char*)malloc(EVP_PKEY_size(private_key)); if (!signature) { perror("Failed to allocate memory for signature"); handle_openssl_error(); free(hash); return NULL; } EVP_MD_CTX* md_ctx = EVP_MD_CTX_new(); if (!md_ctx) { perror("Failed to create EVP_MD_CTX"); handle_openssl_error(); free(hash); free(signature); exit(EXIT_FAILURE); } // OpenSSLのライブラリ関数を使用して、データの署名を生成する一連の操作を行う if (!EVP_SignInit(md_ctx, EVP_sha256()) || !EVP_SignUpdate(md_ctx, hash, *signature_len) || !EVP_SignFinal(md_ctx, signature, signature_len, private_key)) { perror("Failed to sign data"); handle_openssl_error(); free(hash); free(signature); EVP_MD_CTX_free(md_ctx); exit(EXIT_FAILURE); } free(hash); EVP_MD_CTX_free(md_ctx); // データのハッシュを計算し、それをプライベートキーで署名する return signature; } // データの署名を検証する関数 int verify_signature(const unsigned char* data, size_t data_len, const unsigned char* signature, size_t signature_len, EVP_PKEY* public_key) { unsigned char* hash = sha256_hash(data, data_len, NULL); if (!hash) { return -1; } EVP_MD_CTX* md_ctx = EVP_MD_CTX_new(); if (!md_ctx) { perror("Failed to create EVP_MD_CTX"); handle_openssl_error(); free(hash); exit(EXIT_FAILURE); } // OpenSSLの関数を使用してデータのデジタル署名を検証する int result = EVP_VerifyInit(md_ctx, EVP_sha256()) && EVP_VerifyUpdate(md_ctx, hash, (unsigned int)SHA256_DIGEST_LENGTH) && EVP_VerifyFinal(md_ctx, signature, (unsigned int)signature_len, public_key); free(hash); EVP_MD_CTX_free(md_ctx); // データのハッシュを計算し、その署名を公開キーで検証する return result; } // プライベートキーをファイルから読み込む関数 int load_private_key(const char* key_file, EVP_PKEY** private_key) { FILE* fp; if (fopen_s(&fp, key_file, "rb") != 0) { perror("Failed to open private key file"); return 0; } * private_key = PEM_read_PrivateKey(fp, NULL, NULL, NULL); fclose(fp); if (!*private_key) { perror("Failed to read private key"); handle_openssl_error(); return 0; } // ファイルからプライベートキーを読み込む return 1; } // パブリックキーをファイルから読み込む関数 int load_public_key(const char* key_file, EVP_PKEY** public_key) { FILE* fp; if (fopen_s(&fp, key_file, "rb") != 0) { perror("Failed to open public key file"); return 0; } *public_key = PEM_read_PUBKEY(fp, NULL, NULL, NULL); fclose(fp); if (!*public_key) { perror("Failed to read public key"); handle_openssl_error(); return 0; } // ファイルからパブリックキーを読み込む return 1; } int main() { const char* private_key_file = "private_key.pem"; const char* public_key_file = "public_key.pem"; initialize_openssl(); // テストデータ const char* data = "Hello, World!"; size_t data_len = strlen(data); // プライベートキーとパブリックキーの初期化 EVP_PKEY* private_key = NULL; EVP_PKEY* public_key = NULL; // プライベートキーとパブリックキーをファイルから読み込む if (!load_private_key(private_key_file, &private_key) || !load_public_key(public_key_file, &public_key)) { EVP_PKEY_free(private_key); EVP_PKEY_free(public_key); return -1; } // デジタル署名の生成 unsigned int signature_len; unsigned char* signature = sign_data((const unsigned char*)data, data_len, private_key, &signature_len); if (!signature) { // エラー処理 EVP_PKEY_free(private_key); EVP_PKEY_free(public_key); return -1; } // デジタル署名の検証 int result = verify_signature((const unsigned char*)data, data_len, signature, signature_len, public_key); // 結果の表示 if (result == 1) { printf("デジタル署名の検証に成功しました。\n"); } else if (result == 0) { printf("デジタル署名の検証に失敗しました。\n"); } else { perror("デジタル署名の検証中にエラーが発生しました"); } // 使用したメモリの解放 EVP_PKEY_free(private_key); EVP_PKEY_free(public_key); free(signature); return 0; }