libp2r2p 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/AGENTS.md +20 -0
  2. package/README.md +129 -0
  3. package/base16/index.js +14 -0
  4. package/base64/index.js +29 -0
  5. package/content-key/event/index.js +85 -0
  6. package/content-key/index.js +1 -0
  7. package/content-key/services/iykc-proof.js +129 -0
  8. package/double-dh/index.js +166 -0
  9. package/ecdh/index.js +8 -0
  10. package/idb/index.js +64 -0
  11. package/idb-queue/index.js +793 -0
  12. package/index.js +21 -0
  13. package/key/index.js +139 -0
  14. package/network/index.js +68 -0
  15. package/nip44-v3/index.js +175 -0
  16. package/nip46/constants/index.js +5 -0
  17. package/nip46/helpers/frame.js +51 -0
  18. package/nip46/helpers/url.js +96 -0
  19. package/nip46/index.js +5 -0
  20. package/nip46/services/bunker-signer.js +49 -0
  21. package/nip46/services/client.js +252 -0
  22. package/nip46/services/server-session.js +225 -0
  23. package/nip46/services/transport.js +265 -0
  24. package/package.json +49 -0
  25. package/private-channel/constants/index.js +5 -0
  26. package/private-channel/helpers/chunk-size.js +61 -0
  27. package/private-channel/helpers/chunks.js +282 -0
  28. package/private-channel/helpers/event.js +68 -0
  29. package/private-channel/index.js +942 -0
  30. package/private-channel/services/received-chunks.js +398 -0
  31. package/private-message/index.js +672 -0
  32. package/private-messenger/constants/index.js +1 -0
  33. package/private-messenger/index.js +1431 -0
  34. package/private-messenger/recovery/index.js +316 -0
  35. package/relay/constants/index.js +18 -0
  36. package/relay/helpers/hll.js +62 -0
  37. package/relay/helpers/publish.js +100 -0
  38. package/relay/helpers/routing.js +36 -0
  39. package/relay/helpers/timer.js +4 -0
  40. package/relay/index.js +4 -0
  41. package/relay/services/query.js +224 -0
  42. package/relay/services/relay-connection.js +156 -0
  43. package/relay/services/relay-pool.js +908 -0
  44. package/temporary-storage/index.js +85 -0
  45. package/tests/base16.test.js +19 -0
  46. package/tests/base64.test.js +18 -0
  47. package/tests/content-key-event.test.js +48 -0
  48. package/tests/fixtures/nip44v3-vectors.json +1 -0
  49. package/tests/helpers/test-signer.js +185 -0
  50. package/tests/idb-queue.test.js +153 -0
  51. package/tests/idb.test.js +91 -0
  52. package/tests/nip44-v3.test.js +73 -0
  53. package/tests/nip46.test.js +668 -0
  54. package/tests/private-channel.test.js +1899 -0
  55. package/tests/private-message.test.js +460 -0
  56. package/tests/private-messenger.test.js +1715 -0
  57. package/tests/queries.test.js +101 -0
  58. package/tests/queue-parity.test.js +105 -0
  59. package/tests/relay-hll.test.js +32 -0
  60. package/tests/relay-pool.test.js +2067 -0
  61. package/tests/temporary-storage.test.js +89 -0
  62. package/tests/web-storage-queue.test.js +480 -0
  63. package/web-storage-queue/index.js +652 -0
