@@ -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