@btc-vision/transaction 1.6.19 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/browser/index.js +1 -1
  2. package/browser/index.js.LICENSE.txt +2 -0
  3. package/browser/src/_version.d.ts +1 -0
  4. package/browser/{epoch → src/epoch}/interfaces/IChallengeSolution.d.ts +2 -0
  5. package/browser/{keypair → src/keypair}/Address.d.ts +7 -4
  6. package/browser/{keypair → src/keypair}/AddressVerificator.d.ts +3 -0
  7. package/browser/{keypair → src/keypair}/EcKeyPair.d.ts +3 -2
  8. package/browser/{keypair → src/keypair}/MessageSigner.d.ts +9 -0
  9. package/browser/src/keypair/Wallet.d.ts +47 -0
  10. package/browser/{keypair → src/keypair}/interfaces/IWallet.d.ts +2 -0
  11. package/browser/src/mnemonic/BIPStandard.d.ts +8 -0
  12. package/browser/src/mnemonic/Mnemonic.d.ts +34 -0
  13. package/browser/src/mnemonic/MnemonicStrength.d.ts +7 -0
  14. package/browser/{opnet.d.ts → src/opnet.d.ts} +5 -0
  15. package/browser/src/transaction/browser/types/OPWallet.d.ts +14 -0
  16. package/browser/test/address.test.d.ts +1 -0
  17. package/browser/test/addressverificator-mldsa.test.d.ts +1 -0
  18. package/browser/test/derivePath.test.d.ts +1 -0
  19. package/browser/test/messagesigner-mldsa.test.d.ts +1 -0
  20. package/browser/test/messagesigner-schnorr.test.d.ts +1 -0
  21. package/browser/test/network-awareness.test.d.ts +1 -0
  22. package/build/_version.d.ts +1 -1
  23. package/build/_version.js +1 -1
  24. package/build/crypto/crypto-browser.d.ts +11 -0
  25. package/build/crypto/crypto-browser.js +56 -0
  26. package/build/epoch/ChallengeSolution.js +3 -2
  27. package/build/epoch/interfaces/IChallengeSolution.d.ts +2 -0
  28. package/build/keypair/Address.d.ts +7 -4
  29. package/build/keypair/Address.js +88 -37
  30. package/build/keypair/AddressVerificator.d.ts +3 -0
  31. package/build/keypair/AddressVerificator.js +49 -1
  32. package/build/keypair/EcKeyPair.d.ts +3 -2
  33. package/build/keypair/EcKeyPair.js +17 -3
  34. package/build/keypair/MessageSigner.d.ts +9 -0
  35. package/build/keypair/MessageSigner.js +23 -0
  36. package/build/keypair/Wallet.d.ts +20 -3
  37. package/build/keypair/Wallet.js +108 -9
  38. package/build/keypair/interfaces/IWallet.d.ts +2 -0
  39. package/build/mnemonic/BIPStandard.d.ts +8 -0
  40. package/build/mnemonic/BIPStandard.js +24 -0
  41. package/build/mnemonic/Mnemonic.d.ts +34 -0
  42. package/build/mnemonic/Mnemonic.js +140 -0
  43. package/build/mnemonic/MnemonicStrength.d.ts +7 -0
  44. package/build/mnemonic/MnemonicStrength.js +8 -0
  45. package/build/opnet.d.ts +5 -0
  46. package/build/opnet.js +5 -0
  47. package/build/transaction/browser/types/OPWallet.d.ts +14 -0
  48. package/build/transaction/browser/types/OPWallet.js +6 -0
  49. package/documentation/README.md +32 -0
  50. package/documentation/quantum-support/01-introduction.md +88 -0
  51. package/documentation/quantum-support/02-mnemonic-and-wallet.md +445 -0
  52. package/documentation/quantum-support/03-address-generation.md +329 -0
  53. package/documentation/quantum-support/04-message-signing.md +623 -0
  54. package/documentation/quantum-support/05-address-verification.md +307 -0
  55. package/documentation/quantum-support/README.md +65 -0
  56. package/gulpfile.js +2 -2
  57. package/package.json +25 -17
  58. package/src/_version.ts +1 -1
  59. package/src/epoch/ChallengeSolution.ts +3 -2
  60. package/src/epoch/interfaces/IChallengeSolution.ts +2 -0
  61. package/src/keypair/Address.ts +145 -43
  62. package/src/keypair/AddressVerificator.ts +87 -2
  63. package/src/keypair/EcKeyPair.ts +58 -6
  64. package/src/keypair/MessageSigner.ts +58 -0
  65. package/src/keypair/Wallet.ts +339 -57
  66. package/src/keypair/interfaces/IWallet.ts +13 -3
  67. package/src/mnemonic/BIPStandard.ts +92 -0
  68. package/src/mnemonic/Mnemonic.ts +465 -0
  69. package/src/mnemonic/MnemonicStrength.ts +12 -0
  70. package/src/network/ChainId.ts +1 -4
  71. package/src/opnet.ts +17 -0
  72. package/src/transaction/browser/types/OPWallet.ts +73 -0
  73. package/test/address.test.ts +1068 -0
  74. package/test/addressverificator-mldsa.test.ts +473 -0
  75. package/test/derivePath.test.ts +513 -0
  76. package/test/messagesigner-mldsa.test.ts +1060 -0
  77. package/test/messagesigner-schnorr.test.ts +1011 -0
  78. package/test/network-awareness.test.ts +163 -0
  79. package/tsconfig.json +1 -1
  80. package/vitest.config.ts +21 -0
  81. package/browser/_version.d.ts +0 -1
  82. package/browser/keypair/Wallet.d.ts +0 -30
  83. package/doc/README.md +0 -0
  84. /package/browser/{abi → src/abi}/ABICoder.d.ts +0 -0
  85. /package/browser/{buffer → src/buffer}/BinaryReader.d.ts +0 -0
  86. /package/browser/{buffer → src/buffer}/BinaryWriter.d.ts +0 -0
  87. /package/browser/{bytecode → src/bytecode}/Compressor.d.ts +0 -0
  88. /package/browser/{consensus → src/consensus}/Consensus.d.ts +0 -0
  89. /package/browser/{consensus → src/consensus}/ConsensusConfig.d.ts +0 -0
  90. /package/browser/{consensus → src/consensus}/metadata/RoswellConsensus.d.ts +0 -0
  91. /package/browser/{crypto → src/crypto}/crypto-browser.d.ts +0 -0
  92. /package/browser/{crypto → src/crypto}/crypto.d.ts +0 -0
  93. /package/browser/{deterministic → src/deterministic}/AddressMap.d.ts +0 -0
  94. /package/browser/{deterministic → src/deterministic}/AddressSet.d.ts +0 -0
  95. /package/browser/{deterministic → src/deterministic}/DeterministicMap.d.ts +0 -0
  96. /package/browser/{deterministic → src/deterministic}/DeterministicSet.d.ts +0 -0
  97. /package/browser/{deterministic → src/deterministic}/Map.d.ts +0 -0
  98. /package/browser/{epoch → src/epoch}/ChallengeSolution.d.ts +0 -0
  99. /package/browser/{epoch → src/epoch}/validator/EpochValidator.d.ts +0 -0
  100. /package/browser/{event → src/event}/NetEvent.d.ts +0 -0
  101. /package/browser/{generators → src/generators}/AddressGenerator.d.ts +0 -0
  102. /package/browser/{generators → src/generators}/Features.d.ts +0 -0
  103. /package/browser/{generators → src/generators}/Generator.d.ts +0 -0
  104. /package/browser/{generators → src/generators}/builders/CalldataGenerator.d.ts +0 -0
  105. /package/browser/{generators → src/generators}/builders/CustomGenerator.d.ts +0 -0
  106. /package/browser/{generators → src/generators}/builders/DeploymentGenerator.d.ts +0 -0
  107. /package/browser/{generators → src/generators}/builders/LegacyCalldataGenerator.d.ts +0 -0
  108. /package/browser/{generators → src/generators}/builders/MultiSignGenerator.d.ts +0 -0
  109. /package/browser/{generators → src/generators}/builders/P2WDAGenerator.d.ts +0 -0
  110. /package/browser/{index.d.ts → src/index.d.ts} +0 -0
  111. /package/browser/{keypair → src/keypair}/Secp256k1PointDeriver.d.ts +0 -0
  112. /package/browser/{metadata → src/metadata}/ContractBaseMetadata.d.ts +0 -0
  113. /package/browser/{metadata → src/metadata}/tokens.d.ts +0 -0
  114. /package/browser/{network → src/network}/ChainId.d.ts +0 -0
  115. /package/browser/{p2wda → src/p2wda}/P2WDADetector.d.ts +0 -0
  116. /package/browser/{signer → src/signer}/SignerUtils.d.ts +0 -0
  117. /package/browser/{signer → src/signer}/TweakedSigner.d.ts +0 -0
  118. /package/browser/{transaction → src/transaction}/ContractAddress.d.ts +0 -0
  119. /package/browser/{transaction → src/transaction}/TransactionFactory.d.ts +0 -0
  120. /package/browser/{transaction → src/transaction}/browser/BrowserSignerBase.d.ts +0 -0
  121. /package/browser/{transaction → src/transaction}/browser/Web3Provider.d.ts +0 -0
  122. /package/browser/{transaction → src/transaction}/browser/extensions/UnisatSigner.d.ts +0 -0
  123. /package/browser/{transaction → src/transaction}/browser/extensions/XverseSigner.d.ts +0 -0
  124. /package/browser/{transaction → src/transaction}/browser/types/Unisat.d.ts +0 -0
  125. /package/browser/{transaction → src/transaction}/browser/types/Xverse.d.ts +0 -0
  126. /package/browser/{transaction → src/transaction}/builders/CancelTransaction.d.ts +0 -0
  127. /package/browser/{transaction → src/transaction}/builders/ChallengeSolutionTransaction.d.ts +0 -0
  128. /package/browser/{transaction → src/transaction}/builders/CustomScriptTransaction.d.ts +0 -0
  129. /package/browser/{transaction → src/transaction}/builders/DeploymentTransaction.d.ts +0 -0
  130. /package/browser/{transaction → src/transaction}/builders/FundingTransaction.d.ts +0 -0
  131. /package/browser/{transaction → src/transaction}/builders/InteractionTransaction.d.ts +0 -0
  132. /package/browser/{transaction → src/transaction}/builders/InteractionTransactionP2WDA.d.ts +0 -0
  133. /package/browser/{transaction → src/transaction}/builders/MultiSignTransaction.d.ts +0 -0
  134. /package/browser/{transaction → src/transaction}/builders/SharedInteractionTransaction.d.ts +0 -0
  135. /package/browser/{transaction → src/transaction}/builders/TransactionBuilder.d.ts +0 -0
  136. /package/browser/{transaction → src/transaction}/enums/TransactionType.d.ts +0 -0
  137. /package/browser/{transaction → src/transaction}/interfaces/ITransactionParameters.d.ts +0 -0
  138. /package/browser/{transaction → src/transaction}/interfaces/Tap.d.ts +0 -0
  139. /package/browser/{transaction → src/transaction}/mineable/IP2WSHAddress.d.ts +0 -0
  140. /package/browser/{transaction → src/transaction}/mineable/TimelockGenerator.d.ts +0 -0
  141. /package/browser/{transaction → src/transaction}/processor/PsbtTransaction.d.ts +0 -0
  142. /package/browser/{transaction → src/transaction}/psbt/PSBTTypes.d.ts +0 -0
  143. /package/browser/{transaction → src/transaction}/shared/P2TR_MS.d.ts +0 -0
  144. /package/browser/{transaction → src/transaction}/shared/TweakedTransaction.d.ts +0 -0
  145. /package/browser/{utils → src/utils}/BitcoinUtils.d.ts +0 -0
  146. /package/browser/{utils → src/utils}/BufferHelper.d.ts +0 -0
  147. /package/browser/{utils → src/utils}/StringToBuffer.d.ts +0 -0
  148. /package/browser/{utils → src/utils}/lengths.d.ts +0 -0
  149. /package/browser/{utils → src/utils}/types.d.ts +0 -0
  150. /package/browser/{utxo → src/utxo}/OPNetLimitedProvider.d.ts +0 -0
  151. /package/browser/{utxo → src/utxo}/interfaces/BroadcastResponse.d.ts +0 -0
  152. /package/browser/{utxo → src/utxo}/interfaces/IUTXO.d.ts +0 -0
  153. /package/browser/{verification → src/verification}/TapscriptVerificator.d.ts +0 -0
  154. /package/{doc → documentation}/addresses/P2OP.md +0 -0
  155. /package/{doc → documentation}/addresses/P2WDA.md +0 -0