@@ -0,0 +1,91 @@
1
+ import { test } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import { IDBFactory } from 'fake-indexeddb'
4
+ import { run } from '../idb/index.js'
5
+
6
+ function deferred () {
7
+ let resolve
8
+ let reject
9
+ const promise = new Promise((nextResolve, nextReject) => {
10
+ resolve = nextResolve
11
+ reject = nextReject
12
+ })
13
+ return { promise, resolve, reject }
14
+ }
15
+
16
+ function transactionDone (tx) {
17
+ return new Promise((resolve, reject) => {
18
+ tx.oncomplete = () => resolve()
19
+ tx.onabort = () => reject(tx.error || new Error('IDB_TRANSACTION_ABORTED'))
20
+ tx.onerror = () => reject(tx.error || new Error('IDB_TRANSACTION_FAILED'))
21
+ })
22
+ }
23
+
24
+ function openRowsDb () {
25
+ const indexedDB = new IDBFactory()
26
+ return new Promise((resolve, reject) => {
27
+ const request = indexedDB.open('idb-run-test', 1)
28
+ request.onerror = () => reject(request.error)
29
+ request.onupgradeneeded = () => {
30
+ const store = request.result.createObjectStore('rows', { keyPath: 'id' })
31
+ store.createIndex('byGroup', 'group')
32
+ }
33
+ request.onsuccess = () => resolve(request.result)
34
+ })
35
+ }
36
+
37
+ test('run performs store and index requests inside a shared transaction', async () => {
38
+ const db = await openRowsDb()
39
+ const tx = db.transaction(['rows'], 'readwrite')
40
+ const done = transactionDone(tx)
41
+
42
+ await run('put', [{ id: 'one', group: 'alpha', value: 1 }], 'rows', null, { db, tx })
43
+ await run('put', [{ id: 'two', group: 'beta', value: 2 }], 'rows', null, { db, tx })
44
+ const found = await run('get', ['alpha'], 'rows', 'byGroup', { db, tx })
45
+
46
+ assert.equal(found.result.id, 'one')
47
+ await done
48
+ db.close()
49
+ })
50
+
51
+ test('run supports the reusable deferred cursor pattern', async () => {
52
+ const db = await openRowsDb()
53
+ const setup = db.transaction(['rows'], 'readwrite')
54
+ const setupDone = transactionDone(setup)
55
+ await run('put', [{ id: 'one', group: 'alpha' }], 'rows', null, { db, tx: setup })
56
+ await run('put', [{ id: 'two', group: 'beta' }], 'rows', null, { db, tx: setup })
57
+ await setupDone
58
+
59
+ const tx = db.transaction(['rows'], 'readonly')
60
+ const done = transactionDone(tx)
61
+ const p = deferred()
62
+ let cursor = (await run('openCursor', [], 'rows', null, { db, tx, p })).result
63
+ const ids = []
64
+ while (cursor) {
65
+ ids.push(cursor.value.id)
66
+ Object.assign(p, deferred())
67
+ cursor.continue()
68
+ cursor = (await p.promise).result
69
+ }
70
+
71
+ assert.deepEqual(ids, ['one', 'two'])
72
+ await done
73
+ db.close()
74
+ })
75
+
76
+ test('run aborts a transaction when a request fails', async () => {
77
+ const db = await openRowsDb()
78
+ const tx = db.transaction(['rows'], 'readwrite')
79
+ const done = transactionDone(tx)
80
+
81
+ await run('add', [{ id: 'one', group: 'alpha' }], 'rows', null, { db, tx })
82
+ await assert.rejects(
83
+ run('add', [{ id: 'one', group: 'beta' }], 'rows', null, { db, tx })
84
+ )
85
+ await assert.rejects(done)
86
+
87
+ const read = db.transaction(['rows'], 'readonly')
88
+ const row = await run('get', ['one'], 'rows', null, { db, tx: read })
89
+ assert.equal(row.result, undefined)
90
+ db.close()
91
+ })
@@ -0,0 +1,73 @@
1
+ import { test } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import { readFileSync } from 'node:fs'
4
+ import { getPublicKey } from 'nostr-tools'
5
+ import { sha256 } from '@noble/hashes/sha2.js'
6
+
7
+ import * as nip44v3 from '../nip44-v3/index.js'
8
+ import { bytesToHex, hexToBytes } from '../base16/index.js'
9
+
10
+ const vectors = JSON.parse(readFileSync(new URL('./fixtures/nip44v3-vectors.json', import.meta.url), 'utf8'))
11
+
12
+ function pubOf (sec) {
13
+ return getPublicKey(hexToBytes(sec))
14
+ }
15
+
16
+ test('nip44-v3 passes the vendored upstream self-test vectors', () => {
17
+ const fails = []
18
+ const check = (section, name, cond, detail = '') => {
19
+ if (!cond) fails.push(`[${section}] ${name}${detail ? `: ${detail}` : ''}`)
20
+ }
21
+
22
+ for (const [i, v] of (vectors.encrypt_decrypt || []).entries()) {
23
+ const sec1 = hexToBytes(v.secret1)
24
+ const sec2 = hexToBytes(v.secret2)
25
+ const pub1 = pubOf(v.secret1)
26
+ const pub2 = pubOf(v.secret2)
27
+ const nonce = hexToBytes(v.nonce)
28
+ const scope = hexToBytes(v.scope_hex)
29
+ const plaintext = hexToBytes(v.plaintext_hex)
30
+ const keys = nip44v3.deriveKeys(sec1, pub2, nonce)
31
+ check('encrypt_decrypt', `ed[${i}] prk`, bytesToHex(keys.prk) === v.prk)
32
+ check('encrypt_decrypt', `ed[${i}] encryption_key`, bytesToHex(keys.encryption_key) === v.encryption_key)
33
+ check('encrypt_decrypt', `ed[${i}] mac_key`, bytesToHex(keys.mac_key) === v.mac_key)
34
+ check('encrypt_decrypt', `ed[${i}] encrypt party1`, nip44v3.encryptBytes(sec1, pub2, v.kind, scope, plaintext, nonce) === v.ciphertext)
35
+ check('encrypt_decrypt', `ed[${i}] encrypt party2`, nip44v3.encryptBytes(sec2, pub1, v.kind, scope, plaintext, nonce) === v.ciphertext)
36
+ check('encrypt_decrypt', `ed[${i}] decrypt party1`, bytesToHex(nip44v3.decryptBytes(sec1, pub2, v.kind, scope, v.ciphertext)) === v.plaintext_hex)
37
+ check('encrypt_decrypt', `ed[${i}] decrypt party2`, bytesToHex(nip44v3.decryptBytes(sec2, pub1, v.kind, scope, v.ciphertext)) === v.plaintext_hex)
38
+ }
39
+
40
+ for (const [i, v] of (vectors.decrypt_only || []).entries()) {
41
+ check('decrypt_only', `do[${i}]`, bytesToHex(nip44v3.decryptBytes(hexToBytes(v.secret1), pubOf(v.secret2), v.kind, hexToBytes(v.scope_hex), v.ciphertext)) === v.plaintext_hex)
42
+ }
43
+
44
+ for (const [i, v] of (vectors.long_encrypt_decrypt || []).entries()) {
45
+ const pattern = hexToBytes(v.pattern_hex)
46
+ const plaintext = new Uint8Array(pattern.length * v.repeat)
47
+ for (let r = 0; r < v.repeat; r++) plaintext.set(pattern, r * pattern.length)
48
+ const scope = hexToBytes(v.scope_hex)
49
+ const ciphertext = nip44v3.encryptBytes(hexToBytes(v.secret1), pubOf(v.secret2), v.kind, scope, plaintext, hexToBytes(v.nonce))
50
+ check('long_encrypt_decrypt', `long[${i}] sha256`, bytesToHex(sha256(nip44v3.toBytes(ciphertext))) === v.ciphertext_sha256)
51
+ check('long_encrypt_decrypt', `long[${i}] round-trip`, bytesToHex(nip44v3.decryptBytes(hexToBytes(v.secret1), pubOf(v.secret2), v.kind, scope, ciphertext)) === bytesToHex(plaintext))
52
+ }
53
+
54
+ for (const row of (vectors.padded_length || [])) {
55
+ check('padded_length', `pad[${row[0]}]`, nip44v3.targetSize(row[0]) === row[1])
56
+ }
57
+
58
+ for (const [i, v] of (vectors.invalid_decryption || []).entries()) {
59
+ assert.throws(() => nip44v3.decryptBytes(hexToBytes(v.secret), v.public, v.kind, hexToBytes(v.scope_hex), v.ciphertext), Error, `invalid vector ${i} should reject`)
60
+ }
61
+
62
+ assert.deepEqual(fails, [])
63
+ })
64
+
65
+ test('nip44-v3 byte payload helpers round-trip arbitrary bytes', () => {
66
+ const alice = hexToBytes('1'.repeat(64))
67
+ const bob = hexToBytes('2'.repeat(64))
68
+ const plaintext = nip44v3.b64encode(new Uint8Array([0, 1, 2, 127, 128, 255]))
69
+ const ciphertext = nip44v3.nip07Encrypt(alice, getPublicKey(bob), '30078', 'spec.nostr.land/nip44v3', plaintext)
70
+
71
+ assert.equal(nip44v3.nip07Decrypt(bob, getPublicKey(alice), 30078, 'spec.nostr.land/nip44v3', ciphertext), plaintext)
72
+ assert.throws(() => nip44v3.nip07Decrypt(bob, getPublicKey(alice), 1, 'spec.nostr.land/nip44v3', ciphertext), /kind mismatch/)
73
+ })