如何在Node.js中验证QLDB文档?哈希计算不符问题求助
I see exactly where you're hitting a wall—you're converting hashes to hex strings and comparing individual characters, which doesn't match QLDB's required binary byte-level lexicographical comparison (the exact logic the Java example uses directly with byte arrays). Hex string character comparison works differently than raw byte value comparison, and concatenating hex strings instead of binary data will always produce the wrong hash.
Let's break down the fixes step by step:
Core Problems in Your Code
- You're converting hash bytes to hex strings immediately, then comparing single hex characters (each representing 4 bits) instead of full byte values (8 bits)
- You're concatenating hex strings and hashing that string, but QLDB requires concatenating raw binary bytes before hashing
Fixed Implementation
Here's the corrected code that aligns perfectly with the Java verification logic:
const crypto = require('crypto'); // Assuming makeReader is imported from ion-js or the QLDB SDK // 1. Read block hash as raw Buffer (no hex conversion yet) const rBlock = makeReader(res.Revision.IonText); let blockHash; rBlock.next(); rBlock.stepIn(); rBlock.next(); while (rBlock.next() !== null) { if (rBlock.fieldName() === 'hash') { blockHash = Buffer.from(rBlock.byteValue()); break; // We only need the single block hash } } // 2. Read proof hashes as raw Buffers const rProof = makeReader(res.Proof.IonText); const proofHashes = []; rProof.next(); rProof.stepIn(); while (rProof.next() !== null) { proofHashes.push(Buffer.from(rProof.byteValue())); } // 3. Compute the digest using binary byte comparison and concatenation let currentHash = blockHash; for (const proofHash of proofHashes) { // Compare raw byte values lexicographically (matches Java's Arrays.compare logic) let comparisonResult = 0; for (let i = 0; i < currentHash.length; i++) { if (currentHash[i] > proofHash[i]) { comparisonResult = 1; break; } else if (currentHash[i] < proofHash[i]) { comparisonResult = -1; break; } } // Concatenate the smaller buffer first, then the larger one const concatenated = comparisonResult < 0 ? Buffer.concat([currentHash, proofHash]) : Buffer.concat([proofHash, currentHash]); // Hash the concatenated binary data currentHash = crypto.createHash('sha256').update(concatenated).digest(); } // Convert final digest to hex/base64 for comparison with ledger values const finalDigestHex = currentHash.toString('hex'); const finalDigestBase64 = currentHash.toString('base64'); console.log('Final computed digest (hex):', finalDigestHex); console.log('Final computed digest (base64):', finalDigestBase64);
Key Fixes Explained
- Keep hashes as Buffers: We avoid converting to hex until the final step—all comparisons and concatenations happen on raw binary data, matching how Java handles byte arrays.
- Byte-level comparison: We compare each byte's numerical value directly, not the hex string characters. This is exactly how QLDB expects proof validation to work.
- Binary concatenation: Using
Buffer.concatcombines raw bytes instead of string concatenation, ensuring the SHA-256 input matches exactly what the ledger uses.
Quick Verification Tip
Double-check that you're comparing the final computed digest to the correct ledger value (either the Commitment hash from the ledger or a value returned by a verification API call). Make sure you use the same encoding (hex or base64) for both your computed value and the ledger's value.
内容的提问来源于stack exchange,提问作者Alko

