Skip to content

Commit 6e2bb2c

Browse files
Merge pull request #6602 from BitGo/BTC-2360
feat(utxo-core): add BIP322 message tagged hash implementation
2 parents d13b592 + 364ad84 commit 6e2bb2c

File tree

5 files changed

+58
-1
lines changed

5 files changed

+58
-1
lines changed

modules/utxo-core/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@
5656
"@bitgo/utxo-lib": "^11.6.3",
5757
"@bitgo/wasm-miniscript": "2.0.0-beta.7",
5858
"bip174": "npm:@bitgo-forks/[email protected]",
59-
"bitcoinjs-message": "npm:@bitgo-forks/[email protected]"
59+
"bitcoinjs-message": "npm:@bitgo-forks/[email protected]",
60+
"fast-sha256": "^1.3.0"
6061
},
6162
"gitHead": "18e460ddf02de2dbf13c2aa243478188fb539f0c"
6263
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './toSpend';
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Hash } from 'fast-sha256';
2+
3+
export const BIP322_TAG = 'BIP0322-signed-message';
4+
5+
/**
6+
* Perform a tagged hash
7+
*
8+
* @param {string | Buffer} message - The message to hash as a Buffer or utf-8 string
9+
* @param {Buffer} [tag=BIP322_TAG] - The tag to use for hashing, defaults to BIP322_TAG.
10+
* @returns {Buffer} - The resulting hash of the message with the tag.
11+
*/
12+
export function hashMessageWithTag(message: string | Buffer, tag = BIP322_TAG): Buffer {
13+
// Compute the message hash - SHA256(SHA256(tag) || SHA256(tag) || message)
14+
// Reference: https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki#full
15+
const tagHasher = new Hash();
16+
tagHasher.update(Buffer.from(BIP322_TAG));
17+
const tagHash = tagHasher.digest();
18+
const messageHasher = new Hash();
19+
messageHasher.update(tagHash);
20+
messageHasher.update(tagHash);
21+
messageHasher.update(Buffer.from(message));
22+
const messageHash = messageHasher.digest();
23+
return Buffer.from(messageHash);
24+
}

modules/utxo-core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export * as descriptor from './descriptor';
33
export * as testutil from './testutil';
44
export * as paygo from './paygo';
55
export * as bip32utils from './bip32utils';
6+
export * as bip322 from './bip322';
67
export * from './dustThreshold';
78
export * from './Output';
89
export * from './xOnlyPubkey';
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import assert from 'assert';
2+
3+
import { hashMessageWithTag } from '../../src/bip322';
4+
5+
describe('to_spend', function () {
6+
describe('Message hashing', function () {
7+
// Test vectors from BIP322
8+
// Source: https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki#message-hashing
9+
const fixtures = [
10+
{
11+
message: '',
12+
hash: 'c90c269c4f8fcbe6880f72a721ddfbf1914268a794cbb21cfafee13770ae19f1',
13+
},
14+
{
15+
message: 'Hello World',
16+
hash: 'f0eb03b1a75ac6d9847f55c624a99169b5dccba2a31f5b23bea77ba270de0a7a',
17+
},
18+
];
19+
fixtures.forEach(({ message, hash }) => {
20+
it(`should hash the message "${message}"`, function () {
21+
const result = hashMessageWithTag(Buffer.from(message));
22+
assert.deepStrictEqual(
23+
result.toString('hex'),
24+
hash,
25+
`Hash for message "${message}" does not match expected value`
26+
);
27+
});
28+
});
29+
});
30+
});

0 commit comments

Comments
 (0)