smartledger-bsv 3.3.3 → 3.3.5

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 (62) hide show
  1. package/CHANGELOG.md +50 -28
  2. package/README.md +55 -36
  3. package/bsv-covenant.min.js +6 -6
  4. package/bsv-gdaf.min.js +6 -6
  5. package/bsv-ltp.min.js +6 -6
  6. package/bsv-mnemonic.min.js +4 -4
  7. package/bsv-smartcontract.min.js +5 -5
  8. package/bsv.bundle.js +5 -5
  9. package/bsv.min.js +5 -5
  10. package/demos/README.md +188 -0
  11. package/demos/architecture_demo.js +247 -0
  12. package/demos/browser-test.html +1208 -0
  13. package/demos/bsv_wallet_demo.js +242 -0
  14. package/demos/complete_ltp_demo.js +511 -0
  15. package/demos/debug_tools_demo.js +87 -0
  16. package/demos/demo_features.js +123 -0
  17. package/demos/easy_interface_demo.js +109 -0
  18. package/demos/ecies_demo.js +182 -0
  19. package/demos/gdaf_core_test.js +131 -0
  20. package/demos/gdaf_demo.js +237 -0
  21. package/demos/ltp_demo.js +361 -0
  22. package/demos/ltp_primitives_demo.js +403 -0
  23. package/demos/message_demo.js +209 -0
  24. package/demos/preimage_separation_demo.js +383 -0
  25. package/demos/script_helper_demo.js +289 -0
  26. package/demos/security_demo.js +287 -0
  27. package/demos/shamir_demo.js +121 -0
  28. package/demos/simple_demo.js +204 -0
  29. package/demos/simple_p2pkh_demo.js +169 -0
  30. package/demos/simple_utxo_preimage_demo.js +196 -0
  31. package/demos/smart_contract_demo.html +1347 -0
  32. package/demos/smart_contract_demo.js +910 -0
  33. package/demos/utxo_generator_demo.js +244 -0
  34. package/demos/validation_pipeline_demo.js +155 -0
  35. package/demos/web3keys.html +740 -0
  36. package/docs/BUNDLE_UPDATE_SUMMARY.md +40 -0
  37. package/docs/DOCUMENTATION_REVIEW_REPORT.md +11 -11
  38. package/docs/FIX_CREATEHMAC_ISSUE.md +91 -0
  39. package/docs/MODULE_REFERENCE_COMPLETE.md +28 -28
  40. package/docs/SMARTLEDGER_BSV_USAGE_ANSWERS.md +477 -0
  41. package/docs/SMARTLEDGER_BSV_USAGE_EXAMPLES.js +372 -0
  42. package/docs/SMARTLEDGER_BSV_USAGE_GUIDE.md +555 -0
  43. package/docs/SMART_CONTRACT_DEVELOPMENT_GUIDE.md +1459 -0
  44. package/docs/advanced/UTXO_MANAGER_GUIDE.md +2 -2
  45. package/docs/getting-started/INSTALLATION.md +25 -25
  46. package/docs/getting-started/QUICK_START.md +7 -7
  47. package/docs/migration/FROM_BSV_1_5_6.md +5 -5
  48. package/examples/complete_workflow_demo.js +783 -0
  49. package/examples/definitive_working_demo.js +261 -0
  50. package/examples/final_working_contracts.js +338 -0
  51. package/examples/smart_contract_templates.js +718 -0
  52. package/examples/working_smart_contracts.js +348 -0
  53. package/index.js +7 -0
  54. package/lib/browser-utxo-manager-es5.js +316 -0
  55. package/lib/browser-utxo-manager.js +533 -0
  56. package/lib/mnemonic/pbkdf2.browser.js +69 -0
  57. package/lib/mnemonic/pbkdf2.js +2 -68
  58. package/lib/mnemonic/pbkdf2.node.js +68 -0
  59. package/package.json +19 -8
  60. package/tests/browser-compatibility/README.md +35 -0
  61. package/tests/browser-compatibility/test-cdn-vs-local.html +186 -0
  62. package/tests/browser-compatibility/test-pbkdf2.html +51 -0