@@ -0,0 +1,623 @@
1
+ # Message Signing Guide
2
+
3
+ ## Table of Contents
4
+ - [ML-DSA Signing](#ml-dsa-signing)
5
+ - [Schnorr Signing](#schnorr-signing)
6
+ - [Input Formats](#input-formats)
7
+ - [Signature Verification](#signature-verification)
8
+ - [Tweaked Signatures](#tweaked-signatures)
9
+ - [Best Practices](#best-practices)
10
+
11
+ ## ML-DSA Signing
12
+
13
+ ### Basic ML-DSA Signing
14
+
15
+ Sign messages with quantum-resistant ML-DSA signatures:
16
+
17
+ ```typescript
18
+ import { Mnemonic, MessageSigner, MLDSASecurityLevel } from '@btc-vision/transaction';
19
+ import { networks } from '@btc-vision/bitcoin';
20
+
21
+ // Generate wallet
22
+ const mnemonic = Mnemonic.generate(undefined, '', networks.bitcoin, MLDSASecurityLevel.LEVEL2);
23
+ const wallet = mnemonic.derive(0);
24
+
25
+ // Sign a message
26
+ const message = 'Hello, Quantum World!';
27
+ const signed = MessageSigner.signMLDSAMessage(wallet.mldsaKeypair, message);
28
+
29
+ console.log('Message:', signed.message);
30
+ console.log('Signature:', Buffer.from(signed.signature).toString('hex'));
31
+ console.log('Public Key:', Buffer.from(signed.publicKey).toString('hex'));
32
+ console.log('Security Level:', signed.securityLevel);
33
+ ```
34
+
35
+ ### ML-DSA Signature Sizes
36
+
37
+ Different security levels produce different signature sizes:
38
+
39
+ ```typescript
40
+ // LEVEL2 (ML-DSA-44)
41
+ const level2Mnemonic = Mnemonic.generate(undefined, '', networks.bitcoin, MLDSASecurityLevel.LEVEL2);
42
+ const level2Wallet = level2Mnemonic.derive(0);
43
+ const level2Sig = MessageSigner.signMLDSAMessage(level2Wallet.mldsaKeypair, 'test');
44
+ console.log('LEVEL2 Signature Size:', level2Sig.signature.length); // 2420 bytes
45
+
46
+ // LEVEL3 (ML-DSA-65)
47
+ const level3Mnemonic = Mnemonic.generate(undefined, '', networks.bitcoin, MLDSASecurityLevel.LEVEL3);
48
+ const level3Wallet = level3Mnemonic.derive(0);
49
+ const level3Sig = MessageSigner.signMLDSAMessage(level3Wallet.mldsaKeypair, 'test');
50
+ console.log('LEVEL3 Signature Size:', level3Sig.signature.length); // 3309 bytes
51
+
52
+ // LEVEL5 (ML-DSA-87)
53
+ const level5Mnemonic = Mnemonic.generate(undefined, '', networks.bitcoin, MLDSASecurityLevel.LEVEL5);
54
+ const level5Wallet = level5Mnemonic.derive(0);
55
+ const level5Sig = MessageSigner.signMLDSAMessage(level5Wallet.mldsaKeypair, 'test');
56
+ console.log('LEVEL5 Signature Size:', level5Sig.signature.length); // 4627 bytes
57
+ ```
58
+
59
+ ### Verifying ML-DSA Signatures
60
+
61
+ When verifying signatures, you need to create a public-key-only keypair using `QuantumBIP32Factory.fromPublicKey()`:
62
+
63
+ ```typescript
64
+ import { MessageSigner, QuantumBIP32Factory } from '@btc-vision/transaction';
65
+
66
+ // Sign message
67
+ const message = 'Verify this quantum signature';
68
+ const signed = MessageSigner.signMLDSAMessage(wallet.mldsaKeypair, message);
69
+
70
+ // Create public-key-only keypair for verification
71
+ const publicKeyPair = QuantumBIP32Factory.fromPublicKey(
72
+ signed.publicKey, // ML-DSA public key from signature
73
+ wallet.chainCode, // Chain code from wallet
74
+ network, // Network (mainnet/testnet/regtest)
75
+ securityLevel // ML-DSA security level (LEVEL2/LEVEL3/LEVEL5)
76
+ );
77
+
78
+ // Verify signature
79
+ const isValid = MessageSigner.verifyMLDSASignature(
80
+ publicKeyPair, // Use the public-key-only keypair
81
+ signed.message,
82
+ signed.signature
83
+ );
84
+
85
+ console.log('Signature valid:', isValid); // true
86
+
87
+ // Verify with wrong message fails
88
+ const isInvalid = MessageSigner.verifyMLDSASignature(
89
+ publicKeyPair,
90
+ 'Wrong message',
91
+ signed.signature
92
+ );
93
+ console.log('Invalid signature:', isInvalid); // false
94
+ ```
95
+
96
+ **Important:** The `verifyMLDSASignature` method requires a keypair object, not just a raw public key.
97
+
98
+ - **If you have the original keypair:** Use it directly (e.g., `wallet.mldsaKeypair`)
99
+ - **If you only have the public key:** Use `QuantumBIP32Factory.fromPublicKey()` to reconstruct the keypair
100
+
101
+ ### When to Use QuantumBIP32Factory.fromPublicKey()
102
+
103
+ **Use it when you DON'T have the original keypair:**
104
+ - Receiving a signature from someone else over the network
105
+ - Verifying signatures from stored public keys in a database
106
+ - Working with public keys in distributed systems
107
+ - Validating signatures from external sources
108
+
109
+ **Don't use it when you already have the keypair:**
110
+ - Verifying your own signatures in the same session
111
+ - Testing signatures you just created
112
+ - When you have access to `wallet.mldsaKeypair`
113
+
114
+ ### Creating a Public-Key-Only Keypair
115
+
116
+ Parameters for `QuantumBIP32Factory.fromPublicKey()`:
117
+
118
+ ```typescript
119
+ const keypair = QuantumBIP32Factory.fromPublicKey(
120
+ publicKey, // Uint8Array - ML-DSA public key (1312-2592 bytes)
121
+ chainCode, // Buffer - Chain code (32 bytes)
122
+ network, // Network - networks.bitcoin, networks.testnet, or networks.regtest
123
+ securityLevel // MLDSASecurityLevel - LEVEL2, LEVEL3, or LEVEL5
124
+ );
125
+ ```
126
+
127
+ **Parameter Details:**
128
+ - `publicKey`: The ML-DSA public key (1312 bytes for LEVEL2, 1952 for LEVEL3, 2592 for LEVEL5)
129
+ - `chainCode`: BIP32 chain code (32 bytes) - available from `wallet.chainCode`
130
+ - `network`: Bitcoin network configuration object
131
+ - `securityLevel`: **Must match** the security level used to generate the original key
132
+
133
+ **Why is this needed?**
134
+
135
+ The `verifyMLDSASignature` method requires a keypair object (not just a raw public key) because:
136
+ 1. It needs the security level information embedded in the keypair
137
+ 2. It needs the proper key structure for the ML-DSA verification algorithm
138
+ 3. It maintains consistency with BIP32 hierarchical deterministic key derivation
139
+
140
+ ### Common Verification Scenarios
141
+
142
+ **Scenario 1: Verifying your own signature (same session)**
143
+
144
+ ```typescript
145
+ const message = 'My message';
146
+ const signed = MessageSigner.signMLDSAMessage(wallet.mldsaKeypair, message);
147
+
148
+ // You already have the keypair - use it directly
149
+ const valid = MessageSigner.verifyMLDSASignature(
150
+ wallet.mldsaKeypair, // Use existing keypair
151
+ signed.message,
152
+ signed.signature
153
+ );
154
+
155
+ console.log('Valid:', valid); // true
156
+ ```
157
+
158
+ **Scenario 2: Verifying a signature from someone else**
159
+
160
+ ```typescript
161
+ // You receive these from the network/API:
162
+ const receivedPublicKey = Buffer.from(/* hex string from network */);
163
+ const receivedMessage = 'Message from sender';
164
+ const receivedSignature = Buffer.from(/* hex string from network */);
165
+ const receivedChainCode = Buffer.from(/* hex string from network */);
166
+ const receivedSecurityLevel = MLDSASecurityLevel.LEVEL2;
167
+
168
+ // Reconstruct keypair from public key
169
+ const keypair = QuantumBIP32Factory.fromPublicKey(
170
+ receivedPublicKey,
171
+ receivedChainCode,
172
+ networks.bitcoin,
173
+ receivedSecurityLevel
174
+ );
175
+
176
+ // Verify the signature
177
+ const valid = MessageSigner.verifyMLDSASignature(
178
+ keypair,
179
+ receivedMessage,
180
+ receivedSignature
181
+ );
182
+
183
+ console.log('Signature from other party valid:', valid);
184
+ ```
185
+
186
+ **Scenario 3: Verifying stored signatures**
187
+
188
+ ```typescript
189
+ // Load public key and signature from database
190
+ const storedPublicKey = await db.getPublicKey(userId);
191
+ const storedChainCode = await db.getChainCode(userId);
192
+ const storedSecurityLevel = await db.getSecurityLevel(userId);
193
+ const signature = await db.getSignature(messageId);
194
+ const message = await db.getMessage(messageId);
195
+
196
+ // Reconstruct keypair
197
+ const keypair = QuantumBIP32Factory.fromPublicKey(
198
+ Buffer.from(storedPublicKey, 'hex'),
199
+ Buffer.from(storedChainCode, 'hex'),
200
+ networks.bitcoin,
201
+ storedSecurityLevel
202
+ );
203
+
204
+ // Verify
205
+ const valid = MessageSigner.verifyMLDSASignature(
206
+ keypair,
207
+ message,
208
+ Buffer.from(signature, 'hex')
209
+ );
210
+
211
+ console.log('Stored signature valid:', valid);
212
+ ```
213
+
214
+ ### Security Considerations
215
+
216
+ **Chain Code:**
217
+ - The chain code is public information in BIP32
218
+ - Store it alongside the public key for verification
219
+ - It's not sensitive but required for keypair reconstruction
220
+
221
+ **Security Level Matching:**
222
+ - Always use the same security level for verification as was used for signing
223
+ - Mismatched security levels will cause verification to fail
224
+ - Store the security level with the public key
225
+
226
+ **Network Matching:**
227
+ - Ensure the network parameter matches the original signing network
228
+ - Mainnet keys won't verify correctly if checked against testnet
229
+
230
+ **Message Integrity:**
231
+ - The message must match exactly between signing and verification
232
+ - Even a single byte difference will cause verification to fail
233
+
234
+ ## Schnorr Signing
235
+
236
+ ### Basic Schnorr Signing
237
+
238
+ Sign messages with classical Schnorr signatures:
239
+
240
+ ```typescript
241
+ import { MessageSigner } from '@btc-vision/transaction';
242
+
243
+ const wallet = mnemonic.derive(0);
244
+
245
+ // Sign with Schnorr
246
+ const message = 'Hello, Bitcoin!';
247
+ const signed = MessageSigner.signMessage(wallet.keypair, message);
248
+
249
+ console.log('Message:', signed.message);
250
+ console.log('Signature:', Buffer.from(signed.signature).toString('hex'));
251
+ console.log('Public Key:', Buffer.from(signed.publicKey).toString('hex'));
252
+ console.log('Signature Size:', signed.signature.length); // 64 bytes (Schnorr)
253
+ ```
254
+
255
+ ### Verifying Schnorr Signatures
256
+
257
+ ```typescript
258
+ // Sign message
259
+ const message = 'Verify this Schnorr signature';
260
+ const signed = MessageSigner.signMessage(wallet.keypair, message);
261
+
262
+ // Verify signature
263
+ const isValid = MessageSigner.verifySignature(
264
+ signed.publicKey,
265
+ signed.message,
266
+ signed.signature
267
+ );
268
+
269
+ console.log('Signature valid:', isValid); // true
270
+ ```
271
+
272
+ ## Input Formats
273
+
274
+ Both ML-DSA and Schnorr signing support multiple input formats:
275
+
276
+ ### String Messages
277
+
278
+ ```typescript
279
+ // UTF-8 string
280
+ const signed1 = MessageSigner.signMLDSAMessage(wallet.mldsaKeypair, 'Hello, World!');
281
+
282
+ // Any string content
283
+ const signed2 = MessageSigner.signMLDSAMessage(
284
+ wallet.mldsaKeypair,
285
+ 'Emoji test: 🚀 Quantum 🔐'
286
+ );
287
+ ```
288
+
289
+ ### Buffer Messages
290
+
291
+ ```typescript
292
+ // From UTF-8 string
293
+ const message1 = Buffer.from('Hello, Buffer!', 'utf-8');
294
+ const signed1 = MessageSigner.signMLDSAMessage(wallet.mldsaKeypair, message1);
295
+
296
+ // Binary data
297
+ const message2 = Buffer.from([0x01, 0x02, 0x03, 0x04]);
298
+ const signed2 = MessageSigner.signMLDSAMessage(wallet.mldsaKeypair, message2);
299
+
300
+ // From hex
301
+ const message3 = Buffer.from('abcdef1234567890', 'hex');
302
+ const signed3 = MessageSigner.signMLDSAMessage(wallet.mldsaKeypair, message3);
303
+ ```
304
+
305
+ ### Uint8Array Messages
306
+
307
+ ```typescript
308
+ // Uint8Array
309
+ const message = new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f]); // "Hello"
310
+ const signed = MessageSigner.signMLDSAMessage(wallet.mldsaKeypair, message);
311
+ ```
312
+
313
+ ### Hex String Messages
314
+
315
+ ```typescript
316
+ // Hex string (with 0x prefix)
317
+ const signed1 = MessageSigner.signMLDSAMessage(
318
+ wallet.mldsaKeypair,
319
+ '0xdeadbeef'
320
+ );
321
+
322
+ // Hex string (without 0x prefix)
323
+ const signed2 = MessageSigner.signMLDSAMessage(
324
+ wallet.mldsaKeypair,
325
+ 'abcdef1234567890'
326
+ );
327
+ ```
328
+
329
+ ### Cross-Format Verification
330
+
331
+ Verification works across all input formats:
332
+
333
+ ```typescript
334
+ const message = 'Test message';
335
+
336
+ // Sign with string
337
+ const signed = MessageSigner.signMLDSAMessage(wallet.mldsaKeypair, message);
338
+
339
+ // Create public-key-only keypair for verification
340
+ const publicKeyPair = QuantumBIP32Factory.fromPublicKey(
341
+ signed.publicKey,
342
+ wallet.chainCode,
343
+ network,
344
+ securityLevel
345
+ );
346
+
347
+ // Verify with Buffer
348
+ const messageBuffer = Buffer.from(message, 'utf-8');
349
+ const valid1 = MessageSigner.verifyMLDSASignature(
350
+ publicKeyPair,
351
+ messageBuffer,
352
+ signed.signature
353
+ );
354
+
355
+ // Verify with Uint8Array
356
+ const messageArray = new Uint8Array(Buffer.from(message, 'utf-8'));
357
+ const valid2 = MessageSigner.verifyMLDSASignature(
358
+ publicKeyPair,
359
+ messageArray,
360
+ signed.signature
361
+ );
362
+
363
+ console.log(valid1 && valid2); // true - all formats work!
364
+ ```
365
+
366
+ ## Tweaked Signatures
367
+
368
+ ### Tweaked Schnorr Signing
369
+
370
+ Sign with tweaked keys for Taproot compatibility:
371
+
372
+ ```typescript
373
+ import { MessageSigner } from '@btc-vision/transaction';
374
+
375
+ const wallet = mnemonic.derive(0);
376
+
377
+ // Sign with tweaked key
378
+ const message = 'Taproot message';
379
+ const signed = MessageSigner.tweakAndSignMessage(wallet.keypair, message);
380
+
381
+ console.log('Tweaked Signature:', Buffer.from(signed.signature).toString('hex'));
382
+ console.log('Tweaked Public Key:', Buffer.from(signed.publicKey).toString('hex'));
383
+ ```
384
+
385
+ ### Verifying Tweaked Signatures
386
+
387
+ ```typescript
388
+ // Sign with tweak
389
+ const message = 'Verify tweaked signature';
390
+ const signed = MessageSigner.tweakAndSignMessage(wallet.keypair, message);
391
+
392
+ // Verify with tweak
393
+ const isValid = MessageSigner.tweakAndVerifySignature(
394
+ signed.publicKey,
395
+ signed.message,
396
+ signed.signature
397
+ );
398
+
399
+ console.log('Tweaked signature valid:', isValid); // true
400
+ ```
401
+
402
+ ## Message Hashing
403
+
404
+ ### SHA-256 Hashing
405
+
406
+ The MessageSigner automatically hashes messages before signing:
407
+
408
+ ```typescript
409
+ import { MessageSigner } from '@btc-vision/transaction';
410
+
411
+ // Long message
412
+ const longMessage = 'This is a very long message that will be hashed before signing...';
413
+
414
+ // Automatically hashed to 32 bytes before signing
415
+ const hash = MessageSigner.sha256(longMessage);
416
+ console.log('Message hash:', Buffer.from(hash).toString('hex'));
417
+ console.log('Hash length:', hash.length); // 32 bytes
418
+
419
+ // Then signed
420
+ const signed = MessageSigner.signMLDSAMessage(wallet.mldsaKeypair, longMessage);
421
+ ```
422
+
423
+ ### Pre-hashed Messages
424
+
425
+ ```typescript
426
+ // You can also sign pre-hashed data
427
+ const message = 'Original message';
428
+ const hash = MessageSigner.sha256(message);
429
+
430
+ // Sign the hash directly
431
+ const signed = MessageSigner.signMLDSAMessage(wallet.mldsaKeypair, hash);
432
+ ```
433
+
434
+ ## Best Practices
435
+
436
+ ### ✅ DO:
437
+
438
+ ```typescript
439
+ // Use appropriate security level for your use case
440
+ const standardWallet = Mnemonic.generate(
441
+ undefined, // Default strength (24 words)
442
+ '', // No passphrase
443
+ networks.bitcoin, // Mainnet
444
+ MLDSASecurityLevel.LEVEL2 // Good for most applications
445
+ );
446
+
447
+ // Include context in your messages
448
+ const message = JSON.stringify({
449
+ action: 'transfer',
450
+ amount: 1000,
451
+ timestamp: Date.now(),
452
+ nonce: crypto.randomBytes(16).toString('hex')
453
+ });
454
+
455
+ // Verify signatures before trusting
456
+ const isValid = MessageSigner.verifyMLDSASignature(
457
+ publicKey,
458
+ message,
459
+ signature
460
+ );
461
+ if (!isValid) {
462
+ throw new Error('Invalid signature');
463
+ }
464
+
465
+ // Store signatures with metadata
466
+ const signatureData = {
467
+ message: signed.message,
468
+ signature: Buffer.from(signed.signature).toString('hex'),
469
+ publicKey: Buffer.from(signed.publicKey).toString('hex'),
470
+ securityLevel: signed.securityLevel,
471
+ timestamp: Date.now()
472
+ };
473
+ ```
474
+
475
+ ### ❌ DON'T:
476
+
477
+ ```typescript
478
+ // Don't sign without verification
479
+ MessageSigner.signMLDSAMessage(wallet.mldsaKeypair, userInput); // Dangerous!
480
+
481
+ // Don't use signatures without checking validity
482
+ // Always verify!
483
+
484
+ // Don't expose private keys
485
+ console.log(wallet.privateKey); // Never do this!
486
+
487
+ // Don't sign arbitrary untrusted data
488
+ const untrustedData = externalAPI.getData();
489
+ // Validate and sanitize first!
490
+
491
+ // Don't reuse signatures for different messages
492
+ // Generate new signature for each unique message
493
+ ```
494
+
495
+ ### Message Structure
496
+
497
+ ```typescript
498
+ // Good: Structured, verifiable message
499
+ interface SignedMessage {
500
+ version: number;
501
+ action: string;
502
+ payload: any;
503
+ timestamp: number;
504
+ nonce: string;
505
+ }
506
+
507
+ const message: SignedMessage = {
508
+ version: 1,
509
+ action: 'authenticate',
510
+ payload: { userId: '123' },
511
+ timestamp: Date.now(),
512
+ nonce: crypto.randomBytes(16).toString('hex')
513
+ };
514
+
515
+ const messageString = JSON.stringify(message);
516
+ const signed = MessageSigner.signMLDSAMessage(wallet.mldsaKeypair, messageString);
517
+ ```
518
+
519
+ ## Complete Example
520
+
521
+ ```typescript
522
+ import {
523
+ MessageSigner,
524
+ MLDSASecurityLevel,
525
+ Mnemonic,
526
+ QuantumBIP32Factory,
527
+ } from '@btc-vision/transaction';
528
+ import { networks } from '@btc-vision/bitcoin';
529
+
530
+ const network = networks.regtest;
531
+ const securityLevel = MLDSASecurityLevel.LEVEL2;
532
+
533
+ // Setup
534
+ const mnemonic = Mnemonic.generate(undefined, undefined, network, securityLevel);
535
+
536
+ const wallet = mnemonic.derive(0);
537
+
538
+ // 1. Sign with ML-DSA (Quantum-resistant)
539
+ console.log('=== ML-DSA Signing ===');
540
+ const quantumMessage = 'Quantum-resistant message';
541
+ const quantumSigned = MessageSigner.signMLDSAMessage(wallet.mldsaKeypair, quantumMessage);
542
+
543
+ console.log('Message:', quantumSigned.message);
544
+ console.log('Signature Size:', quantumSigned.signature.length, 'bytes');
545
+ console.log('Public Key Size:', quantumSigned.publicKey.length, 'bytes');
546
+ console.log('Security Level:', quantumSigned.securityLevel);
547
+
548
+ const keypair = QuantumBIP32Factory.fromPublicKey(
549
+ quantumSigned.publicKey,
550
+ wallet.chainCode,
551
+ network,
552
+ securityLevel,
553
+ );
554
+
555
+ // Verify ML-DSA
556
+ const quantumValid = MessageSigner.verifyMLDSASignature(
557
+ keypair,
558
+ quantumMessage,
559
+ quantumSigned.signature,
560
+ );
561
+
562
+ console.log('ML-DSA Valid:', quantumValid);
563
+
564
+ // 2. Sign with Schnorr (Classical)
565
+ console.log('\n=== Schnorr Signing ===');
566
+ const classicalMessage = 'Classical signature';
567
+ const classicalSigned = MessageSigner.signMessage(wallet.keypair, classicalMessage);
568
+
569
+ console.log('Message:', classicalSigned.message);
570
+ console.log('Signature Size:', classicalSigned.signature.length, 'bytes');
571
+
572
+ // Verify Schnorr
573
+ const classicalValid = MessageSigner.verifySignature(
574
+ wallet.keypair.publicKey,
575
+ classicalMessage,
576
+ classicalSigned.signature,
577
+ );
578
+ console.log('Schnorr Valid:', classicalValid);
579
+
580
+ // 3. Multiple Input Formats
581
+ console.log('\n=== Input Format Tests ===');
582
+
583
+ const testMessage = 'Format test';
584
+
585
+ // String
586
+ const sig1 = MessageSigner.signMLDSAMessage(wallet.mldsaKeypair, testMessage);
587
+
588
+ // Buffer
589
+ const sig2 = MessageSigner.signMLDSAMessage(wallet.mldsaKeypair, Buffer.from(testMessage, 'utf-8'));
590
+
591
+ // Uint8Array
592
+ const sig3 = MessageSigner.signMLDSAMessage(
593
+ wallet.mldsaKeypair,
594
+ new Uint8Array(Buffer.from(testMessage, 'utf-8')),
595
+ );
596
+
597
+ // All verify successfully
598
+ console.log(
599
+ 'String format valid:',
600
+ MessageSigner.verifyMLDSASignature(wallet.mldsaKeypair, testMessage, sig1.signature),
601
+ );
602
+ console.log(
603
+ 'Buffer format valid:',
604
+ MessageSigner.verifyMLDSASignature(
605
+ wallet.mldsaKeypair,
606
+ Buffer.from(testMessage),
607
+ sig2.signature,
608
+ ),
609
+ );
610
+ console.log(
611
+ 'Uint8Array format valid:',
612
+ MessageSigner.verifyMLDSASignature(
613
+ wallet.mldsaKeypair,
614
+ new Uint8Array(Buffer.from(testMessage)),
615
+ sig3.signature,
616
+ ),
617
+ );
618
+ ```
619
+
620
+ ## Next Steps
621
+
622
+ - [Address Verification](./05-address-verification.md) - Validate addresses and public keys
623
+ - [Introduction](./01-introduction.md) - Back to overview