Skip to content

Commit b1e8ae5

Browse files
committed
v2.0.3 Fixed Merkle Root Verification and Paths for Keys
1 parent 922b7e9 commit b1e8ae5

File tree

3 files changed

+42
-19
lines changed

3 files changed

+42
-19
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,5 @@
5252
},
5353
"minimum-stability": "stable",
5454
"prefer-stable": true,
55-
"version": "2.0.2"
55+
"version": "2.0.3"
5656
}

config/blockchain.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,13 @@
111111

112112
/*
113113
|--------------------------------------------------------------------------
114-
| Blockchain Root Configuration
114+
| Merkle Root Configuration
115115
|--------------------------------------------------------------------------
116116
|
117117
| Enable Merkle root signing with a master key pair.
118118
|
119119
*/
120-
'with_blockchain_root' => env('WITH_BLOCKCHAIN_ROOT', false),
120+
'with_merkle_root' => env('WITH_MERKLE_ROOT', false),
121121
'master_private_key' => env('MASTER_PRIVATE_KEY', null),
122122
'master_private_key_password' => env('MASTER_PRIVATE_KEY_PASSWORD', null),
123123
'master_public_key' => env('MASTER_PUBLIC_KEY', null),

src/BlockchainManager.php

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -168,14 +168,15 @@ public function signBlock(string $data, $privateKey = null, ?string $password =
168168
*/
169169
public function createBlock(string $tableName, int $recordId, $data, ?int $user_id = null, $privateKey = null, ?string $password = null)
170170
{
171+
171172
$timestamp = $timestamp ?? now()->toDateTimeString();
172173
if (config('blockchain.auto_verify')) {
174+
173175
$verification = $this->verifyChain($tableName, $recordId);
174176
if (!$verification['valid']) {
175177
return $verification;
176178
}
177179
}
178-
179180
$blockchain = BlockchainLedger::where('table_name', $tableName)
180181
->where('record_id', $recordId)
181182
->orderBy('id', 'DESC')
@@ -206,7 +207,6 @@ public function createBlock(string $tableName, int $recordId, $data, ?int $user_
206207

207208
$with_certificate = ModelHasCertificate::where('user_id', $user_id)->where('status', 1)->first();
208209
$default_certificate = BlockchainDefaultCertificate::where('status', 1)->first();
209-
210210
if ($with_certificate) {
211211
$signature = $this->signBlock($signatureData, $privateKey, $password, $user_id);
212212
} else {
@@ -228,8 +228,7 @@ public function createBlock(string $tableName, int $recordId, $data, ?int $user_
228228
'default_certificate_id' => !$with_certificate && $default_certificate ? $default_certificate->id : null,
229229
'algorithm' => $hashAlgorithm,
230230
]);
231-
232-
config('blockchain.with_blockchain_root') ? $this->updateMerkleRoot($tableName, $recordId) : '';
231+
config('blockchain.with_merkle_root') ? $this->updateMerkleRoot($tableName, $recordId) : '';
233232

234233
return $block;
235234
}
@@ -246,14 +245,14 @@ public function createBlock(string $tableName, int $recordId, $data, ?int $user_
246245
*/
247246
public function verifyBlock(BlockchainLedger $block): bool
248247
{
248+
249249
$computedHash = $block->data . $block->data_hash . $block->previous_hash . $block->block_hash . $block->algorithm;
250250

251251
$publicKeyPath = $this->getPublicKeyPath($block);
252-
253252
if ($block->with_user_certificate == 1) {
254253
$certificate = ModelHasCertificate::where('id', $block->certificate_id)->first();
255-
if ($certificate && file_exists(storage_path($certificate->public_key_path)) && $block->with_user_certificate == 1) {
256-
$publicKeyPath = storage_path($certificate->public_key_path);
254+
if ($certificate && file_exists($certificate->public_key_path) && $block->with_user_certificate == 1) {
255+
$publicKeyPath = $certificate->public_key_path;
257256
}
258257
}
259258

@@ -297,12 +296,15 @@ public function verifyChain(string $tableName, int $recordId): array
297296
];
298297
}
299298

300-
$verify_root = $this->verifyMerkleRoot($tableName, $recordId);
301-
if (!$verify_root) {
302-
return [
303-
'valid' => false,
304-
'message' => 'Blockchain tampering detected: Merkle root verification failed. One or more blocks may have been altered.',
305-
];
299+
if(config('blockchain.with_merkle_root')) {
300+
$merkle_root = BlockchainRoot::where('table_name', $tableName)->where('record_id', $recordId)->first();
301+
$verify_root = $this->verifyMerkleRoot($tableName, $recordId);
302+
if (!$verify_root) {
303+
return [
304+
'valid' => false,
305+
'message' => 'Blockchain tampering detected: Merkle root verification failed. One or more blocks may have been altered.',
306+
];
307+
}
306308
}
307309

308310
$invalidBlocks = [];
@@ -459,7 +461,7 @@ public function updateMerkleRoot(string $tableName, int $recordId)
459461

460462
$merkleRoot = $this->computeMerkleRoot($blocks);
461463

462-
$masterPrivateKey = file_get_contents(storage_path(config('blockchain.master_private_key')));
464+
$masterPrivateKey = file_get_contents(config('blockchain.master_private_key'));
463465
$password = config('blockchain.master_private_key_password');
464466
openssl_sign($merkleRoot, $signature, openssl_pkey_get_private($masterPrivateKey, $password), OPENSSL_ALGO_SHA256);
465467

@@ -484,7 +486,28 @@ public function verifyMerkleRoot(string $tableName, int $recordId): bool
484486
->where('record_id', $recordId)
485487
->first();
486488

487-
if (!$root) return false;
489+
if (!$root) {
490+
$blocks = BlockchainLedger::where('table_name', $tableName)
491+
->where('record_id', $recordId)
492+
->orderBy('id', 'ASC')
493+
->pluck('block_hash')
494+
->toArray();
495+
496+
if (empty($blocks)) return false;
497+
498+
$merkleRoot = $this->computeMerkleRoot($blocks);
499+
500+
$masterPrivateKey = file_get_contents(config('blockchain.master_private_key'));
501+
$password = config('blockchain.master_private_key_password');
502+
openssl_sign($merkleRoot, $signature, openssl_pkey_get_private($masterPrivateKey, $password), OPENSSL_ALGO_SHA256);
503+
504+
$root = BlockchainRoot::create([
505+
'table_name' => $tableName,
506+
'record_id' => $recordId,
507+
'merkle_root' => $merkleRoot,
508+
'signature' => base64_encode($signature)
509+
]);
510+
};
488511

489512
$blocks = BlockchainLedger::where('table_name', $tableName)
490513
->where('record_id', $recordId)
@@ -493,7 +516,7 @@ public function verifyMerkleRoot(string $tableName, int $recordId): bool
493516
->toArray();
494517

495518
$computedRoot = $this->computeMerkleRoot($blocks);
496-
$masterPublicKey = file_get_contents(storage_path(config('blockchain.master_public_key')));
519+
$masterPublicKey = file_get_contents(config('blockchain.master_public_key'));
497520

498521
$verified = openssl_verify(
499522
$computedRoot,

0 commit comments

Comments
 (0)