@@ -0,0 +1,533 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * Browser-Compatible UTXO Manager
5
+ * Lightweight UTXO management for browser environments with configurable storage
6
+ */
7
+
8
+ /**
9
+ * Storage types available for browser UTXO management
10
+ */
11
+ var STORAGE_TYPES = {
12
+ MEMORY: 'memory', // In-memory only (lost on page reload)
13
+ SESSION: 'session', // sessionStorage (lost when tab closes)
14
+ LOCAL: 'local' // localStorage (persists until cleared)
15
+ }
16
+
17
+ /**
18
+ * Browser-compatible UTXO Manager
19
+ * Provides UTXO tracking and management for browser applications
20
+ */
21
+ function BrowserUTXOManager(options) {
22
+ options = options || {}
23
+ /**
24
+ * Create a new browser UTXO manager
25
+ * @param {Object} options - Configuration options
26
+ * @param {string} options.storage - Storage type: 'memory', 'session', or 'local' (default: 'memory')
27
+ * @param {string} options.storageKey - Key for browser storage (default: 'smartledger-utxos')
28
+ * @param {boolean} options.autoSave - Auto-save after each operation (default: true)
29
+ * @param {number} options.maxUTXOs - Maximum UTXOs to store (default: 1000)
30
+ */
31
+ constructor(options = {}) {
32
+ this.options = {
33
+ storage: options.storage || STORAGE_TYPES.MEMORY,
34
+ storageKey: options.storageKey || 'smartledger-utxos',
35
+ autoSave: options.autoSave !== false,
36
+ maxUTXOs: options.maxUTXOs || 1000,
37
+ ...options
38
+ }
39
+
40
+ // Validate storage type
41
+ if (!Object.values(STORAGE_TYPES).includes(this.options.storage)) {
42
+ throw new Error(`Invalid storage type: ${this.options.storage}. Must be one of: ${Object.values(STORAGE_TYPES).join(', ')}`)
43
+ }
44
+
45
+ // Initialize storage
46
+ this.utxos = new Map() // Main UTXO store: key = "txid:vout", value = utxo object
47
+ this.addressIndex = new Map() // Address index: key = address, value = Set of utxo keys
48
+ this.spentUTXOs = new Map() // Spent UTXO tracking
49
+ this.metadata = {
50
+ totalUTXOs: 0,
51
+ totalValue: 0,
52
+ createdAt: new Date().toISOString(),
53
+ lastUpdated: new Date().toISOString()
54
+ }
55
+
56
+ // Load existing data
57
+ this.loadFromStorage()
58
+ }
59
+
60
+ /**
61
+ * Get storage interface based on configuration
62
+ * @returns {Object} Storage interface (memory, sessionStorage, or localStorage)
63
+ * @private
64
+ */
65
+ _getStorage() {
66
+ switch (this.options.storage) {
67
+ case STORAGE_TYPES.MEMORY:
68
+ return null // Memory storage handled by class properties
69
+ case STORAGE_TYPES.SESSION:
70
+ return typeof sessionStorage !== 'undefined' ? sessionStorage : null
71
+ case STORAGE_TYPES.LOCAL:
72
+ return typeof localStorage !== 'undefined' ? localStorage : null
73
+ default:
74
+ return null
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Load UTXOs from configured storage
80
+ */
81
+ loadFromStorage() {
82
+ try {
83
+ if (this.options.storage === STORAGE_TYPES.MEMORY) {
84
+ // Memory storage - nothing to load, start fresh
85
+ return
86
+ }
87
+
88
+ const storage = this._getStorage()
89
+ if (!storage) {
90
+ console.warn('BrowserUTXOManager: Storage not available, using memory mode')
91
+ return
92
+ }
93
+
94
+ const stored = storage.getItem(this.options.storageKey)
95
+ if (!stored) {
96
+ return // No existing data
97
+ }
98
+
99
+ const data = JSON.parse(stored)
100
+
101
+ // Restore UTXOs
102
+ if (data.utxos) {
103
+ data.utxos.forEach(utxoData => {
104
+ const key = `${utxoData.txid}:${utxoData.vout}`
105
+ this.utxos.set(key, utxoData)
106
+ })
107
+ }
108
+
109
+ // Restore address index
110
+ if (data.addressIndex) {
111
+ Object.entries(data.addressIndex).forEach(([address, utxoKeys]) => {
112
+ this.addressIndex.set(address, new Set(utxoKeys))
113
+ })
114
+ }
115
+
116
+ // Restore spent UTXOs
117
+ if (data.spentUTXOs) {
118
+ data.spentUTXOs.forEach(spentData => {
119
+ const key = `${spentData.txid}:${spentData.vout}`
120
+ this.spentUTXOs.set(key, spentData)
121
+ })
122
+ }
123
+
124
+ // Restore metadata
125
+ if (data.metadata) {
126
+ this.metadata = { ...this.metadata, ...data.metadata }
127
+ }
128
+
129
+ this._updateMetadata()
130
+ console.log(`✅ BrowserUTXOManager: Loaded ${this.utxos.size} UTXOs from ${this.options.storage} storage`)
131
+
132
+ } catch (error) {
133
+ console.error('BrowserUTXOManager: Error loading from storage:', error.message)
134
+ // Continue with empty state
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Save UTXOs to configured storage
140
+ */
141
+ saveToStorage() {
142
+ try {
143
+ if (this.options.storage === STORAGE_TYPES.MEMORY) {
144
+ return // Memory storage - nothing to persist
145
+ }
146
+
147
+ const storage = this._getStorage()
148
+ if (!storage) {
149
+ return // Storage not available
150
+ }
151
+
152
+ // Prepare data for serialization
153
+ const data = {
154
+ utxos: Array.from(this.utxos.values()),
155
+ addressIndex: {},
156
+ spentUTXOs: Array.from(this.spentUTXOs.values()),
157
+ metadata: this.metadata
158
+ }
159
+
160
+ // Convert address index to serializable format
161
+ this.addressIndex.forEach((utxoKeys, address) => {
162
+ data.addressIndex[address] = Array.from(utxoKeys)
163
+ })
164
+
165
+ storage.setItem(this.options.storageKey, JSON.stringify(data))
166
+ console.log(`💾 BrowserUTXOManager: Saved ${this.utxos.size} UTXOs to ${this.options.storage} storage`)
167
+
168
+ } catch (error) {
169
+ console.error('BrowserUTXOManager: Error saving to storage:', error.message)
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Add a UTXO to the manager
175
+ * @param {Object} utxo - UTXO object {txid, vout, address, satoshis, script}
176
+ * @returns {boolean} - true if added, false if already exists or limit exceeded
177
+ */
178
+ addUTXO(utxo) {
179
+ try {
180
+ // Validate UTXO
181
+ if (!utxo.txid || typeof utxo.vout !== 'number' || !utxo.address || typeof utxo.satoshis !== 'number') {
182
+ throw new Error('Invalid UTXO: missing required fields (txid, vout, address, satoshis)')
183
+ }
184
+
185
+ const key = `${utxo.txid}:${utxo.vout}`
186
+
187
+ // Check if already exists
188
+ if (this.utxos.has(key)) {
189
+ console.log(`⚠️ UTXO already exists: ${key}`)
190
+ return false
191
+ }
192
+
193
+ // Check limits
194
+ if (this.utxos.size >= this.options.maxUTXOs) {
195
+ console.warn(`⚠️ Maximum UTXO limit reached (${this.options.maxUTXOs})`)
196
+ return false
197
+ }
198
+
199
+ // Add timestamp
200
+ const utxoWithMeta = {
201
+ ...utxo,
202
+ addedAt: new Date().toISOString()
203
+ }
204
+
205
+ // Store UTXO
206
+ this.utxos.set(key, utxoWithMeta)
207
+
208
+ // Update address index
209
+ if (!this.addressIndex.has(utxo.address)) {
210
+ this.addressIndex.set(utxo.address, new Set())
211
+ }
212
+ this.addressIndex.get(utxo.address).add(key)
213
+
214
+ this._updateMetadata()
215
+
216
+ if (this.options.autoSave) {
217
+ this.saveToStorage()
218
+ }
219
+
220
+ console.log(`✅ UTXO added: ${key} (${utxo.satoshis} sats)`)
221
+ return true
222
+
223
+ } catch (error) {
224
+ console.error('BrowserUTXOManager: Error adding UTXO:', error.message)
225
+ return false
226
+ }
227
+ }
228
+
229
+ /**
230
+ * Get all UTXOs for a specific address
231
+ * @param {string} address - Bitcoin address
232
+ * @returns {Array} Array of UTXO objects
233
+ */
234
+ getUTXOsForAddress(address) {
235
+ try {
236
+ const utxoKeys = this.addressIndex.get(address)
237
+ if (!utxoKeys) {
238
+ return []
239
+ }
240
+
241
+ const utxos = []
242
+ utxoKeys.forEach(key => {
243
+ const utxo = this.utxos.get(key)
244
+ if (utxo) {
245
+ utxos.push(utxo)
246
+ }
247
+ })
248
+
249
+ return utxos.sort((a, b) => b.satoshis - a.satoshis) // Sort by value descending
250
+
251
+ } catch (error) {
252
+ console.error('BrowserUTXOManager: Error getting UTXOs for address:', error.message)
253
+ return []
254
+ }
255
+ }
256
+
257
+ /**
258
+ * Get total balance for an address
259
+ * @param {string} address - Bitcoin address
260
+ * @returns {number} Total satoshis
261
+ */
262
+ getBalance(address) {
263
+ const utxos = this.getUTXOsForAddress(address)
264
+ return utxos.reduce((total, utxo) => total + utxo.satoshis, 0)
265
+ }
266
+
267
+ /**
268
+ * Spend UTXOs (mark as spent and remove from available set)
269
+ * @param {Array} inputs - Array of input objects {txid, vout} or {txid, vout, spentInTx}
270
+ * @param {string} spentInTx - Optional transaction ID where UTXOs were spent
271
+ * @returns {Array} Array of spent UTXO objects
272
+ */
273
+ spendUTXOs(inputs, spentInTx = 'browser-spend') {
274
+ const spentUTXOs = []
275
+
276
+ try {
277
+ inputs.forEach(input => {
278
+ const key = `${input.txid}:${input.vout}`
279
+ const utxo = this.utxos.get(key)
280
+
281
+ if (!utxo) {
282
+ console.warn(`⚠️ UTXO not found: ${key}`)
283
+ return
284
+ }
285
+
286
+ // Mark as spent
287
+ const spentUTXO = {
288
+ ...utxo,
289
+ spentAt: new Date().toISOString(),
290
+ spentInTx: input.spentInTx || spentInTx
291
+ }
292
+
293
+ this.spentUTXOs.set(key, spentUTXO)
294
+ spentUTXOs.push(spentUTXO)
295
+
296
+ // Remove from available UTXOs
297
+ this.utxos.delete(key)
298
+
299
+ // Update address index
300
+ const addressSet = this.addressIndex.get(utxo.address)
301
+ if (addressSet) {
302
+ addressSet.delete(key)
303
+ if (addressSet.size === 0) {
304
+ this.addressIndex.delete(utxo.address)
305
+ }
306
+ }
307
+
308
+ console.log(`❌ UTXO spent: ${key} in ${spentUTXO.spentInTx}`)
309
+ })
310
+
311
+ this._updateMetadata()
312
+
313
+ if (this.options.autoSave) {
314
+ this.saveToStorage()
315
+ }
316
+
317
+ } catch (error) {
318
+ console.error('BrowserUTXOManager: Error spending UTXOs:', error.message)
319
+ }
320
+
321
+ return spentUTXOs
322
+ }
323
+
324
+ /**
325
+ * Check if a UTXO is available (unspent)
326
+ * @param {string} txid - Transaction ID
327
+ * @param {number} vout - Output index
328
+ * @returns {boolean} True if UTXO is available
329
+ */
330
+ isUTXOAvailable(txid, vout) {
331
+ const key = `${txid}:${vout}`
332
+ return this.utxos.has(key)
333
+ }
334
+
335
+ /**
336
+ * Get UTXO details
337
+ * @param {string} txid - Transaction ID
338
+ * @param {number} vout - Output index
339
+ * @returns {Object|null} UTXO object or null if not found
340
+ */
341
+ getUTXO(txid, vout) {
342
+ const key = `${txid}:${vout}`
343
+
344
+ // Check if available
345
+ if (this.utxos.has(key)) {
346
+ return { status: 'available', utxo: this.utxos.get(key) }
347
+ }
348
+
349
+ // Check if spent
350
+ if (this.spentUTXOs.has(key)) {
351
+ return { status: 'spent', utxo: this.spentUTXOs.get(key) }
352
+ }
353
+
354
+ return { status: 'not_found', utxo: null }
355
+ }
356
+
357
+ /**
358
+ * Create mock UTXOs for testing (browser-compatible)
359
+ * @param {string} address - Target address
360
+ * @param {number} count - Number of UTXOs to create
361
+ * @param {number} satoshis - Satoshis per UTXO
362
+ * @returns {Array} Array of created UTXOs
363
+ */
364
+ createMockUTXOs(address, count = 5, satoshis = 100000) {
365
+ const mockUTXOs = []
366
+
367
+ try {
368
+ for (let i = 0; i < count; i++) {
369
+ // Generate random txid using Web Crypto API
370
+ const txidArray = new Uint8Array(32)
371
+ if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) {
372
+ window.crypto.getRandomValues(txidArray)
373
+ } else {
374
+ // Fallback for environments without Web Crypto
375
+ for (let j = 0; j < 32; j++) {
376
+ txidArray[j] = Math.floor(Math.random() * 256)
377
+ }
378
+ }
379
+
380
+ const txid = Array.from(txidArray).map(b => b.toString(16).padStart(2, '0')).join('')
381
+ const script = `76a914${Array.from(new Uint8Array(20)).map(b => Math.floor(Math.random() * 256).toString(16).padStart(2, '0')).join('')}88ac`
382
+
383
+ const utxo = {
384
+ txid,
385
+ vout: i,
386
+ address,
387
+ satoshis,
388
+ script,
389
+ isMock: true
390
+ }
391
+
392
+ if (this.addUTXO(utxo)) {
393
+ mockUTXOs.push(utxo)
394
+ }
395
+ }
396
+
397
+ } catch (error) {
398
+ console.error('BrowserUTXOManager: Error creating mock UTXOs:', error.message)
399
+ }
400
+
401
+ return mockUTXOs
402
+ }
403
+
404
+ /**
405
+ * Get manager statistics
406
+ * @returns {Object} Statistics object
407
+ */
408
+ getStats() {
409
+ const addresses = Array.from(this.addressIndex.keys())
410
+ const balancesByAddress = {}
411
+
412
+ addresses.forEach(address => {
413
+ balancesByAddress[address] = this.getBalance(address)
414
+ })
415
+
416
+ return {
417
+ totalUTXOs: this.utxos.size,
418
+ totalSpent: this.spentUTXOs.size,
419
+ totalValue: this.metadata.totalValue,
420
+ totalAddresses: addresses.length,
421
+ storageType: this.options.storage,
422
+ storageKey: this.options.storageKey,
423
+ balancesByAddress,
424
+ createdAt: this.metadata.createdAt,
425
+ lastUpdated: this.metadata.lastUpdated
426
+ }
427
+ }
428
+
429
+ /**
430
+ * Clear all UTXOs and reset state
431
+ * @param {boolean} clearStorage - Also clear browser storage (default: true)
432
+ */
433
+ reset(clearStorage = true) {
434
+ this.utxos.clear()
435
+ this.addressIndex.clear()
436
+ this.spentUTXOs.clear()
437
+
438
+ this.metadata = {
439
+ totalUTXOs: 0,
440
+ totalValue: 0,
441
+ createdAt: new Date().toISOString(),
442
+ lastUpdated: new Date().toISOString()
443
+ }
444
+
445
+ if (clearStorage && this.options.storage !== STORAGE_TYPES.MEMORY) {
446
+ const storage = this._getStorage()
447
+ if (storage) {
448
+ storage.removeItem(this.options.storageKey)
449
+ console.log(`🔄 Cleared ${this.options.storage} storage`)
450
+ }
451
+ }
452
+
453
+ console.log('🔄 BrowserUTXOManager reset complete')
454
+ }
455
+
456
+ /**
457
+ * Update internal metadata
458
+ * @private
459
+ */
460
+ _updateMetadata() {
461
+ this.metadata.totalUTXOs = this.utxos.size
462
+ this.metadata.totalValue = Array.from(this.utxos.values())
463
+ .reduce((total, utxo) => total + utxo.satoshis, 0)
464
+ this.metadata.lastUpdated = new Date().toISOString()
465
+ }
466
+
467
+ /**
468
+ * Export UTXOs as JSON
469
+ * @returns {string} JSON string of all data
470
+ */
471
+ exportData() {
472
+ const data = {
473
+ utxos: Array.from(this.utxos.values()),
474
+ spentUTXOs: Array.from(this.spentUTXOs.values()),
475
+ metadata: this.metadata,
476
+ exportedAt: new Date().toISOString()
477
+ }
478
+ return JSON.stringify(data, null, 2)
479
+ }
480
+
481
+ /**
482
+ * Import UTXOs from JSON
483
+ * @param {string} jsonData - JSON string to import
484
+ * @param {boolean} merge - Merge with existing data (default: false)
485
+ * @returns {boolean} Success status
486
+ */
487
+ importData(jsonData, merge = false) {
488
+ try {
489
+ const data = JSON.parse(jsonData)
490
+
491
+ if (!merge) {
492
+ this.reset(false) // Don't clear storage yet
493
+ }
494
+
495
+ // Import UTXOs
496
+ if (data.utxos && Array.isArray(data.utxos)) {
497
+ data.utxos.forEach(utxo => {
498
+ this.addUTXO(utxo)
499
+ })
500
+ }
501
+
502
+ // Import spent UTXOs
503
+ if (data.spentUTXOs && Array.isArray(data.spentUTXOs)) {
504
+ data.spentUTXOs.forEach(spentUTXO => {
505
+ const key = `${spentUTXO.txid}:${spentUTXO.vout}`
506
+ this.spentUTXOs.set(key, spentUTXO)
507
+ })
508
+ }
509
+
510
+ this._updateMetadata()
511
+
512
+ if (this.options.autoSave) {
513
+ this.saveToStorage()
514
+ }
515
+
516
+ console.log('✅ BrowserUTXOManager: Imported ' + (data.utxos && data.utxos.length || 0) + ' UTXOs')
517
+ return true
518
+
519
+ } catch (error) {
520
+ console.error('BrowserUTXOManager: Error importing data:', error.message)
521
+ return false
522
+ }
523
+ }
524
+ }
525
+
526
+ // Export for both CommonJS and ES modules
527
+ if (typeof module !== 'undefined' && module.exports) {
528
+ module.exports = BrowserUTXOManager
529
+ module.exports.STORAGE_TYPES = STORAGE_TYPES
530
+ } else if (typeof window !== 'undefined') {
531
+ window.BrowserUTXOManager = BrowserUTXOManager
532
+ window.BrowserUTXOManager.STORAGE_TYPES = STORAGE_TYPES
533
+ }
@@ -0,0 +1,69 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * Browser-compatible PBKDF2 implementation using BSV crypto
5
+ * Credit to: https://github.com/stayradiated/pbkdf2-sha512
6
+ * Copyright (c) 2014, JP Richardson Copyright (c) 2010-2011 Intalio Pte, All Rights Reserved
7
+ */
8
+
9
+ // Import BSV crypto instead of Node.js crypto
10
+ var Hash = require('../crypto/hash')
11
+
12
+ function pbkdf2 (key, salt, iterations, dkLen) {
13
+ var hLen = 64 // SHA512 Mac length
14
+ if (dkLen > (Math.pow(2, 32) - 1) * hLen) {
15
+ throw Error('Requested key length too long')
16
+ }
17
+
18
+ if (typeof key !== 'string' && !Buffer.isBuffer(key)) {
19
+ throw new TypeError('key must a string or Buffer')
20
+ }
21
+
22
+ if (typeof salt !== 'string' && !Buffer.isBuffer(salt)) {
23
+ throw new TypeError('salt must a string or Buffer')
24
+ }
25
+
26
+ if (typeof key === 'string') {
27
+ key = Buffer.from(key)
28
+ }
29
+
30
+ if (typeof salt === 'string') {
31
+ salt = Buffer.from(salt)
32
+ }
33
+
34
+ var DK = Buffer.alloc(dkLen)
35
+ var U = Buffer.alloc(hLen)
36
+ var T = Buffer.alloc(hLen)
37
+ var block1 = Buffer.alloc(salt.length + 4)
38
+
39
+ var l = Math.ceil(dkLen / hLen)
40
+ var r = dkLen - (l - 1) * hLen
41
+
42
+ salt.copy(block1, 0, 0, salt.length)
43
+ for (var i = 1; i <= l; i++) {
44
+ block1[salt.length + 0] = (i >> 24 & 0xff)
45
+ block1[salt.length + 1] = (i >> 16 & 0xff)
46
+ block1[salt.length + 2] = (i >> 8 & 0xff)
47
+ block1[salt.length + 3] = (i >> 0 & 0xff)
48
+
49
+ // Use BSV's browser-compatible HMAC instead of Node.js crypto
50
+ U = Hash.sha512hmac(block1, key)
51
+ U.copy(T, 0, 0, hLen)
52
+
53
+ for (var j = 1; j < iterations; j++) {
54
+ U = Hash.sha512hmac(U, key)
55
+
56
+ for (var k = 0; k < hLen; k++) {
57
+ T[k] ^= U[k]
58
+ }
59
+ }
60
+
61
+ var destPos = (i - 1) * hLen
62
+ var len = (i === l ? r : hLen)
63
+ T.copy(DK, destPos, 0, len)
64
+ }
65
+
66
+ return DK
67
+ }
68
+
69
+ module.exports = pbkdf2
@@ -1,68 +1,2 @@
1
- 'use strict'
2
-
3
- var crypto = require('crypto')
4
-
5
- /**
6
- * PDKBF2
7
- * Credit to: https://github.com/stayradiated/pbkdf2-sha512
8
- * Copyright (c) 2014, JP Richardson Copyright (c) 2010-2011 Intalio Pte, All Rights Reserved
9
- */
10
- function pbkdf2 (key, salt, iterations, dkLen) {
11
- var hLen = 64 // SHA512 Mac length
12
- if (dkLen > (Math.pow(2, 32) - 1) * hLen) {
13
- throw Error('Requested key length too long')
14
- }
15
-
16
- if (typeof key !== 'string' && !Buffer.isBuffer(key)) {
17
- throw new TypeError('key must a string or Buffer')
18
- }
19
-
20
- if (typeof salt !== 'string' && !Buffer.isBuffer(salt)) {
21
- throw new TypeError('salt must a string or Buffer')
22
- }
23
-
24
- if (typeof key === 'string') {
25
- key = Buffer.from(key)
26
- }
27
-
28
- if (typeof salt === 'string') {
29
- salt = Buffer.from(salt)
30
- }
31
-
32
- var DK = Buffer.alloc(dkLen)
33
-
34
- var U = Buffer.alloc(hLen)
35
- var T = Buffer.alloc(hLen)
36
- var block1 = Buffer.alloc(salt.length + 4)
37
-
38
- var l = Math.ceil(dkLen / hLen)
39
- var r = dkLen - (l - 1) * hLen
40
-
41
- salt.copy(block1, 0, 0, salt.length)
42
- for (var i = 1; i <= l; i++) {
43
- block1[salt.length + 0] = (i >> 24 & 0xff)
44
- block1[salt.length + 1] = (i >> 16 & 0xff)
45
- block1[salt.length + 2] = (i >> 8 & 0xff)
46
- block1[salt.length + 3] = (i >> 0 & 0xff)
47
-
48
- U = crypto.createHmac('sha512', key).update(block1).digest()
49
-
50
- U.copy(T, 0, 0, hLen)
51
-
52
- for (var j = 1; j < iterations; j++) {
53
- U = crypto.createHmac('sha512', key).update(U).digest()
54
-
55
- for (var k = 0; k < hLen; k++) {
56
- T[k] ^= U[k]
57
- }
58
- }
59
-
60
- var destPos = (i - 1) * hLen
61
- var len = (i === l ? r : hLen)
62
- T.copy(DK, destPos, 0, len)
63
- }
64
-
65
- return DK
66
- }
67
-
68
- module.exports = pbkdf2
1
+ if (process.browser) module.exports = require('./pbkdf2.browser')
2
+ else module.exports = require('./pbkdf2.node')