Files
BankManager/merkle.c
T

98 lines
2.7 KiB
C
Raw Permalink Normal View History

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <wincrypt.h>
#include "bank.h"
HashValue g_merkleRoot;
static HCRYPTPROV g_hProv = 0;
static void ensureProvider() {
if (g_hProv == 0)
CryptAcquireContext(&g_hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
}
static void sha256(unsigned char* out, const unsigned char* data1, unsigned int len1,
const unsigned char* data2, unsigned int len2) {
HCRYPTHASH hHash = 0;
DWORD hashLen = HASH_SIZE;
ensureProvider();
CryptCreateHash(g_hProv, CALG_SHA_256, 0, 0, &hHash);
if (data1 && len1) CryptHashData(hHash, data1, len1, 0);
if (data2 && len2) CryptHashData(hHash, data2, len2, 0);
CryptGetHashParam(hHash, HP_HASHVAL, out, &hashLen, 0);
CryptDestroyHash(hHash);
}
/* ==================== Merkle Tree ==================== */
void HashLogEntry(const LogEntry* entry, HashValue* out) {
char buf[256];
sprintf(buf, "ID:%d Type:%s Amount:%.2f Balance:%.2f Time:%s Loc:%s",
entry->account_id, entry->type, entry->amount,
entry->balance, entry->timestamp, entry->location);
sha256(out->data, (unsigned char*)buf, (unsigned int)strlen(buf), NULL, 0);
}
static void hashPair(const HashValue* a, const HashValue* b, HashValue* out) {
sha256(out->data, a->data, HASH_SIZE, b->data, HASH_SIZE);
}
void BuildMerkleTree(HashValue* root) {
int count = GetLogCount();
if (count == 0) {
memset(root->data, 0, HASH_SIZE);
return;
}
HashValue* leaves = (HashValue*)malloc(count * sizeof(HashValue));
if (!leaves) return;
int i = g_logQueue.front;
int idx = 0;
while (i != g_logQueue.rear) {
HashLogEntry(&g_logQueue.logs[i], &leaves[idx]);
i = (i + 1) % MAX_LOGS;
idx++;
}
int n = count;
while (n > 1) {
int j;
for (j = 0; j < n / 2; j++)
hashPair(&leaves[2 * j], &leaves[2 * j + 1], &leaves[j]);
if (n % 2 == 1) {
hashPair(&leaves[n - 1], &leaves[n - 1], &leaves[n / 2]);
n = n / 2 + 1;
} else {
n = n / 2;
}
}
memcpy(root->data, leaves[0].data, HASH_SIZE);
free(leaves);
}
void HashToHex(const HashValue* hash, char* hex_out) {
int i;
for (i = 0; i < HASH_SIZE; i++)
sprintf(hex_out + i * 2, "%02x", hash->data[i]);
hex_out[HASH_SIZE * 2] = '\0';
}
void PrintMerkleRoot() {
char hex[65];
HashToHex(&g_merkleRoot, hex);
printf("\n当前默克尔根: %s\n", hex);
}
int VerifyMerkleTree() {
HashValue computed;
BuildMerkleTree(&computed);
return memcmp(computed.data, g_merkleRoot.data, HASH_SIZE) == 0;
}