smartledger-bsv 3.2.1 → 3.3.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.
- package/CHANGELOG.md +147 -0
- package/README.md +289 -55
- package/architecture_demo.js +247 -0
- package/bsv-covenant.min.js +10 -0
- package/bsv-gdaf.min.js +37 -0
- package/bsv-ltp.min.js +37 -0
- package/bsv-script-helper.min.js +10 -0
- package/bsv-security.min.js +31 -0
- package/bsv-shamir.min.js +12 -0
- package/bsv-smartcontract.min.js +37 -0
- package/bsv.bundle.js +9 -9
- package/bsv.min.js +3 -3
- package/build/bsv-covenant.min.js +10 -0
- package/build/bsv-script-helper.min.js +10 -0
- package/build/bsv-security.min.js +31 -0
- package/build/bsv-smartcontract.min.js +39 -0
- package/build/bsv.bundle.js +39 -0
- package/build/bsv.min.js +39 -0
- package/build/webpack.bundle.config.js +22 -0
- package/build/webpack.config.js +18 -0
- package/build/webpack.covenant.config.js +27 -0
- package/build/webpack.gdaf.config.js +54 -0
- package/build/webpack.ltp.config.js +17 -0
- package/build/webpack.script-helper.config.js +27 -0
- package/build/webpack.security.config.js +23 -0
- package/build/webpack.smartcontract.config.js +25 -0
- package/build/webpack.subproject.config.js +6 -0
- package/bundle-entry.js +341 -0
- package/complete_ltp_demo.js +511 -0
- package/covenant-entry.js +44 -0
- package/docs/pushtx-key-insights.md +106 -0
- package/gdaf-entry.js +54 -0
- package/index.js +272 -5
- package/lib/crypto/shamir.js +360 -0
- package/lib/gdaf/attestation-signer.js +461 -0
- package/lib/gdaf/attestation-verifier.js +600 -0
- package/lib/gdaf/did-resolver.js +382 -0
- package/lib/gdaf/index.js +471 -0
- package/lib/gdaf/schema-validator.js +682 -0
- package/lib/gdaf/smartledger-anchor.js +486 -0
- package/lib/gdaf/zk-prover.js +507 -0
- package/lib/ltp/anchor.js +438 -0
- package/lib/ltp/claim.js +1026 -0
- package/lib/ltp/index.js +470 -0
- package/lib/ltp/obligation.js +945 -0
- package/lib/ltp/proof.js +828 -0
- package/lib/ltp/registry.js +702 -0
- package/lib/ltp/right.js +765 -0
- package/lib/smart_contract/API_REFERENCE.md +1 -1
- package/lib/smart_contract/EXAMPLES.md +2 -2
- package/lib/smart_contract/QUICK_START.md +2 -2
- package/lib/smart_contract/README.md +1 -1
- package/lib/smart_contract/index.js +4 -0
- package/ltp-entry.js +92 -0
- package/package.json +91 -20
- package/script-helper-entry.js +49 -0
- package/security-entry.js +70 -0
- package/shamir-entry.js +173 -0
- package/shamir_demo.js +121 -0
- package/simple_demo.js +204 -0
- package/smartcontract-entry.js +133 -0
- package/test_shamir.js +221 -0
- package/test_standalone_shamir.html +83 -0
- package/tests/bundle-completeness-test.html +131 -0
- package/tests/bundle-demo.html +476 -0
- package/tests/smartcontract-test.html +239 -0
- package/tests/standalone-modules-test.html +260 -0
- package/tests/test.html +612 -0
- package/tests/unpkg-demo.html +194 -0
- package/docs/nchain.md +0 -958
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
var bsv = require('../../')
|
|
4
|
+
var PublicKey = bsv.PublicKey
|
|
5
|
+
var PrivateKey = bsv.PrivateKey
|
|
6
|
+
var Hash = bsv.crypto.Hash
|
|
7
|
+
var $ = bsv.util.preconditions
|
|
8
|
+
var errors = bsv.errors
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* SmartLedger DID Resolver
|
|
12
|
+
*
|
|
13
|
+
* Implements the did:smartledger DID method for decentralized identity
|
|
14
|
+
* management on the Bitcoin SV blockchain.
|
|
15
|
+
*
|
|
16
|
+
* DID Format: did:smartledger:<pubkey>[:<network>][:<path>]
|
|
17
|
+
*
|
|
18
|
+
* Features:
|
|
19
|
+
* - Generate DIDs from private/public keys
|
|
20
|
+
* - Resolve DID documents
|
|
21
|
+
* - Verify DID authenticity
|
|
22
|
+
* - Support for key rotation and service endpoints
|
|
23
|
+
* - Integration with SmartLedger attestation framework
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* DID Resolver constructor
|
|
28
|
+
* @param {Object} options - Configuration options
|
|
29
|
+
*/
|
|
30
|
+
function DIDResolver(options) {
|
|
31
|
+
if (!(this instanceof DIDResolver)) {
|
|
32
|
+
return new DIDResolver(options)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
this.options = options || {}
|
|
36
|
+
this.network = this.options.network || 'mainnet'
|
|
37
|
+
this.registry = this.options.registry || null
|
|
38
|
+
|
|
39
|
+
return this
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Generate DID from public key
|
|
44
|
+
* @param {PublicKey|String} publicKey - Public key
|
|
45
|
+
* @param {Object} options - Additional options
|
|
46
|
+
* @returns {String} DID string
|
|
47
|
+
*/
|
|
48
|
+
DIDResolver.fromPublicKey = function(publicKey, options) {
|
|
49
|
+
options = options || {}
|
|
50
|
+
|
|
51
|
+
if (typeof publicKey === 'string') {
|
|
52
|
+
publicKey = PublicKey.fromString(publicKey)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
$.checkArgument(publicKey instanceof PublicKey, 'Invalid public key')
|
|
56
|
+
|
|
57
|
+
var pubkeyHex = publicKey.toString('hex')
|
|
58
|
+
var network = options.network || 'mainnet'
|
|
59
|
+
var path = options.path || ''
|
|
60
|
+
|
|
61
|
+
var did = 'did:smartledger:' + pubkeyHex
|
|
62
|
+
|
|
63
|
+
if (network !== 'mainnet') {
|
|
64
|
+
did += ':' + network
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (path) {
|
|
68
|
+
did += ':' + path
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return did
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Generate DID from private key
|
|
76
|
+
* @param {PrivateKey|String} privateKey - Private key
|
|
77
|
+
* @param {Object} options - Additional options
|
|
78
|
+
* @returns {String} DID string
|
|
79
|
+
*/
|
|
80
|
+
DIDResolver.fromPrivateKey = function(privateKey, options) {
|
|
81
|
+
if (typeof privateKey === 'string') {
|
|
82
|
+
privateKey = PrivateKey.fromWIF(privateKey)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
$.checkArgument(privateKey instanceof PrivateKey, 'Invalid private key')
|
|
86
|
+
|
|
87
|
+
return DIDResolver.fromPublicKey(privateKey.toPublicKey(), options)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Parse DID string into components
|
|
92
|
+
* @param {String} did - DID string
|
|
93
|
+
* @returns {Object} DID components
|
|
94
|
+
*/
|
|
95
|
+
DIDResolver.parseDID = function(did) {
|
|
96
|
+
$.checkArgument(typeof did === 'string', 'DID must be a string')
|
|
97
|
+
|
|
98
|
+
if (!did.startsWith('did:smartledger:')) {
|
|
99
|
+
throw new Error('Invalid SmartLedger DID format')
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
var parts = did.split(':')
|
|
103
|
+
|
|
104
|
+
if (parts.length < 3) {
|
|
105
|
+
throw new Error('Invalid DID format')
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
var result = {
|
|
109
|
+
method: 'smartledger',
|
|
110
|
+
identifier: parts[2],
|
|
111
|
+
network: 'mainnet',
|
|
112
|
+
path: ''
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Parse optional network
|
|
116
|
+
if (parts.length > 3 && parts[3] !== '') {
|
|
117
|
+
result.network = parts[3]
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Parse optional path
|
|
121
|
+
if (parts.length > 4) {
|
|
122
|
+
result.path = parts.slice(4).join(':')
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return result
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Validate DID format
|
|
130
|
+
* @param {String} did - DID string
|
|
131
|
+
* @returns {Boolean} True if valid
|
|
132
|
+
*/
|
|
133
|
+
DIDResolver.isValidDID = function(did) {
|
|
134
|
+
try {
|
|
135
|
+
var parsed = DIDResolver.parseDID(did)
|
|
136
|
+
|
|
137
|
+
// Validate public key format
|
|
138
|
+
if (!/^[0-9a-fA-F]{66}$/.test(parsed.identifier) &&
|
|
139
|
+
!/^[0-9a-fA-F]{130}$/.test(parsed.identifier)) {
|
|
140
|
+
return false
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Validate network
|
|
144
|
+
if (!['mainnet', 'testnet', 'regtest'].includes(parsed.network)) {
|
|
145
|
+
return false
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return true
|
|
149
|
+
} catch (e) {
|
|
150
|
+
return false
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Extract public key from DID
|
|
156
|
+
* @param {String} did - DID string
|
|
157
|
+
* @returns {PublicKey} Public key
|
|
158
|
+
*/
|
|
159
|
+
DIDResolver.getPublicKey = function(did) {
|
|
160
|
+
var parsed = DIDResolver.parseDID(did)
|
|
161
|
+
return PublicKey.fromString(parsed.identifier)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Create DID Document
|
|
166
|
+
* @param {String} did - DID string
|
|
167
|
+
* @param {Object} options - Document options
|
|
168
|
+
* @returns {Object} DID Document
|
|
169
|
+
*/
|
|
170
|
+
DIDResolver.createDocument = function(did, options) {
|
|
171
|
+
options = options || {}
|
|
172
|
+
|
|
173
|
+
$.checkArgument(DIDResolver.isValidDID(did), 'Invalid DID')
|
|
174
|
+
|
|
175
|
+
var publicKey = DIDResolver.getPublicKey(did)
|
|
176
|
+
var keyId = did + '#keys-1'
|
|
177
|
+
|
|
178
|
+
var document = {
|
|
179
|
+
'@context': [
|
|
180
|
+
'https://www.w3.org/ns/did/v1',
|
|
181
|
+
'https://w3id.org/security/suites/secp256k1-2019/v1'
|
|
182
|
+
],
|
|
183
|
+
id: did,
|
|
184
|
+
verificationMethod: [{
|
|
185
|
+
id: keyId,
|
|
186
|
+
type: 'EcdsaSecp256k1VerificationKey2019',
|
|
187
|
+
controller: did,
|
|
188
|
+
publicKeyHex: publicKey.toString('hex')
|
|
189
|
+
}],
|
|
190
|
+
authentication: [keyId],
|
|
191
|
+
assertionMethod: [keyId],
|
|
192
|
+
keyAgreement: [keyId],
|
|
193
|
+
capabilityInvocation: [keyId],
|
|
194
|
+
capabilityDelegation: [keyId]
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Add service endpoints if provided
|
|
198
|
+
if (options.services && Array.isArray(options.services)) {
|
|
199
|
+
document.service = options.services
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Add additional verification methods
|
|
203
|
+
if (options.verificationMethods) {
|
|
204
|
+
document.verificationMethod = document.verificationMethod.concat(options.verificationMethods)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Add metadata
|
|
208
|
+
if (options.created) {
|
|
209
|
+
document.created = options.created
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (options.updated) {
|
|
213
|
+
document.updated = options.updated
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return document
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Resolve DID to DID Document
|
|
221
|
+
* @param {String} did - DID string
|
|
222
|
+
* @param {Object} options - Resolution options
|
|
223
|
+
* @returns {Promise<Object>} DID Resolution Result
|
|
224
|
+
*/
|
|
225
|
+
DIDResolver.resolve = async function(did, options) {
|
|
226
|
+
options = options || {}
|
|
227
|
+
|
|
228
|
+
try {
|
|
229
|
+
$.checkArgument(DIDResolver.isValidDID(did), 'Invalid DID')
|
|
230
|
+
|
|
231
|
+
// For now, create a standard document
|
|
232
|
+
// In production, this would query a registry or distributed storage
|
|
233
|
+
var document = DIDResolver.createDocument(did, options)
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
'@context': 'https://w3id.org/did-resolution/v1',
|
|
237
|
+
didDocument: document,
|
|
238
|
+
didResolutionMetadata: {
|
|
239
|
+
contentType: 'application/did+ld+json',
|
|
240
|
+
retrieved: new Date().toISOString()
|
|
241
|
+
},
|
|
242
|
+
didDocumentMetadata: {
|
|
243
|
+
method: {
|
|
244
|
+
published: true,
|
|
245
|
+
recoveryCommitment: null,
|
|
246
|
+
updateCommitment: null
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
} catch (error) {
|
|
251
|
+
return {
|
|
252
|
+
'@context': 'https://w3id.org/did-resolution/v1',
|
|
253
|
+
didDocument: null,
|
|
254
|
+
didResolutionMetadata: {
|
|
255
|
+
error: 'notFound',
|
|
256
|
+
errorMessage: error.message
|
|
257
|
+
},
|
|
258
|
+
didDocumentMetadata: {}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Verify DID ownership
|
|
265
|
+
* @param {String} did - DID string
|
|
266
|
+
* @param {String} signature - Signature to verify
|
|
267
|
+
* @param {String|Buffer} message - Original message
|
|
268
|
+
* @returns {Boolean} True if signature is valid
|
|
269
|
+
*/
|
|
270
|
+
DIDResolver.verifyOwnership = function(did, signature, message) {
|
|
271
|
+
try {
|
|
272
|
+
var publicKey = DIDResolver.getPublicKey(did)
|
|
273
|
+
var messageHash = Hash.sha256(Buffer.isBuffer(message) ? message : Buffer.from(message, 'utf8'))
|
|
274
|
+
|
|
275
|
+
var sig = bsv.crypto.Signature.fromString(signature)
|
|
276
|
+
var ecdsa = new bsv.crypto.ECDSA()
|
|
277
|
+
ecdsa.hashbuf = messageHash
|
|
278
|
+
ecdsa.pubkey = publicKey
|
|
279
|
+
ecdsa.sig = sig
|
|
280
|
+
|
|
281
|
+
return ecdsa.verify()
|
|
282
|
+
} catch (e) {
|
|
283
|
+
return false
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Sign message with DID
|
|
289
|
+
* @param {String} message - Message to sign
|
|
290
|
+
* @param {PrivateKey} privateKey - Private key for signing
|
|
291
|
+
* @returns {String} Signature
|
|
292
|
+
*/
|
|
293
|
+
DIDResolver.signMessage = function(message, privateKey) {
|
|
294
|
+
$.checkArgument(privateKey instanceof PrivateKey, 'Invalid private key')
|
|
295
|
+
|
|
296
|
+
var messageHash = Hash.sha256(Buffer.isBuffer(message) ? message : Buffer.from(message, 'utf8'))
|
|
297
|
+
|
|
298
|
+
var ecdsa = new bsv.crypto.ECDSA()
|
|
299
|
+
ecdsa.hashbuf = messageHash
|
|
300
|
+
ecdsa.privkey = privateKey
|
|
301
|
+
ecdsa.pubkey = privateKey.toPublicKey()
|
|
302
|
+
|
|
303
|
+
return ecdsa.sign().toString()
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Create DID proof of ownership
|
|
308
|
+
* @param {PrivateKey} privateKey - Private key
|
|
309
|
+
* @param {String} challenge - Challenge string
|
|
310
|
+
* @returns {Object} Proof object
|
|
311
|
+
*/
|
|
312
|
+
DIDResolver.createProofOfOwnership = function(privateKey, challenge) {
|
|
313
|
+
$.checkArgument(privateKey instanceof PrivateKey, 'Invalid private key')
|
|
314
|
+
$.checkArgument(typeof challenge === 'string', 'Challenge must be a string')
|
|
315
|
+
|
|
316
|
+
var did = DIDResolver.fromPrivateKey(privateKey)
|
|
317
|
+
var timestamp = new Date().toISOString()
|
|
318
|
+
var message = challenge + ':' + timestamp + ':' + did
|
|
319
|
+
var signature = DIDResolver.signMessage(message, privateKey)
|
|
320
|
+
|
|
321
|
+
return {
|
|
322
|
+
type: 'EcdsaSecp256k1Signature2019',
|
|
323
|
+
created: timestamp,
|
|
324
|
+
verificationMethod: did + '#keys-1',
|
|
325
|
+
proofPurpose: 'authentication',
|
|
326
|
+
challenge: challenge,
|
|
327
|
+
jws: signature
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Verify proof of ownership
|
|
333
|
+
* @param {Object} proof - Proof object
|
|
334
|
+
* @param {String} did - DID string
|
|
335
|
+
* @returns {Boolean} True if proof is valid
|
|
336
|
+
*/
|
|
337
|
+
DIDResolver.verifyProofOfOwnership = function(proof, did) {
|
|
338
|
+
try {
|
|
339
|
+
$.checkArgument(proof && typeof proof === 'object', 'Invalid proof object')
|
|
340
|
+
$.checkArgument(typeof did === 'string', 'DID must be a string')
|
|
341
|
+
|
|
342
|
+
var message = proof.challenge + ':' + proof.created + ':' + did
|
|
343
|
+
return DIDResolver.verifyOwnership(did, proof.jws, message)
|
|
344
|
+
} catch (e) {
|
|
345
|
+
return false
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Generate DID URL for specific purposes
|
|
351
|
+
* @param {String} did - Base DID
|
|
352
|
+
* @param {String} fragment - Fragment identifier
|
|
353
|
+
* @returns {String} DID URL
|
|
354
|
+
*/
|
|
355
|
+
DIDResolver.createDIDURL = function(did, fragment) {
|
|
356
|
+
$.checkArgument(typeof did === 'string', 'DID must be a string')
|
|
357
|
+
$.checkArgument(typeof fragment === 'string', 'Fragment must be a string')
|
|
358
|
+
|
|
359
|
+
return did + '#' + fragment
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Generate test DID for development
|
|
364
|
+
* @param {Object} options - Generation options
|
|
365
|
+
* @returns {Object} Test DID data
|
|
366
|
+
*/
|
|
367
|
+
DIDResolver.generateTestDID = function(options) {
|
|
368
|
+
options = options || {}
|
|
369
|
+
|
|
370
|
+
var privateKey = new PrivateKey()
|
|
371
|
+
var did = DIDResolver.fromPrivateKey(privateKey, options)
|
|
372
|
+
var document = DIDResolver.createDocument(did, options)
|
|
373
|
+
|
|
374
|
+
return {
|
|
375
|
+
did: did,
|
|
376
|
+
privateKey: privateKey.toWIF(),
|
|
377
|
+
publicKey: privateKey.toPublicKey().toString('hex'),
|
|
378
|
+
document: document
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
module.exports = DIDResolver
|