@smartledger/bsv 9.0.0 → 9.1.0

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/CHANGELOG.md +137 -0
  2. package/README.md +152 -1041
  3. package/STABILITY.md +134 -0
  4. package/bsv-gdaf.min.js +53 -48
  5. package/bsv-ltp.min.js +23 -18
  6. package/bsv-smartcontract.min.js +18 -18
  7. package/bsv.bundle.js +53 -48
  8. package/bsv.min.js +53 -48
  9. package/docs/MODULE_REFERENCE_COMPLETE.md +27 -27
  10. package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
  11. package/docs/getting-started/INSTALLATION.md +23 -23
  12. package/docs/getting-started/QUICK_START.md +7 -7
  13. package/docs/migration/FROM_BSV_1_5_6.md +5 -5
  14. package/docs/proposals/10.0.0-package-split.md +131 -0
  15. package/index.js +5 -0
  16. package/lib/block/merkleblock.js +19 -5
  17. package/lib/hdprivatekey.js +15 -0
  18. package/lib/script/interpreter.js +109 -1
  19. package/lib/smart_contract/builder.js +14 -0
  20. package/lib/util/deprecate.js +159 -0
  21. package/package.json +19 -82
  22. package/version.js +1 -1
  23. package/.mocharc.json +0 -5
  24. package/test/address.js +0 -629
  25. package/test/block/block.js +0 -239
  26. package/test/block/blockheader.js +0 -270
  27. package/test/block/merkleblock.js +0 -207
  28. package/test/build/bundle_crypto_shim.js +0 -104
  29. package/test/build/bundle_externals.js +0 -125
  30. package/test/build/bundle_smoke.js +0 -55
  31. package/test/build/esbuild_main.js +0 -65
  32. package/test/build/esm_wrapper.js +0 -97
  33. package/test/build/exports_resolution.js +0 -84
  34. package/test/build/version_sync.js +0 -14
  35. package/test/cli/smoke.js +0 -261
  36. package/test/consensus/base58-vectors.js +0 -120
  37. package/test/consensus/sv-script-vectors.js +0 -81
  38. package/test/consensus/sv-sighash-vectors.js +0 -51
  39. package/test/consensus/sv-tx-vectors.js +0 -48
  40. package/test/credentials-test.js +0 -332
  41. package/test/crypto/backend_selection.js +0 -126
  42. package/test/crypto/bn.js +0 -168
  43. package/test/crypto/ecdsa.js +0 -426
  44. package/test/crypto/elliptic-fixed.js +0 -61
  45. package/test/crypto/hash.browser.js +0 -121
  46. package/test/crypto/hash.js +0 -122
  47. package/test/crypto/point.js +0 -193
  48. package/test/crypto/random.js +0 -105
  49. package/test/crypto/security.js +0 -176
  50. package/test/crypto/shamir.js +0 -177
  51. package/test/crypto/shamir_rngcap.js +0 -29
  52. package/test/crypto/signature.js +0 -399
  53. package/test/data/bip69.json +0 -215
  54. package/test/data/bitcoin-sv/README.md +0 -170
  55. package/test/data/bitcoin-sv/base58_encode_decode.json +0 -14
  56. package/test/data/bitcoin-sv/base58_keys_invalid.json +0 -152
  57. package/test/data/bitcoin-sv/base58_keys_valid.json +0 -452
  58. package/test/data/bitcoin-sv/script_tests.json +0 -2591
  59. package/test/data/bitcoin-sv/sighash.json +0 -1003
  60. package/test/data/bitcoin-sv/tx_invalid.json +0 -285
  61. package/test/data/bitcoin-sv/tx_valid.json +0 -367
  62. package/test/data/bitcoind/base58_keys_invalid.json +0 -152
  63. package/test/data/bitcoind/base58_keys_valid.json +0 -452
  64. package/test/data/bitcoind/blocks.json +0 -27
  65. package/test/data/bitcoind/script_tests.json +0 -2244
  66. package/test/data/bitcoind/sig_canonical.json +0 -7
  67. package/test/data/bitcoind/sig_noncanonical.json +0 -22
  68. package/test/data/bitcoind/tx_invalid.json +0 -177
  69. package/test/data/bitcoind/tx_valid.json +0 -224
  70. package/test/data/blk86756-testnet.dat +0 -0
  71. package/test/data/blk86756-testnet.js +0 -12
  72. package/test/data/blk86756-testnet.json +0 -684
  73. package/test/data/brc220-batch-vector.json +0 -129
  74. package/test/data/ecdsa.json +0 -230
  75. package/test/data/merkleblocks.js +0 -486
  76. package/test/data/messages.json +0 -22
  77. package/test/data/sighash.json +0 -1004
  78. package/test/data/tx_creation.json +0 -85
  79. package/test/didweb/relationships.js +0 -144
  80. package/test/ecies/bitcore-ecies.js +0 -178
  81. package/test/ecies/electrum-ecies.js +0 -206
  82. package/test/encoding/base58.js +0 -131
  83. package/test/encoding/base58check.js +0 -145
  84. package/test/encoding/bufferreader.js +0 -328
  85. package/test/encoding/bufferwriter.js +0 -160
  86. package/test/encoding/varint.js +0 -104
  87. package/test/gdaf/anchor_no_key_leak.js +0 -146
  88. package/test/gdaf/anchor_spv.js +0 -163
  89. package/test/gdaf/canonicalization.js +0 -106
  90. package/test/gdaf/canonicalize.js +0 -140
  91. package/test/gdaf/zk_prover.js +0 -204
  92. package/test/hdkeys.js +0 -365
  93. package/test/hdprivatekey.js +0 -339
  94. package/test/hdpublickey.js +0 -293
  95. package/test/index.js +0 -16
  96. package/test/ltp/ids.js +0 -74
  97. package/test/ltp/right.js +0 -198
  98. package/test/ltp/verify_failclosed.js +0 -134
  99. package/test/message/message.js +0 -190
  100. package/test/mnemonic/data/fixtures.json +0 -300
  101. package/test/mnemonic/mnemonic.js +0 -277
  102. package/test/mnemonic/mocha.opts +0 -1
  103. package/test/mnemonic/pbkdf2.test.js +0 -43
  104. package/test/networks.js +0 -207
  105. package/test/notaryhash/batch_leaf.js +0 -140
  106. package/test/notaryhash/batch_vector.js +0 -282
  107. package/test/notaryhash/certificate.js +0 -249
  108. package/test/notaryhash/encoding.js +0 -186
  109. package/test/notaryhash/interop.js +0 -112
  110. package/test/notaryhash/merkle.js +0 -181
  111. package/test/notaryhash/script.js +0 -270
  112. package/test/notaryhash/verify.js +0 -342
  113. package/test/opcode.js +0 -186
  114. package/test/ordinals/bsv20.js +0 -337
  115. package/test/ordinals/inscription.js +0 -329
  116. package/test/ordinals/ordlock.js +0 -567
  117. package/test/privatekey.js +0 -540
  118. package/test/publickey.js +0 -411
  119. package/test/regressions.js +0 -215
  120. package/test/script/chronicle.js +0 -543
  121. package/test/script/defaults.js +0 -160
  122. package/test/script/genesis_limits.js +0 -203
  123. package/test/script/interpreter.js +0 -776
  124. package/test/script/script.js +0 -1259
  125. package/test/script/string_ops.js +0 -88
  126. package/test/security/fail_closed_contracts.js +0 -104
  127. package/test/security/threat_model_coverage.js +0 -31
  128. package/test/smart_contract/covenants.js +0 -207
  129. package/test/smart_contract/dsl_debugger.js +0 -92
  130. package/test/smart_contract/extract_field.js +0 -61
  131. package/test/smart_contract/nonenforcing_guard.js +0 -44
  132. package/test/smart_contract/ordinal_transfer.js +0 -71
  133. package/test/smart_contract/preimage.js +0 -98
  134. package/test/smart_contract/sighash_marketplace.js +0 -98
  135. package/test/smart_contract/token_generalized.js +0 -175
  136. package/test/spv/headerchain.js +0 -86
  137. package/test/spv/merkleproof.js +0 -133
  138. package/test/statuslist/failclosed.js +0 -78
  139. package/test/transaction/deserialize.js +0 -33
  140. package/test/transaction/input/input.js +0 -92
  141. package/test/transaction/input/multisig.js +0 -174
  142. package/test/transaction/input/multisigscripthash.js +0 -111
  143. package/test/transaction/input/publickey.js +0 -68
  144. package/test/transaction/input/publickeyhash.js +0 -59
  145. package/test/transaction/output.js +0 -185
  146. package/test/transaction/sighash.js +0 -91
  147. package/test/transaction/signature.js +0 -127
  148. package/test/transaction/transaction.js +0 -1299
  149. package/test/transaction/unspentoutput.js +0 -97
  150. package/test/types/dts_drift.js +0 -124
  151. package/test/types/surface_honesty.js +0 -102
  152. package/test/util/id.js +0 -72
  153. package/test/util/js.js +0 -76
  154. package/test/util/preconditions.js +0 -79
  155. package/test/vcjwt/interop.js +0 -126
