@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.
- package/CHANGELOG.md +137 -0
- package/README.md +152 -1041
- package/STABILITY.md +134 -0
- package/bsv-gdaf.min.js +53 -48
- package/bsv-ltp.min.js +23 -18
- package/bsv-smartcontract.min.js +18 -18
- package/bsv.bundle.js +53 -48
- package/bsv.min.js +53 -48
- package/docs/MODULE_REFERENCE_COMPLETE.md +27 -27
- package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
- package/docs/getting-started/INSTALLATION.md +23 -23
- package/docs/getting-started/QUICK_START.md +7 -7
- package/docs/migration/FROM_BSV_1_5_6.md +5 -5
- package/docs/proposals/10.0.0-package-split.md +131 -0
- package/index.js +5 -0
- package/lib/block/merkleblock.js +19 -5
- package/lib/hdprivatekey.js +15 -0
- package/lib/script/interpreter.js +109 -1
- package/lib/smart_contract/builder.js +14 -0
- package/lib/util/deprecate.js +159 -0
- package/package.json +19 -82
- package/version.js +1 -1
- package/.mocharc.json +0 -5
- package/test/address.js +0 -629
- package/test/block/block.js +0 -239
- package/test/block/blockheader.js +0 -270
- package/test/block/merkleblock.js +0 -207
- package/test/build/bundle_crypto_shim.js +0 -104
- package/test/build/bundle_externals.js +0 -125
- package/test/build/bundle_smoke.js +0 -55
- package/test/build/esbuild_main.js +0 -65
- package/test/build/esm_wrapper.js +0 -97
- package/test/build/exports_resolution.js +0 -84
- package/test/build/version_sync.js +0 -14
- package/test/cli/smoke.js +0 -261
- package/test/consensus/base58-vectors.js +0 -120
- package/test/consensus/sv-script-vectors.js +0 -81
- package/test/consensus/sv-sighash-vectors.js +0 -51
- package/test/consensus/sv-tx-vectors.js +0 -48
- package/test/credentials-test.js +0 -332
- package/test/crypto/backend_selection.js +0 -126
- package/test/crypto/bn.js +0 -168
- package/test/crypto/ecdsa.js +0 -426
- package/test/crypto/elliptic-fixed.js +0 -61
- package/test/crypto/hash.browser.js +0 -121
- package/test/crypto/hash.js +0 -122
- package/test/crypto/point.js +0 -193
- package/test/crypto/random.js +0 -105
- package/test/crypto/security.js +0 -176
- package/test/crypto/shamir.js +0 -177
- package/test/crypto/shamir_rngcap.js +0 -29
- package/test/crypto/signature.js +0 -399
- package/test/data/bip69.json +0 -215
- package/test/data/bitcoin-sv/README.md +0 -170
- package/test/data/bitcoin-sv/base58_encode_decode.json +0 -14
- package/test/data/bitcoin-sv/base58_keys_invalid.json +0 -152
- package/test/data/bitcoin-sv/base58_keys_valid.json +0 -452
- package/test/data/bitcoin-sv/script_tests.json +0 -2591
- package/test/data/bitcoin-sv/sighash.json +0 -1003
- package/test/data/bitcoin-sv/tx_invalid.json +0 -285
- package/test/data/bitcoin-sv/tx_valid.json +0 -367
- package/test/data/bitcoind/base58_keys_invalid.json +0 -152
- package/test/data/bitcoind/base58_keys_valid.json +0 -452
- package/test/data/bitcoind/blocks.json +0 -27
- package/test/data/bitcoind/script_tests.json +0 -2244
- package/test/data/bitcoind/sig_canonical.json +0 -7
- package/test/data/bitcoind/sig_noncanonical.json +0 -22
- package/test/data/bitcoind/tx_invalid.json +0 -177
- package/test/data/bitcoind/tx_valid.json +0 -224
- package/test/data/blk86756-testnet.dat +0 -0
- package/test/data/blk86756-testnet.js +0 -12
- package/test/data/blk86756-testnet.json +0 -684
- package/test/data/brc220-batch-vector.json +0 -129
- package/test/data/ecdsa.json +0 -230
- package/test/data/merkleblocks.js +0 -486
- package/test/data/messages.json +0 -22
- package/test/data/sighash.json +0 -1004
- package/test/data/tx_creation.json +0 -85
- package/test/didweb/relationships.js +0 -144
- package/test/ecies/bitcore-ecies.js +0 -178
- package/test/ecies/electrum-ecies.js +0 -206
- package/test/encoding/base58.js +0 -131
- package/test/encoding/base58check.js +0 -145
- package/test/encoding/bufferreader.js +0 -328
- package/test/encoding/bufferwriter.js +0 -160
- package/test/encoding/varint.js +0 -104
- package/test/gdaf/anchor_no_key_leak.js +0 -146
- package/test/gdaf/anchor_spv.js +0 -163
- package/test/gdaf/canonicalization.js +0 -106
- package/test/gdaf/canonicalize.js +0 -140
- package/test/gdaf/zk_prover.js +0 -204
- package/test/hdkeys.js +0 -365
- package/test/hdprivatekey.js +0 -339
- package/test/hdpublickey.js +0 -293
- package/test/index.js +0 -16
- package/test/ltp/ids.js +0 -74
- package/test/ltp/right.js +0 -198
- package/test/ltp/verify_failclosed.js +0 -134
- package/test/message/message.js +0 -190
- package/test/mnemonic/data/fixtures.json +0 -300
- package/test/mnemonic/mnemonic.js +0 -277
- package/test/mnemonic/mocha.opts +0 -1
- package/test/mnemonic/pbkdf2.test.js +0 -43
- package/test/networks.js +0 -207
- package/test/notaryhash/batch_leaf.js +0 -140
- package/test/notaryhash/batch_vector.js +0 -282
- package/test/notaryhash/certificate.js +0 -249
- package/test/notaryhash/encoding.js +0 -186
- package/test/notaryhash/interop.js +0 -112
- package/test/notaryhash/merkle.js +0 -181
- package/test/notaryhash/script.js +0 -270
- package/test/notaryhash/verify.js +0 -342
- package/test/opcode.js +0 -186
- package/test/ordinals/bsv20.js +0 -337
- package/test/ordinals/inscription.js +0 -329
- package/test/ordinals/ordlock.js +0 -567
- package/test/privatekey.js +0 -540
- package/test/publickey.js +0 -411
- package/test/regressions.js +0 -215
- package/test/script/chronicle.js +0 -543
- package/test/script/defaults.js +0 -160
- package/test/script/genesis_limits.js +0 -203
- package/test/script/interpreter.js +0 -776
- package/test/script/script.js +0 -1259
- package/test/script/string_ops.js +0 -88
- package/test/security/fail_closed_contracts.js +0 -104
- package/test/security/threat_model_coverage.js +0 -31
- package/test/smart_contract/covenants.js +0 -207
- package/test/smart_contract/dsl_debugger.js +0 -92
- package/test/smart_contract/extract_field.js +0 -61
- package/test/smart_contract/nonenforcing_guard.js +0 -44
- package/test/smart_contract/ordinal_transfer.js +0 -71
- package/test/smart_contract/preimage.js +0 -98
- package/test/smart_contract/sighash_marketplace.js +0 -98
- package/test/smart_contract/token_generalized.js +0 -175
- package/test/spv/headerchain.js +0 -86
- package/test/spv/merkleproof.js +0 -133
- package/test/statuslist/failclosed.js +0 -78
- package/test/transaction/deserialize.js +0 -33
- package/test/transaction/input/input.js +0 -92
- package/test/transaction/input/multisig.js +0 -174
- package/test/transaction/input/multisigscripthash.js +0 -111
- package/test/transaction/input/publickey.js +0 -68
- package/test/transaction/input/publickeyhash.js +0 -59
- package/test/transaction/output.js +0 -185
- package/test/transaction/sighash.js +0 -91
- package/test/transaction/signature.js +0 -127
- package/test/transaction/transaction.js +0 -1299
- package/test/transaction/unspentoutput.js +0 -97
- package/test/types/dts_drift.js +0 -124
- package/test/types/surface_honesty.js +0 -102
- package/test/util/id.js +0 -72
- package/test/util/js.js +0 -76
- package/test/util/preconditions.js +0 -79
- package/test/vcjwt/interop.js +0 -126
package/test/credentials-test.js
DELETED
|
@@ -1,332 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test Vectors for DID:web + VC-JWT + StatusList2021
|
|
3
|
-
* Comprehensive test suite for v3.4.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
'use strict'
|
|
7
|
-
|
|
8
|
-
var didweb = require('../lib/didweb')
|
|
9
|
-
var vcjwt = require('../lib/vcjwt')
|
|
10
|
-
var statuslist = require('../lib/statuslist')
|
|
11
|
-
var anchor = require('../lib/anchor')
|
|
12
|
-
var assert = require('assert')
|
|
13
|
-
|
|
14
|
-
console.log('🧪 SmartLedger BSV v3.4.0 - Credential Test Suite\n')
|
|
15
|
-
|
|
16
|
-
// Test 1: DID:web Key Generation (ES256)
|
|
17
|
-
async function testES256KeyGeneration() {
|
|
18
|
-
console.log('1️⃣ Testing ES256 key generation...')
|
|
19
|
-
|
|
20
|
-
var keys = await didweb.generateIssuerKeys({ alg: 'ES256' })
|
|
21
|
-
|
|
22
|
-
assert(keys.privateJwk, 'Private JWK should exist')
|
|
23
|
-
assert(keys.publicJwk, 'Public JWK should exist')
|
|
24
|
-
assert.strictEqual(keys.alg, 'ES256', 'Algorithm should be ES256')
|
|
25
|
-
assert(keys.kid, 'Key ID should exist')
|
|
26
|
-
assert.strictEqual(keys.publicJwk.kty, 'EC', 'Key type should be EC')
|
|
27
|
-
assert.strictEqual(keys.publicJwk.crv, 'P-256', 'Curve should be P-256')
|
|
28
|
-
|
|
29
|
-
console.log(' ✅ ES256 key generation successful')
|
|
30
|
-
console.log(' ✅ Kid:', keys.kid)
|
|
31
|
-
return keys
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Test 2: DID:web Key Generation (ES256K)
|
|
35
|
-
async function testES256KKeyGeneration() {
|
|
36
|
-
console.log('\n2️⃣ Testing ES256K key generation...')
|
|
37
|
-
|
|
38
|
-
var keys = await didweb.generateIssuerKeys({ alg: 'ES256K' })
|
|
39
|
-
|
|
40
|
-
assert(keys.privateJwk, 'Private JWK should exist')
|
|
41
|
-
assert(keys.publicJwk, 'Public JWK should exist')
|
|
42
|
-
assert.strictEqual(keys.alg, 'ES256K', 'Algorithm should be ES256K')
|
|
43
|
-
assert(keys.kid, 'Key ID should exist')
|
|
44
|
-
assert.strictEqual(keys.publicJwk.kty, 'EC', 'Key type should be EC')
|
|
45
|
-
assert.strictEqual(keys.publicJwk.crv, 'secp256k1', 'Curve should be secp256k1')
|
|
46
|
-
|
|
47
|
-
console.log(' ✅ ES256K key generation successful')
|
|
48
|
-
console.log(' ✅ Kid:', keys.kid)
|
|
49
|
-
return keys
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Test 3: DID:web Document Building
|
|
53
|
-
async function testDIDDocumentBuilding(p256Keys) {
|
|
54
|
-
console.log('\n3️⃣ Testing DID:web document building...')
|
|
55
|
-
|
|
56
|
-
var docs = didweb.buildDidWebDocuments({
|
|
57
|
-
domain: 'smartledger.technology',
|
|
58
|
-
p256: { jwk: p256Keys.publicJwk, kid: p256Keys.kid },
|
|
59
|
-
controllerName: 'SmartLedger Test Issuer'
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
assert.strictEqual(docs.did, 'did:web:smartledger.technology', 'DID should be correctly formatted')
|
|
63
|
-
assert(docs.didDocument, 'DID Document should exist')
|
|
64
|
-
assert(docs.jwks, 'JWKS should exist')
|
|
65
|
-
assert(docs.didDocument.verificationMethod.length > 0, 'Should have verification methods')
|
|
66
|
-
assert(docs.jwks.keys.length > 0, 'JWKS should have keys')
|
|
67
|
-
|
|
68
|
-
console.log(' ✅ DID:', docs.did)
|
|
69
|
-
console.log(' ✅ Verification methods:', docs.didDocument.verificationMethod.length)
|
|
70
|
-
console.log(' ✅ JWKS keys:', docs.jwks.keys.length)
|
|
71
|
-
|
|
72
|
-
return docs
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Test 4: VC-JWT Issuance (ES256)
|
|
76
|
-
async function testVCIssuanceES256(issuerDid, keys) {
|
|
77
|
-
console.log('\n4️⃣ Testing VC-JWT issuance (ES256)...')
|
|
78
|
-
|
|
79
|
-
var result = await vcjwt.issueVcJwt({
|
|
80
|
-
issuerDid: issuerDid,
|
|
81
|
-
subjectId: 'did:example:holder123',
|
|
82
|
-
types: ['VerifiableCredential', 'AgeCredential'],
|
|
83
|
-
credentialSubject: {
|
|
84
|
-
ageOver: 18,
|
|
85
|
-
country: 'US'
|
|
86
|
-
},
|
|
87
|
-
privateJwk: keys.privateJwk,
|
|
88
|
-
alg: 'ES256',
|
|
89
|
-
kid: keys.kid
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
assert(result.jwt, 'JWT should be generated')
|
|
93
|
-
assert(result.jwt.split('.').length === 3, 'JWT should have 3 parts')
|
|
94
|
-
|
|
95
|
-
console.log(' ✅ JWT generated')
|
|
96
|
-
console.log(' ✅ JWT length:', result.jwt.length)
|
|
97
|
-
|
|
98
|
-
return result.jwt
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Test 5: VC-JWT Verification
|
|
102
|
-
async function testVCVerification(jwt, jwks) {
|
|
103
|
-
console.log('\n5️⃣ Testing VC-JWT verification...')
|
|
104
|
-
|
|
105
|
-
var didResolver = async function(did) {
|
|
106
|
-
return { jwks: jwks }
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
var result = await vcjwt.verifyVcJwt(jwt, {
|
|
110
|
-
didResolver: didResolver,
|
|
111
|
-
expectedIssuerDid: 'did:web:smartledger.technology'
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
assert.strictEqual(result.valid, true, 'JWT should be valid')
|
|
115
|
-
assert(result.payload, 'Payload should be present')
|
|
116
|
-
assert(result.header, 'Header should be present')
|
|
117
|
-
|
|
118
|
-
console.log(' ✅ JWT verification successful')
|
|
119
|
-
console.log(' ✅ Issuer:', result.payload.iss)
|
|
120
|
-
console.log(' ✅ Subject:', result.payload.sub)
|
|
121
|
-
|
|
122
|
-
return result
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Test 6: StatusList2021 Creation
|
|
126
|
-
async function testStatusListCreation(issuerDid, keys) {
|
|
127
|
-
console.log('\n6️⃣ Testing StatusList2021 creation...')
|
|
128
|
-
|
|
129
|
-
var result = await statuslist.createStatusList({
|
|
130
|
-
issuerDid: issuerDid,
|
|
131
|
-
privateJwk: keys.privateJwk
|
|
132
|
-
})
|
|
133
|
-
|
|
134
|
-
assert(result.listVcJwt, 'Status list JWT should be created')
|
|
135
|
-
assert(result.listId, 'List ID should be created')
|
|
136
|
-
|
|
137
|
-
console.log(' ✅ Status list created')
|
|
138
|
-
console.log(' ✅ List ID:', result.listId)
|
|
139
|
-
|
|
140
|
-
return result.listVcJwt
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Test 7: StatusList2021 Update (Revocation)
|
|
144
|
-
async function testStatusListRevocation(listJwt, keys, issuerDid, jwks) {
|
|
145
|
-
console.log('\n7️⃣ Testing credential revocation...')
|
|
146
|
-
|
|
147
|
-
var index = 42
|
|
148
|
-
var didResolver = async function() { return { jwks: jwks } }
|
|
149
|
-
var verifyOpts = { expectedIssuerDid: issuerDid, didResolver: didResolver }
|
|
150
|
-
|
|
151
|
-
// Check initial status
|
|
152
|
-
var initialStatus = await statuslist.getCredentialStatusEntry(Object.assign({
|
|
153
|
-
listVcJwt: listJwt,
|
|
154
|
-
index: index
|
|
155
|
-
}, verifyOpts))
|
|
156
|
-
|
|
157
|
-
assert.strictEqual(initialStatus, 'valid', 'Initial status should be valid')
|
|
158
|
-
console.log(' ✅ Initial status at index', index + ':', initialStatus)
|
|
159
|
-
|
|
160
|
-
// Revoke credential
|
|
161
|
-
var result = await statuslist.updateStatusList(Object.assign({
|
|
162
|
-
listVcJwt: listJwt,
|
|
163
|
-
index: index,
|
|
164
|
-
status: 'revoked',
|
|
165
|
-
privateJwk: keys.privateJwk
|
|
166
|
-
}, verifyOpts))
|
|
167
|
-
|
|
168
|
-
assert(result.listVcJwt, 'Updated list should be returned')
|
|
169
|
-
|
|
170
|
-
// Check updated status
|
|
171
|
-
var updatedStatus = await statuslist.getCredentialStatusEntry(Object.assign({
|
|
172
|
-
listVcJwt: result.listVcJwt,
|
|
173
|
-
index: index
|
|
174
|
-
}, verifyOpts))
|
|
175
|
-
|
|
176
|
-
assert.strictEqual(updatedStatus, 'revoked', 'Status should be revoked')
|
|
177
|
-
console.log(' ✅ Updated status at index', index + ':', updatedStatus)
|
|
178
|
-
|
|
179
|
-
return result.listVcJwt
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// Test 8: Anchor Hash Generation
|
|
183
|
-
function testAnchorHashing() {
|
|
184
|
-
console.log('\n8️⃣ Testing anchor hash generation...')
|
|
185
|
-
|
|
186
|
-
var testData = 'Test Verifiable Credential Data'
|
|
187
|
-
var hash = anchor.sha256Hex(testData)
|
|
188
|
-
|
|
189
|
-
assert(hash, 'Hash should be generated')
|
|
190
|
-
assert.strictEqual(hash.length, 64, 'Hash should be 64 hex characters')
|
|
191
|
-
assert(/^[a-f0-9]{64}$/.test(hash), 'Hash should be valid hex')
|
|
192
|
-
|
|
193
|
-
console.log(' ✅ SHA-256 hash generated')
|
|
194
|
-
console.log(' ✅ Hash:', hash)
|
|
195
|
-
|
|
196
|
-
// Test hash reproducibility
|
|
197
|
-
var hash2 = anchor.sha256Hex(testData)
|
|
198
|
-
assert.strictEqual(hash, hash2, 'Hash should be reproducible')
|
|
199
|
-
console.log(' ✅ Hash reproducibility confirmed')
|
|
200
|
-
|
|
201
|
-
return hash
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Test 9: Anchor Payload Building
|
|
205
|
-
function testAnchorPayload(hash, issuerDid) {
|
|
206
|
-
console.log('\n9️⃣ Testing anchor payload building...')
|
|
207
|
-
|
|
208
|
-
var payload = anchor.buildAnchorPayload({
|
|
209
|
-
kind: 'VC_ANCHOR_SHA256',
|
|
210
|
-
hash: hash,
|
|
211
|
-
issuerDid: issuerDid,
|
|
212
|
-
issuedAt: new Date().toISOString()
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
assert(payload.json, 'Payload JSON should be generated')
|
|
216
|
-
|
|
217
|
-
var parsed = JSON.parse(payload.json)
|
|
218
|
-
assert.strictEqual(parsed.protocol, 'SmartLedger', 'Protocol should be SmartLedger')
|
|
219
|
-
assert.strictEqual(parsed.type, 'VC_ANCHOR_SHA256', 'Type should match')
|
|
220
|
-
assert.strictEqual(parsed.hash, hash, 'Hash should match')
|
|
221
|
-
assert.strictEqual(parsed.issuer, issuerDid, 'Issuer should match')
|
|
222
|
-
|
|
223
|
-
console.log(' ✅ Anchor payload created')
|
|
224
|
-
console.log(' ✅ Size:', payload.json.length, 'bytes')
|
|
225
|
-
console.log(' ✅ Protocol:', parsed.protocol)
|
|
226
|
-
|
|
227
|
-
return payload
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// Test 10: End-to-end Workflow
|
|
231
|
-
async function testEndToEndWorkflow() {
|
|
232
|
-
console.log('\n🔟 Testing complete end-to-end workflow...')
|
|
233
|
-
|
|
234
|
-
// Generate keys
|
|
235
|
-
var keys = await didweb.generateIssuerKeys({ alg: 'ES256' })
|
|
236
|
-
|
|
237
|
-
// Build DID documents
|
|
238
|
-
var docs = didweb.buildDidWebDocuments({
|
|
239
|
-
domain: 'test.example.com',
|
|
240
|
-
p256: { jwk: keys.publicJwk, kid: keys.kid }
|
|
241
|
-
})
|
|
242
|
-
|
|
243
|
-
// Issue credential
|
|
244
|
-
var result = await vcjwt.issueVcJwt({
|
|
245
|
-
issuerDid: docs.did,
|
|
246
|
-
subjectId: 'did:example:alice',
|
|
247
|
-
types: ['VerifiableCredential', 'DriverLicense'],
|
|
248
|
-
credentialSubject: {
|
|
249
|
-
licenseNumber: 'DL123456',
|
|
250
|
-
class: 'C'
|
|
251
|
-
},
|
|
252
|
-
privateJwk: keys.privateJwk,
|
|
253
|
-
alg: 'ES256',
|
|
254
|
-
kid: keys.kid
|
|
255
|
-
})
|
|
256
|
-
var jwt = result.jwt
|
|
257
|
-
|
|
258
|
-
// Hash credential for anchoring
|
|
259
|
-
var hash = anchor.sha256Hex(jwt)
|
|
260
|
-
|
|
261
|
-
// Build anchor payload
|
|
262
|
-
var anchorPayload = anchor.buildAnchorPayload({
|
|
263
|
-
kind: 'VC_ANCHOR_SHA256',
|
|
264
|
-
hash: hash,
|
|
265
|
-
issuerDid: docs.did
|
|
266
|
-
})
|
|
267
|
-
|
|
268
|
-
// Verify credential
|
|
269
|
-
var didResolver = async function() { return { jwks: docs.jwks } }
|
|
270
|
-
var verification = await vcjwt.verifyVcJwt(jwt, { didResolver: didResolver })
|
|
271
|
-
|
|
272
|
-
assert.strictEqual(verification.valid, true, 'Credential should be valid')
|
|
273
|
-
|
|
274
|
-
// Create status list
|
|
275
|
-
var statusListResult = await statuslist.createStatusList({
|
|
276
|
-
issuerDid: docs.did,
|
|
277
|
-
privateJwk: keys.privateJwk
|
|
278
|
-
})
|
|
279
|
-
|
|
280
|
-
// Revoke credential
|
|
281
|
-
var statusVerifyOpts = { expectedIssuerDid: docs.did, didResolver: didResolver }
|
|
282
|
-
var updatedList = await statuslist.updateStatusList(Object.assign({
|
|
283
|
-
listVcJwt: statusListResult.listVcJwt,
|
|
284
|
-
index: 10,
|
|
285
|
-
status: 'revoked',
|
|
286
|
-
privateJwk: keys.privateJwk
|
|
287
|
-
}, statusVerifyOpts))
|
|
288
|
-
|
|
289
|
-
// Verify credential is now revoked
|
|
290
|
-
var verification2 = await vcjwt.verifyVcJwt(jwt, { didResolver: didResolver })
|
|
291
|
-
var revokedStatus = await statuslist.getCredentialStatusEntry(Object.assign({
|
|
292
|
-
listVcJwt: updatedList.listVcJwt,
|
|
293
|
-
index: 10
|
|
294
|
-
}, statusVerifyOpts))
|
|
295
|
-
|
|
296
|
-
assert.strictEqual(verification2.valid, true, 'JWT signature still valid')
|
|
297
|
-
assert.strictEqual(revokedStatus, 'revoked', 'But credential is revoked')
|
|
298
|
-
|
|
299
|
-
console.log(' ✅ Complete workflow executed successfully')
|
|
300
|
-
console.log(' ✅ Issue → Anchor → Verify → Revoke → Verify')
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// Run all tests
|
|
304
|
-
async function runTests() {
|
|
305
|
-
try {
|
|
306
|
-
var p256Keys = await testES256KeyGeneration()
|
|
307
|
-
var k1Keys = await testES256KKeyGeneration()
|
|
308
|
-
var docs = await testDIDDocumentBuilding(p256Keys)
|
|
309
|
-
var jwt = await testVCIssuanceES256(docs.did, p256Keys)
|
|
310
|
-
var verification = await testVCVerification(jwt, docs.jwks)
|
|
311
|
-
var statusListJwt = await testStatusListCreation(docs.did, p256Keys)
|
|
312
|
-
var revokedListJwt = await testStatusListRevocation(statusListJwt, p256Keys, docs.did, docs.jwks)
|
|
313
|
-
var hash = testAnchorHashing()
|
|
314
|
-
var anchorPayload = testAnchorPayload(hash, docs.did)
|
|
315
|
-
await testEndToEndWorkflow()
|
|
316
|
-
|
|
317
|
-
console.log('\n🎉 All tests passed successfully!')
|
|
318
|
-
console.log('✅ DID:web generation working')
|
|
319
|
-
console.log('✅ VC-JWT issuance and verification working')
|
|
320
|
-
console.log('✅ StatusList2021 revocation working')
|
|
321
|
-
console.log('✅ BSV anchor hashing working')
|
|
322
|
-
console.log('✅ ES256 and ES256K support confirmed')
|
|
323
|
-
|
|
324
|
-
} catch (error) {
|
|
325
|
-
console.error('\n❌ Test failed:', error.message)
|
|
326
|
-
console.error(error.stack)
|
|
327
|
-
process.exit(1)
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// Run the test suite
|
|
332
|
-
runTests()
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
/* global describe, it */
|
|
4
|
-
|
|
5
|
-
// The hashing and PBKDF2 backends are chosen by CAPABILITY, not by `process.browser`.
|
|
6
|
-
//
|
|
7
|
-
// `process.browser` is a Browserify-era convention, undefined in React Native, Deno,
|
|
8
|
-
// Cloudflare Workers and Bun. Every one of those took the node branch and
|
|
9
|
-
// require('crypto')'d, which fails outright in React Native or — worse — resolves to a
|
|
10
|
-
// partial shim. rn-nodeify and several RN starter templates register exactly such a
|
|
11
|
-
// shim, so this is a reported failure mode, not a hypothetical one.
|
|
12
|
-
//
|
|
13
|
-
// Each case runs in a child process because it has to intercept module resolution
|
|
14
|
-
// before lib/ is loaded, which cannot be undone safely in-process.
|
|
15
|
-
|
|
16
|
-
require('chai').should()
|
|
17
|
-
var path = require('path')
|
|
18
|
-
var spawnSync = require('child_process').spawnSync
|
|
19
|
-
|
|
20
|
-
var ROOT = path.resolve(__dirname, '../..')
|
|
21
|
-
var SHA256_ABC = 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'
|
|
22
|
-
|
|
23
|
-
// Run `body` with Module._load intercepted by `stub`, and print the result of `report`.
|
|
24
|
-
function inChild (stub, report) {
|
|
25
|
-
var src = [
|
|
26
|
-
'var Module = require("module"), orig = Module._load',
|
|
27
|
-
'var real = orig.call(Module, "crypto", module, false)',
|
|
28
|
-
'Module._load = function (r) {',
|
|
29
|
-
' if (r === "crypto") { ' + stub + ' }',
|
|
30
|
-
' return orig.apply(this, arguments)',
|
|
31
|
-
'}',
|
|
32
|
-
// Only the pure-JS backend is loaded for comparison. hash.node.js require()s
|
|
33
|
-
// 'crypto' at module scope, so it is not even loadable when the stub removes it —
|
|
34
|
-
// which is precisely why hash.js must not reach for it unconditionally.
|
|
35
|
-
'var HASH = require(' + JSON.stringify(path.join(ROOT, 'lib/crypto/hash.js')) + ')',
|
|
36
|
-
'var PURE = require(' + JSON.stringify(path.join(ROOT, 'lib/crypto/hash.browser.js')) + ')',
|
|
37
|
-
'console.log(' + report + ')'
|
|
38
|
-
].join('\n')
|
|
39
|
-
var out = spawnSync(process.execPath, ['-e', src], { encoding: 'utf8' })
|
|
40
|
-
if (out.status !== 0) throw new Error('child failed: ' + out.stderr)
|
|
41
|
-
return out.stdout.trim()
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
describe('crypto backend selection', function () {
|
|
45
|
-
this.timeout(30000)
|
|
46
|
-
|
|
47
|
-
it('uses node crypto when it is present and correct', function () {
|
|
48
|
-
// Not the pure-JS module => the node backend was selected.
|
|
49
|
-
inChild('return real', '(HASH !== PURE) + " " + HASH.sha256(Buffer.from("abc")).toString("hex")')
|
|
50
|
-
.should.equal('true ' + SHA256_ABC)
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
it('falls back to the pure-JS backend when there is no crypto module', function () {
|
|
54
|
-
inChild('var e = new Error("no crypto"); e.code = "MODULE_NOT_FOUND"; throw e',
|
|
55
|
-
'(HASH === PURE) + " " + HASH.sha256(Buffer.from("abc")).toString("hex")')
|
|
56
|
-
.should.equal('true ' + SHA256_ABC)
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
// The important one. A shim that EXISTS but computes the wrong digest must be
|
|
60
|
-
// rejected — trusting it would silently corrupt every hash in the library, and a
|
|
61
|
-
// wrong hash is invisible until it matters.
|
|
62
|
-
it('rejects a crypto shim that returns incorrect digests', function () {
|
|
63
|
-
inChild(
|
|
64
|
-
'return { createHash: function () { return { update: function () { return this }, ' +
|
|
65
|
-
'digest: function () { return "deadbeef" } } } }',
|
|
66
|
-
'(HASH === PURE) + " " + HASH.sha256(Buffer.from("abc")).toString("hex")')
|
|
67
|
-
.should.equal('true ' + SHA256_ABC)
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
// OpenSSL 3 moved ripemd160 to the legacy provider, so some Node builds have sha256
|
|
71
|
-
// but throw on ripemd160 — and ripemd160 is what addresses are built from.
|
|
72
|
-
it('rejects a crypto build without ripemd160', function () {
|
|
73
|
-
inChild(
|
|
74
|
-
'return Object.assign({}, real, { createHash: function (a) { ' +
|
|
75
|
-
'if (a === "ripemd160") throw new Error("Digest method not supported"); ' +
|
|
76
|
-
'return real.createHash(a) } })',
|
|
77
|
-
'(HASH === PURE) + " " + HASH.sha256ripemd160(Buffer.from("abc")).toString("hex").slice(0, 16)')
|
|
78
|
-
.should.equal('true bb1be98c142444d7')
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
it('does not consult process.browser', function () {
|
|
82
|
-
var src = [
|
|
83
|
-
'process.browser = undefined',
|
|
84
|
-
'var a = require(' + JSON.stringify(path.join(ROOT, 'lib/crypto/hash.js')) + ')',
|
|
85
|
-
'console.log(a.sha256(Buffer.from("abc")).toString("hex"))'
|
|
86
|
-
].join('\n')
|
|
87
|
-
var withoutFlag = spawnSync(process.execPath, ['-e', src], { encoding: 'utf8' })
|
|
88
|
-
var withFlag = spawnSync(process.execPath, ['-e', 'process.browser = true\n' + src.split('\n').slice(1).join('\n')], { encoding: 'utf8' })
|
|
89
|
-
withoutFlag.stdout.trim().should.equal(SHA256_ABC)
|
|
90
|
-
withFlag.stdout.trim().should.equal(SHA256_ABC)
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
describe('pbkdf2', function () {
|
|
94
|
-
// BIP-39 English test vector; the seed must not depend on which backend ran.
|
|
95
|
-
var PHRASE = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'
|
|
96
|
-
var SEED = 'c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04'
|
|
97
|
-
|
|
98
|
-
function seedInChild (stub) {
|
|
99
|
-
var src = [
|
|
100
|
-
'var Module = require("module"), orig = Module._load',
|
|
101
|
-
'var real = orig.call(Module, "crypto", module, false)',
|
|
102
|
-
'Module._load = function (r) { if (r === "crypto") { ' + stub + ' } return orig.apply(this, arguments) }',
|
|
103
|
-
'var bsv = require(' + JSON.stringify(ROOT) + ')',
|
|
104
|
-
'console.log(new bsv.Mnemonic(' + JSON.stringify(PHRASE) + ').toSeed("TREZOR").toString("hex"))'
|
|
105
|
-
].join('\n')
|
|
106
|
-
var out = spawnSync(process.execPath, ['-e', src], { encoding: 'utf8' })
|
|
107
|
-
if (out.status !== 0) throw new Error('child failed: ' + out.stderr)
|
|
108
|
-
return out.stdout.trim()
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
it('derives the BIP-39 vector with node crypto', function () {
|
|
112
|
-
seedInChild('return real').should.equal(SEED)
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
it('derives the same seed with no crypto module', function () {
|
|
116
|
-
seedInChild('var e = new Error("no crypto"); e.code = "MODULE_NOT_FOUND"; throw e').should.equal(SEED)
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
it('rejects a shim whose HMAC is wrong and still derives the right seed', function () {
|
|
120
|
-
seedInChild(
|
|
121
|
-
'return Object.assign({}, real, { createHmac: function () { return { ' +
|
|
122
|
-
'update: function () { return this }, digest: function () { return Buffer.alloc(64) } } } })'
|
|
123
|
-
).should.equal(SEED)
|
|
124
|
-
})
|
|
125
|
-
})
|
|
126
|
-
})
|
package/test/crypto/bn.js
DELETED
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
var should = require('chai').should()
|
|
4
|
-
var bsv = require('../..')
|
|
5
|
-
var BN = bsv.crypto.BN
|
|
6
|
-
|
|
7
|
-
describe('BN', function () {
|
|
8
|
-
it('should create a bn', function () {
|
|
9
|
-
var bn = new BN(50)
|
|
10
|
-
should.exist(bn)
|
|
11
|
-
bn.toString().should.equal('50')
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
it('should parse this number', function () {
|
|
15
|
-
var bn = new BN(999970000)
|
|
16
|
-
bn.toString().should.equal('999970000')
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
it('should parse numbers below and at bn.js internal word size', function () {
|
|
20
|
-
var bn = new BN(Math.pow(2, 26) - 1)
|
|
21
|
-
bn.toString().should.equal((Math.pow(2, 26) - 1).toString())
|
|
22
|
-
bn = new BN(Math.pow(2, 26))
|
|
23
|
-
bn.toString().should.equal((Math.pow(2, 26)).toString())
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
describe('#add', function () {
|
|
27
|
-
it('should add two small numbers together', function () {
|
|
28
|
-
var bn1 = new BN(50)
|
|
29
|
-
var bn2 = new BN(75)
|
|
30
|
-
var bn3 = bn1.add(bn2)
|
|
31
|
-
bn3.toString().should.equal('125')
|
|
32
|
-
})
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
describe('#sub', function () {
|
|
36
|
-
it('should subtract a small number', function () {
|
|
37
|
-
var bn1 = new BN(50)
|
|
38
|
-
var bn2 = new BN(25)
|
|
39
|
-
var bn3 = bn1.sub(bn2)
|
|
40
|
-
bn3.toString().should.equal('25')
|
|
41
|
-
})
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
describe('#gt', function () {
|
|
45
|
-
it('should say 1 is greater than 0', function () {
|
|
46
|
-
var bn1 = new BN(1)
|
|
47
|
-
var bn0 = new BN(0)
|
|
48
|
-
bn1.gt(bn0).should.equal(true)
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('should say a big number is greater than a small big number', function () {
|
|
52
|
-
var bn1 = new BN('24023452345398529485723980457')
|
|
53
|
-
var bn0 = new BN('34098234283412341234049357')
|
|
54
|
-
bn1.gt(bn0).should.equal(true)
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
it('should say a big number is great than a standard number', function () {
|
|
58
|
-
var bn1 = new BN('24023452345398529485723980457')
|
|
59
|
-
var bn0 = new BN(5)
|
|
60
|
-
bn1.gt(bn0).should.equal(true)
|
|
61
|
-
})
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
describe('to/from ScriptNumBuffer', function () {
|
|
65
|
-
[0, 1, 10, 256, 1000, 65536, 65537, -1, -1000, -65536, -65537].forEach(function (n) {
|
|
66
|
-
it('rountrips correctly for ' + n, function () {
|
|
67
|
-
BN.fromScriptNumBuffer(new BN(n).toScriptNumBuffer()).toNumber().should.equal(n)
|
|
68
|
-
})
|
|
69
|
-
})
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
describe('#fromString', function () {
|
|
73
|
-
it('should make BN from a string', function () {
|
|
74
|
-
BN.fromString('5').toString().should.equal('5')
|
|
75
|
-
})
|
|
76
|
-
it('should work with hex string', function () {
|
|
77
|
-
BN.fromString('7fffff0000000000000000000000000000000000000000000000000000000000', 16)
|
|
78
|
-
.toString(16).should.equal('7fffff0000000000000000000000000000000000000000000000000000000000')
|
|
79
|
-
})
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
describe('#toString', function () {
|
|
83
|
-
it('should make a string', function () {
|
|
84
|
-
new BN(5).toString().should.equal('5')
|
|
85
|
-
})
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
describe('@fromBuffer', function () {
|
|
89
|
-
it('should work with big endian', function () {
|
|
90
|
-
var bn = BN.fromBuffer(Buffer.from('0001', 'hex'), {
|
|
91
|
-
endian: 'big'
|
|
92
|
-
})
|
|
93
|
-
bn.toString().should.equal('1')
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
it('should work with big endian 256', function () {
|
|
97
|
-
var bn = BN.fromBuffer(Buffer.from('0100', 'hex'), {
|
|
98
|
-
endian: 'big'
|
|
99
|
-
})
|
|
100
|
-
bn.toString().should.equal('256')
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
it('should work with little endian if we specify the size', function () {
|
|
104
|
-
var bn = BN.fromBuffer(Buffer.from('0100', 'hex'), {
|
|
105
|
-
size: 2,
|
|
106
|
-
endian: 'little'
|
|
107
|
-
})
|
|
108
|
-
bn.toString().should.equal('1')
|
|
109
|
-
})
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
describe('#toBuffer', function () {
|
|
113
|
-
it('should create a 4 byte buffer', function () {
|
|
114
|
-
var bn = new BN(1)
|
|
115
|
-
bn.toBuffer({
|
|
116
|
-
size: 4
|
|
117
|
-
}).toString('hex').should.equal('00000001')
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
it('should create a 4 byte buffer in little endian', function () {
|
|
121
|
-
var bn = new BN(1)
|
|
122
|
-
bn.toBuffer({
|
|
123
|
-
size: 4,
|
|
124
|
-
endian: 'little'
|
|
125
|
-
}).toString('hex').should.equal('01000000')
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
it('should create a 2 byte buffer even if you ask for a 1 byte', function () {
|
|
129
|
-
var bn = new BN('ff00', 16)
|
|
130
|
-
bn.toBuffer({
|
|
131
|
-
size: 1
|
|
132
|
-
}).toString('hex').should.equal('ff00')
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
it('should create a 4 byte buffer even if you ask for a 1 byte', function () {
|
|
136
|
-
var bn = new BN('ffffff00', 16)
|
|
137
|
-
bn.toBuffer({
|
|
138
|
-
size: 4
|
|
139
|
-
}).toString('hex').should.equal('ffffff00')
|
|
140
|
-
})
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
describe('@fromHex', function () {
|
|
144
|
-
it('should work with big endian', function () {
|
|
145
|
-
var bn = BN.fromHex('0001', {
|
|
146
|
-
endian: 'big'
|
|
147
|
-
})
|
|
148
|
-
bn.toString().should.equal('1')
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
it('should work with little endian if we specify the size', function () {
|
|
152
|
-
var bn = BN.fromHex('0100', {
|
|
153
|
-
size: 2,
|
|
154
|
-
endian: 'little'
|
|
155
|
-
})
|
|
156
|
-
bn.toString().should.equal('1')
|
|
157
|
-
})
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
describe('#toHex', function () {
|
|
161
|
-
it('should create a 4 byte he string', function () {
|
|
162
|
-
var bn = new BN(1)
|
|
163
|
-
bn.toHex({
|
|
164
|
-
size: 4
|
|
165
|
-
}).should.equal('00000001')
|
|
166
|
-
})
|
|
167
|
-
})
|
|
168
|
-
})
|