@@ -1,122 +0,0 @@
1
- 'use strict'
2
-
3
- require('chai').should()
4
- var bsv = require('../..')
5
- var Hash = bsv.crypto.Hash
6
-
7
- describe('Hash', function () {
8
- var buf = Buffer.from([0, 1, 2, 3, 253, 254, 255])
9
- var str = 'test string'
10
-
11
- describe('@sha1', function () {
12
- it('calculates the hash of this buffer correctly', function () {
13
- var hash = Hash.sha1(buf)
14
- hash.toString('hex').should.equal('de69b8a4a5604d0486e6420db81e39eb464a17b2')
15
- hash = Hash.sha1(Buffer.alloc(0))
16
- hash.toString('hex').should.equal('da39a3ee5e6b4b0d3255bfef95601890afd80709')
17
- })
18
-
19
- it('throws an error when the input is not a buffer', function () {
20
- Hash.sha1.bind(Hash, str).should.throw('Invalid Argument')
21
- })
22
- })
23
-
24
- describe('#sha256', function () {
25
- it('calculates the hash of this buffer correctly', function () {
26
- var hash = Hash.sha256(buf)
27
- hash.toString('hex').should.equal('6f2c7b22fd1626998287b3636089087961091de80311b9279c4033ec678a83e8')
28
- })
29
-
30
- it('fails when the input is not a buffer', function () {
31
- Hash.sha256.bind(Hash, str).should.throw('Invalid Argument')
32
- })
33
- })
34
-
35
- describe('#sha256hmac', function () {
36
- it('computes this known big key correctly', function () {
37
- var key = Buffer.from('b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad' +
38
- 'b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad' +
39
- 'b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad' +
40
- 'b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad')
41
- var data = Buffer.from('')
42
- Hash.sha256hmac(data, key).toString('hex')
43
- .should.equal('fb1f87218671f1c0c4593a88498e02b6dfe8afd814c1729e89a1f1f6600faa23')
44
- })
45
-
46
- it('computes this known empty test vector correctly', function () {
47
- var key = Buffer.from('')
48
- var data = Buffer.from('')
49
- Hash.sha256hmac(data, key).toString('hex')
50
- .should.equal('b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad')
51
- })
52
-
53
- it('computes this known non-empty test vector correctly', function () {
54
- var key = Buffer.from('key')
55
- var data = Buffer.from('The quick brown fox jumps over the lazy dog')
56
- Hash.sha256hmac(data, key).toString('hex')
57
- .should.equal('f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8')
58
- })
59
- })
60
-
61
- describe('#sha256sha256', function () {
62
- it('calculates the hash of this buffer correctly', function () {
63
- var hash = Hash.sha256sha256(buf)
64
- hash.toString('hex').should.equal('be586c8b20dee549bdd66018c7a79e2b67bb88b7c7d428fa4c970976d2bec5ba')
65
- })
66
-
67
- it('fails when the input is not a buffer', function () {
68
- Hash.sha256sha256.bind(Hash, str).should.throw('Invalid Argument')
69
- })
70
- })
71
-
72
- describe('#sha256ripemd160', function () {
73
- it('calculates the hash of this buffer correctly', function () {
74
- var hash = Hash.sha256ripemd160(buf)
75
- hash.toString('hex').should.equal('7322e2bd8535e476c092934e16a6169ca9b707ec')
76
- })
77
-
78
- it('fails when the input is not a buffer', function () {
79
- Hash.sha256ripemd160.bind(Hash, str).should.throw('Invalid Argument')
80
- })
81
- })
82
-
83
- describe('#ripemd160', function () {
84
- it('calculates the hash of this buffer correctly', function () {
85
- var hash = Hash.ripemd160(buf)
86
- hash.toString('hex').should.equal('fa0f4565ff776fee0034c713cbf48b5ec06b7f5c')
87
- })
88
-
89
- it('fails when the input is not a buffer', function () {
90
- Hash.ripemd160.bind(Hash, str).should.throw('Invalid Argument')
91
- })
92
- })
93
-
94
- describe('#sha512', function () {
95
- it('calculates the hash of this buffer correctly', function () {
96
- var hash = Hash.sha512(buf)
97
- hash.toString('hex')
98
- .should.equal('c0530aa32048f4904ae162bc14b9eb535eab6c465e960130005fedd' +
99
- 'b71613e7d62aea75f7d3333ba06e805fc8e45681454524e3f8050969fe5a5f7f2392e31d0')
100
- })
101
-
102
- it('fails when the input is not a buffer', function () {
103
- Hash.sha512.bind(Hash, str).should.throw('Invalid Argument')
104
- })
105
- })
106
-
107
- describe('#sha512hmac', function () {
108
- it('calculates this known empty test vector correctly', function () {
109
- var hex = 'b936cee86c9f87aa5d3c6f2e84cb5a4239a5fe50480a6ec66b70ab5b1f4a' +
110
- 'c6730c6c515421b327ec1d69402e53dfb49ad7381eb067b338fd7b0cb22247225d47'
111
- Hash.sha512hmac(Buffer.from([]), Buffer.from([])).toString('hex').should.equal(hex)
112
- })
113
-
114
- it('calculates this known non-empty test vector correctly', function () {
115
- var hex = 'c40bd7c15aa493b309c940e08a73ffbd28b2e4cb729eb94480d727e4df577' +
116
- 'b13cc403a78e6150d83595f3b17c4cc331f12ca5952691de3735a63c1d4c69a2bac'
117
- var data = Buffer.from('test1')
118
- var key = Buffer.from('test2')
119
- Hash.sha512hmac(data, key).toString('hex').should.equal(hex)
120
- })
121
- })
122
- })
@@ -1,193 +0,0 @@
1
- 'use strict'
2
-
3
- var should = require('chai').should()
4
- var bsv = require('../..')
5
- var Point = bsv.crypto.Point
6
- var BN = bsv.crypto.BN
7
-
8
- describe('Point', function () {
9
- var valid = {
10
- x: 'ac242d242d23be966085a2b2b893d989f824e06c9ad0395a8a52f055ba39abb2',
11
- y: '4836ab292c105a711ed10fcfd30999c31ff7c02456147747e03e739ad527c380'
12
- }
13
-
14
- it('should create a point', function () {
15
- var p = Point(valid.x, valid.y)
16
- should.exist(p)
17
- })
18
-
19
- it('should create a point when called with "new"', function () {
20
- var p = new Point(valid.x, valid.y)
21
- should.exist(p)
22
- })
23
-
24
- describe('#getX', function () {
25
- it('should return x', function () {
26
- var p = Point(valid.x, valid.y)
27
- var x = p.getX()
28
- x.toString('hex', 64).should.equal(valid.x)
29
- })
30
-
31
- it('should be convertable to a buffer', function () {
32
- var p = Point(valid.x, valid.y)
33
- var a = p.getX().toBuffer({ size: 32 })
34
- a.length.should.equal(32)
35
- a.should.deep.equal(Buffer.from(valid.x, 'hex'))
36
- })
37
- })
38
-
39
- describe('#getY', function () {
40
- it('should return y', function () {
41
- var p = Point(valid.x, valid.y)
42
- p.getY().toString('hex', 64).should.equal(valid.y)
43
- })
44
-
45
- it('should be convertable to a buffer', function () {
46
- var p = Point(valid.x, valid.y)
47
- var a = p.getY().toBuffer({ size: 32 })
48
- a.length.should.equal(32)
49
- a.should.deep.equal(Buffer.from(valid.y, 'hex'))
50
- })
51
- })
52
-
53
- describe('#add', function () {
54
- it('should accurately add g to itself', function () {
55
- var p1 = Point.getG()
56
- var p2 = Point.getG()
57
- var p3 = p1.add(p2)
58
- p3.getX().toString().should.equal('89565891926547004231252920425935692360644145829622209' +
59
- '833684329913297188986597')
60
- p3.getY().toString().should.equal('12158399299693830322967808612713398636155367887041628' +
61
- '176798871954788371653930')
62
- })
63
- })
64
-
65
- describe('#mul', function () {
66
- it('should accurately multiply g by 2', function () {
67
- var g = Point.getG()
68
- var b = g.mul(new BN(2))
69
- b.getX().toString().should.equal('8956589192654700423125292042593569236064414582962220983' +
70
- '3684329913297188986597')
71
- b.getY().toString().should.equal('1215839929969383032296780861271339863615536788704162817' +
72
- '6798871954788371653930')
73
- })
74
-
75
- it('should accurately multiply g by n-1', function () {
76
- var g = Point.getG()
77
- var n = Point.getN()
78
- var b = g.mul(n.sub(new BN(1)))
79
- b.getX().toString().should.equal('55066263022277343669578718895168534326250603453777594175' +
80
- '500187360389116729240')
81
- b.getY().toString().should.equal('83121579216557378445487899878180864668798711284981320763' +
82
- '518679672151497189239')
83
- })
84
-
85
- // not sure if this is technically accurate or not...
86
- // normally, you should always multiply g by something less than n
87
- // but it is the same result in OpenSSL
88
- it('should accurately multiply g by n+1', function () {
89
- var g = Point.getG()
90
- var n = Point.getN()
91
- var b = g.mul(n.add(new BN(1)))
92
- b.getX().toString().should.equal('550662630222773436695787188951685343262506034537775941755' +
93
- '00187360389116729240')
94
- b.getY().toString().should.equal('326705100207588169780830851305070431844712733806592432759' +
95
- '38904335757337482424')
96
- })
97
- })
98
-
99
- describe('@fromX', function () {
100
- it('should return g', function () {
101
- var g = Point.getG()
102
- var p = Point.fromX(false, g.getX())
103
- g.eq(p).should.equal(true)
104
- })
105
- })
106
-
107
- describe('@pointToCompressed', function () {
108
- it('should return g', function () {
109
- let g = Point.getG()
110
- let pbuf = Point.pointToCompressed(g)
111
- pbuf.length.should.equal(33)
112
- pbuf.toString('hex').should.equal('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798')
113
- })
114
- })
115
-
116
- describe('#toBuffer', function () {
117
- it('should return g', function () {
118
- let g = Point.getG()
119
- let pbuf = g.toBuffer()
120
- pbuf.length.should.equal(33)
121
- pbuf.toString('hex').should.equal('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798')
122
- })
123
- })
124
-
125
- describe('@fromBuffer', function () {
126
- it('should return g', function () {
127
- let buf = Buffer.from('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 'hex')
128
- let p = Point.fromBuffer(buf)
129
- p.toBuffer().toString('hex').should.equal(buf.toString('hex'))
130
- })
131
- })
132
-
133
- describe('#toHex', function () {
134
- it('should return g', function () {
135
- let g = Point.getG()
136
- let phex = g.toHex()
137
- phex.length.should.equal(33 * 2)
138
- phex.should.equal('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798')
139
- })
140
- })
141
-
142
- describe('@fromHex', function () {
143
- it('should return g', function () {
144
- let hex = '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'
145
- let p = Point.fromHex(hex)
146
- p.toHex().should.equal(hex)
147
- })
148
- })
149
-
150
- describe('#validate', function () {
151
- it('should describe this point as valid', function () {
152
- var p = Point(valid.x, valid.y)
153
- should.exist(p.validate())
154
- })
155
-
156
- it('should describe this point as invalid because of zero y', function () {
157
- var x = 'ac242d242d23be966085a2b2b893d989f824e06c9ad0395a8a52f055ba39abb2'
158
- var y = '0000000000000000000000000000000000000000000000000000000000000000';
159
- (function () {
160
- Point(x, y)
161
- }).should.throw('Invalid y value for curve.')
162
- })
163
-
164
- it('should describe this point as invalid because of invalid y', function () {
165
- var x = 'ac242d242d23be966085a2b2b893d989f824e06c9ad0395a8a52f055ba39abb2'
166
- var y = '00000000000000000000000000000000000000000000000000000000000000FF';
167
- (function () {
168
- Point(x, y)
169
- }).should.throw('Invalid y value for curve.')
170
- })
171
-
172
- it('should describe this point as invalid because out of curve bounds', function () {
173
- // point larger than max
174
- var x = 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEDCE6AF48A03BBFD25E8CD0364141'
175
- // calculated y of x
176
- var y = 'ed3970f129bc2ca7c7c6cf92fa7da4de6a1dfc9c14da4bf056aa868d3dd74034';
177
-
178
- (function () {
179
- // set the point
180
- Point(x, y)
181
- }).should.throw('Point does not lie on the curve')
182
- })
183
-
184
- it('should describe this point as invalid because out of curve bounds', function () {
185
- var x = '0000000000000000000000000000000000000000000000000000000000000000';
186
-
187
- (function () {
188
- // set the point
189
- Point.fromX(false, x)
190
- }).should.throw('Invalid X')
191
- })
192
- })
193
- })
@@ -1,105 +0,0 @@
1
- 'use strict'
2
-
3
- var bsv = require('../..')
4
- var Random = bsv.crypto.Random
5
-
6
- describe('Random', function () {
7
- describe('@getRandomBuffer', function () {
8
- it('should return a buffer', function () {
9
- var bytes = Random.getRandomBuffer(8)
10
- bytes.length.should.equal(8)
11
- Buffer.isBuffer(bytes).should.equal(true)
12
- })
13
-
14
- it('should not equate two 256 bit random buffers', function () {
15
- var bytes1 = Random.getRandomBuffer(32)
16
- var bytes2 = Random.getRandomBuffer(32)
17
- bytes1.toString('hex').should.not.equal(bytes2.toString('hex'))
18
- })
19
-
20
- it('should generate 100 8 byte buffers in a row that are not equal', function () {
21
- var hexs = []
22
- for (var i = 0; i < 100; i++) {
23
- hexs[i] = Random.getRandomBuffer(8).toString('hex')
24
- }
25
- for (i = 0; i < 100; i++) {
26
- for (var j = i + 1; j < 100; j++) {
27
- hexs[i].should.not.equal(hexs[j])
28
- }
29
- }
30
- })
31
-
32
- // WebCrypto refuses more than 65,536 bytes per call. Before chunking, a request
33
- // above that limit threw; a naive implementation that ignored the return size
34
- // instead would hand back a zero-filled tail, which is far worse than throwing.
35
- it('fills requests larger than the 65536-byte getRandomValues limit', function () {
36
- var buf = Random.getRandomBuffer(70000)
37
- buf.length.should.equal(70000)
38
- // The tail comes from a second call — assert it is real entropy, not zero padding.
39
- var tail = buf.subarray(65536)
40
- tail.some(function (b) { return b !== 0 }).should.equal(true)
41
- buf.subarray(0, 32).toString('hex').should.not.equal(tail.subarray(0, 32).toString('hex'))
42
- })
43
-
44
- it('handles the exact limit and one past it', function () {
45
- Random.getRandomBuffer(65536).length.should.equal(65536)
46
- Random.getRandomBuffer(65537).length.should.equal(65537)
47
- })
48
-
49
- // The backend is chosen by feature detection. This used to branch on
50
- // `process.browser`, which is undefined in React Native, Deno, Workers and Bun —
51
- // all of which then fell through to require('crypto').randomBytes. Where a partial
52
- // crypto shim supplies a weak randomBytes, that produced guessable keys silently.
53
- it('does not depend on process.browser', function () {
54
- var saved = process.browser
55
- try {
56
- process.browser = undefined
57
- Random.getRandomBuffer(16).length.should.equal(16)
58
- process.browser = true
59
- Random.getRandomBuffer(16).length.should.equal(16)
60
- } finally {
61
- process.browser = saved
62
- }
63
- })
64
-
65
- it('prefers globalThis.crypto.getRandomValues when present', function () {
66
- var calls = 0
67
- var real = Object.getOwnPropertyDescriptor(globalThis, 'crypto')
68
- try {
69
- Object.defineProperty(globalThis, 'crypto', {
70
- configurable: true,
71
- value: {
72
- getRandomValues: function (arr) {
73
- calls++
74
- for (var i = 0; i < arr.length; i++) arr[i] = (i * 7 + 3) & 0xff
75
- return arr
76
- }
77
- }
78
- })
79
- var buf = Random.getRandomBuffer(4)
80
- calls.should.equal(1)
81
- buf.toString('hex').should.equal('030a1118')
82
- } finally {
83
- if (real) Object.defineProperty(globalThis, 'crypto', real)
84
- }
85
- })
86
-
87
- // The throw matters as much as the detection: a key library must never return bytes
88
- // it cannot vouch for. Verified in a child process because it has to remove both
89
- // backends, which cannot be undone safely in-process.
90
- it('throws rather than returning bytes when no CSPRNG exists', function () {
91
- var out = require('child_process').spawnSync(process.execPath, ['-e', [
92
- 'var Module = require("module"), orig = Module._load',
93
- 'delete globalThis.crypto',
94
- 'Module._load = function (r) {',
95
- ' if (r === "crypto") { var e = new Error("no crypto"); e.code = "MODULE_NOT_FOUND"; throw e }',
96
- ' return orig.apply(this, arguments)',
97
- '}',
98
- 'var R = require(' + JSON.stringify(require.resolve('../../lib/crypto/random.js')) + ')',
99
- 'try { R.getRandomBuffer(32); console.log("RETURNED") }',
100
- 'catch (e) { console.log("THREW") }'
101
- ].join('\n')], { encoding: 'utf8' })
102
- out.stdout.trim().should.equal('THREW')
103
- })
104
- })
105
- })
@@ -1,176 +0,0 @@
1
- 'use strict'
2
-
3
- /* global describe, it, before */
4
-
5
- require('chai').should()
6
- var expect = require('chai').expect
7
-
8
- var bsv = require('../../index.js')
9
- var BN = bsv.crypto.BN
10
- var ECDSA = bsv.crypto.ECDSA
11
- var Hash = bsv.crypto.Hash
12
- var Point = bsv.crypto.Point
13
- var Signature = bsv.crypto.Signature
14
- var SmartVerify = bsv.SmartVerify
15
-
16
- describe('SmartLedger Security Patches', function () {
17
- var privateKey, publicKey, message, hash
18
-
19
- before(function () {
20
- privateKey = new bsv.PrivateKey()
21
- publicKey = privateKey.toPublicKey()
22
- message = 'SmartLedger security test message'
23
- hash = Hash.sha256(Buffer.from(message))
24
- })
25
-
26
- describe('Zero Parameter Attack Protection', function () {
27
- it('Signature.validate() throws when r = 0', function () {
28
- var sig = new Signature({ r: new BN(0), s: new BN(1) })
29
- expect(function () { sig.validate() }).to.throw(/r component is zero/)
30
- })
31
-
32
- it('Signature.validate() throws when s = 0', function () {
33
- var sig = new Signature({ r: new BN(1), s: new BN(0) })
34
- expect(function () { sig.validate() }).to.throw(/s component is zero/)
35
- })
36
-
37
- it('smartVerify rejects (without throwing) a zero-s signature', function () {
38
- var sig = new Signature({ r: new BN(1), s: new BN(0) })
39
- SmartVerify.smartVerify(hash, sig, publicKey).should.equal(false)
40
- })
41
- })
42
-
43
- describe('Canonical Signature Enforcement', function () {
44
- it('freshly produced signatures are canonical (low-S)', function () {
45
- var sig = ECDSA.sign(hash, privateKey)
46
- sig.isCanonical().should.equal(true)
47
- SmartVerify.isCanonical(sig).should.equal(true)
48
- })
49
-
50
- it('detects a non-canonical (high-S) signature', function () {
51
- var sig = ECDSA.sign(hash, privateKey)
52
- var n = Point.getN()
53
- var lowS = sig.s.lte(n.shrn(1)) ? sig.s : n.sub(sig.s)
54
- var highS = new Signature({ r: sig.r, s: n.sub(lowS) })
55
-
56
- highS.isCanonical().should.equal(false)
57
- SmartVerify.isCanonical(highS).should.equal(false)
58
- })
59
-
60
- it('toCanonical() converts a high-S signature to canonical form', function () {
61
- var sig = ECDSA.sign(hash, privateKey)
62
- var n = Point.getN()
63
- var lowS = sig.s.lte(n.shrn(1)) ? sig.s : n.sub(sig.s)
64
- var highS = new Signature({ r: sig.r, s: n.sub(lowS) })
65
-
66
- var canonical = highS.toCanonical()
67
- canonical.isCanonical().should.equal(true)
68
- // Both forms verify (ECDSA is malleable in s); canonicalization does not
69
- // change which key/message the signature is valid for.
70
- canonical.r.cmp(highS.r).should.equal(0)
71
- })
72
-
73
- it('toCanonical() returns a new signature and leaves the original alone', function () {
74
- var sig = ECDSA.sign(hash, privateKey)
75
- var n = Point.getN()
76
- var lowS = sig.s.lte(n.shrn(1)) ? sig.s : n.sub(sig.s)
77
- var highS = new Signature({ r: sig.r, s: n.sub(lowS) })
78
- var before = highS.s.toString()
79
-
80
- var canonical = highS.toCanonical()
81
- canonical.should.not.equal(highS)
82
- highS.s.toString().should.equal(before)
83
- })
84
- })
85
-
86
- describe('applySecurityPatches', function () {
87
- var highSig = function () {
88
- var sig = ECDSA.sign(hash, privateKey)
89
- var n = Point.getN()
90
- var lowS = sig.s.lte(n.shrn(1)) ? sig.s : n.sub(sig.s)
91
- return new Signature({ r: sig.r, s: n.sub(lowS) })
92
- }
93
-
94
- it('accepts a canonical signature and returns it for chaining', function () {
95
- var sig = ECDSA.sign(hash, privateKey)
96
- sig.applySecurityPatches().should.equal(sig)
97
- })
98
-
99
- it('rejects a non-canonical (high-S) signature rather than rewriting it', function () {
100
- // Rewriting s to n-s cannot protect against malleability: the rewritten
101
- // signature verifies exactly as the original, so silently normalizing only
102
- // hides from the caller that the signature was malleated.
103
- var highS = highSig()
104
- var before = highS.s.toString()
105
-
106
- expect(function () { highS.applySecurityPatches() }).to.throw(/non-canonical/)
107
- highS.s.toString().should.equal(before)
108
- })
109
-
110
- it('rejects zero and out-of-range components', function () {
111
- expect(function () {
112
- new Signature({ r: new BN(0), s: new BN(1) }).applySecurityPatches()
113
- }).to.throw(/zero r or s/)
114
- expect(function () {
115
- new Signature({ r: new BN(1), s: Point.getN() }).applySecurityPatches()
116
- }).to.throw(/out of range/)
117
- })
118
- })
119
-
120
- describe('SmartVerify Enhanced Validation', function () {
121
- it('accepts a valid signature', function () {
122
- var sig = ECDSA.sign(hash, privateKey)
123
- SmartVerify.smartVerify(hash, sig, publicKey).should.equal(true)
124
- })
125
-
126
- it('rejects a malleated (high-S) signature', function () {
127
- var sig = ECDSA.sign(hash, privateKey)
128
- var n = Point.getN()
129
- var lowS = sig.s.lte(n.shrn(1)) ? sig.s : n.sub(sig.s)
130
- var highS = new Signature({ r: sig.r, s: n.sub(lowS) })
131
- SmartVerify.isCanonical(highS).should.equal(false)
132
- SmartVerify.smartVerify(hash, highS, publicKey).should.equal(false)
133
- // ...while the canonical form of the same signature still verifies.
134
- SmartVerify.smartVerify(hash, new Signature({ r: sig.r, s: lowS }), publicKey).should.equal(true)
135
- })
136
-
137
- it('throws on an invalid (non-32-byte) message hash', function () {
138
- var sig = ECDSA.sign(hash, privateKey)
139
- var shortHash = Buffer.alloc(16)
140
- expect(function () {
141
- SmartVerify.smartVerify(shortHash, sig, publicKey)
142
- }).to.throw(/32-byte/)
143
- })
144
-
145
- it('rejects a signature from the wrong key', function () {
146
- var sig = ECDSA.sign(hash, privateKey)
147
- var otherPub = new bsv.PrivateKey().toPublicKey()
148
- SmartVerify.smartVerify(hash, sig, otherPub).should.equal(false)
149
- })
150
- })
151
-
152
- describe('Integration with Original BSV', function () {
153
- it('round-trips a Bitcoin message signature', function () {
154
- var sig = new bsv.Message(message).sign(privateKey)
155
- var verified = new bsv.Message(message).verify(publicKey.toAddress().toString(), sig)
156
- verified.should.equal(true)
157
- })
158
-
159
- it('signs a transaction to completion', function () {
160
- var utxo = {
161
- txId: 'a'.repeat(64),
162
- outputIndex: 0,
163
- address: privateKey.toAddress().toString(),
164
- script: bsv.Script.buildPublicKeyHashOut(privateKey.toAddress()).toHex(),
165
- satoshis: 100000
166
- }
167
-
168
- var transaction = new bsv.Transaction()
169
- .from(utxo)
170
- .to(privateKey.toAddress(), 50000)
171
- .sign(privateKey)
172
-
173
- transaction.isFullySigned().should.equal(true)
174
- })
175
- })
176
- })