diff options
| author | Adam Soltys <[email protected]> | 2023-03-23 10:18:40 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2023-03-24 21:37:04 -0700 |
| commit | 095b3cf78004305ba25d2fa358d9362d5ca84b62 (patch) | |
| tree | 11367f637976a86add5014f9f72a58f81f14f944 /src | |
| parent | e1fe2fb22efb74a855a2ba3ca5acb1bba774fa0f (diff) | |
| download | coinos-ui-095b3cf78004305ba25d2fa358d9362d5ca84b62.tar.gz coinos-ui-095b3cf78004305ba25d2fa358d9362d5ca84b62.zip | |
use nostr-tools
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/nostr.js | 86 | ||||
| -rw-r--r-- | src/lib/utils.js | 4 | ||||
| -rw-r--r-- | src/routes/(app)/[username]/generate/+page.svelte | 3 | ||||
| -rw-r--r-- | src/routes/(app)/[username]/messages/+page.server.js | 3 | ||||
| -rw-r--r-- | src/routes/(app)/[username]/messages/+page.svelte | 4 |
5 files changed, 27 insertions, 73 deletions
diff --git a/src/lib/nostr.js b/src/lib/nostr.js index d72f48ef..1924643e 100644 --- a/src/lib/nostr.js +++ b/src/lib/nostr.js @@ -1,60 +1,39 @@ import { get } from 'svelte/store'; -import * as ecc from 'tiny-secp256k1'; -import { generateMnemonic, entropyToMnemonic, mnemonicToEntropy, mnemonicToSeedSync } from 'bip39'; import { Buffer } from 'buffer'; -import { bech32m } from 'bech32'; -import { bip32, fail, wait, post, stretch } from '$lib/utils'; -import { calculateId, signId } from 'nostr'; +import { fail, wait, post, stretch } from '$lib/utils'; import { decrypted, password as pw, passwordPrompt, pin, loginRedirect } from '$lib/store'; import { goto, invalidate } from '$app/navigation'; +import { getPublicKey, signEvent, getEventHash, nip04, nip06 } from 'nostr-tools'; +import { mnemonicToEntropy, entropyToMnemonic } from '@scure/bip39'; +import { wordlist } from '@scure/bip39/wordlists/english.js'; +import { bech32m } from '@scure/base'; -const { encode, decode, fromWords, toWords } = bech32m; +const { generateSeedWords, privateKeyFromSeedWords } = nip06; +const { encode, decode, toWords, fromWords } = bech32m; export let generate = async (user) => { - let password = get(pw); - let mnemonic, key, seed, entropy, cipher, salt, child; - if (!get(pin)?.length === 6) return; + let password = get(pw); - mnemonic = generateMnemonic(); - seed = mnemonicToSeedSync(mnemonic); - entropy = mnemonicToEntropy(mnemonic); - key = bip32.fromSeed(seed); - child = key.derivePath("m/44'/1237'/0'/0/0"); - salt = crypto.getRandomValues(new Uint8Array(16)); + let salt = crypto.getRandomValues(new Uint8Array(16)); + let mnemonic = generateSeedWords(); + let sk = privateKeyFromSeedWords(mnemonic); let bytes = new Uint8Array( await crypto.subtle.encrypt( { name: 'AES-GCM', iv: new Uint8Array(16) }, await stretch(password, salt), - Uint8Array.from(Buffer.from(entropy, 'hex')) + Uint8Array.from(Buffer.from(mnemonicToEntropy(mnemonic, wordlist), 'hex')) ) ); - user.pubkey = Buffer.from(ecc.xOnlyPointFromPoint(child.publicKey)).toString('hex'); + user.pubkey = getPublicKey(sk); user.cipher = encode('en', toWords(bytes), 180); user.salt = Buffer.from(salt).toString('hex'); }; export let encrypt = async ({ message, recipient, user }) => { - let sharedPoint = Buffer.from( - ecc.pointMultiply( - Uint8Array.from(Buffer.from('02' + recipient, 'hex')), - Buffer.from(await getPrivateKey(user), 'hex') - ) - ); - - let iv = crypto.getRandomValues(new Uint8Array(16)); - let cipher = await crypto.subtle.encrypt( - { name: 'AES-CBC', iv }, - await crypto.subtle.importKey('raw', sharedPoint.slice(1), 'AES-CBC', true, [ - 'encrypt', - 'decrypt' - ]), - new TextEncoder().encode(message) - ); - - return Buffer.from(cipher).toString('base64') + '?iv=' + Buffer.from(iv).toString('base64'); + return nip04.encrypt(await getPrivateKey(user), recipient, message); }; export let decrypt = async ({ event, user }) => { @@ -63,22 +42,8 @@ export let decrypt = async ({ event, user }) => { let { content, pubkey, id } = event; if (cache[id]) return cache[id]; if (pubkey === user.pubkey) pubkey = event.tags[0][1]; - pubkey = Uint8Array.from(Buffer.from('02' + pubkey, 'hex')); - - let sharedPoint = Buffer.from( - ecc.pointMultiply(pubkey, Buffer.from(await getPrivateKey(user), 'hex')) - ); - let [cipher, iv] = content.split('?iv='); - cipher = Uint8Array.from(Buffer.from(cipher, 'base64')); - iv = Uint8Array.from(Buffer.from(iv, 'base64')); - - let key = await crypto.subtle.importKey('raw', sharedPoint.slice(1), 'AES-CBC', true, [ - 'encrypt', - 'decrypt' - ]); - - let message = await crypto.subtle.decrypt({ name: 'AES-CBC', iv }, key, cipher); + let message = await nip04.decrypt(await getPrivateKey(user), pubkey, content); cache[id] = Buffer.from(message).toString('utf8'); decrypted.set(cache); @@ -111,27 +76,22 @@ let getPrivateKey = async (user) => { password = get(pw); let mnemonic, key, seed, entropy, child, privkey; - entropy = Buffer.from( + + entropy = new Uint8Array( await crypto.subtle.decrypt( { name: 'AES-GCM', iv: new Uint8Array(16) }, await stretch(password, Buffer.from(salt, 'hex')), Uint8Array.from(fromWords(decode(cipher, 180).words)) - ), - 'hex' - ).toString('hex'); - - mnemonic = entropyToMnemonic(entropy); - seed = mnemonicToSeedSync(mnemonic); - key = bip32.fromSeed(seed); - child = key.derivePath("m/44'/1237'/0'/0/0"); + ) + ); - return child.privateKey; + mnemonic = entropyToMnemonic(entropy, wordlist); + return privateKeyFromSeedWords(mnemonic); }; export let sign = async ({ event, user }) => { - let privkey = await getPrivateKey(user); - event.id = await calculateId(event); - event.sig = await signId(privkey, event.id); + event.id = getEventHash(event); + event.sig = signEvent(event, await getPrivateKey(user)); }; export let send = (event) => { diff --git a/src/lib/utils.js b/src/lib/utils.js index 9b612bfd..18554bd9 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -1,5 +1,3 @@ -import * as ecc from 'tiny-secp256k1'; -import { BIP32Factory } from 'bip32'; import { browser } from '$app/environment'; import { toast } from '@zerodevx/svelte-toast'; import { goto } from '$app/navigation'; @@ -212,8 +210,6 @@ export const stretch = async (password, salt) => ['encrypt', 'decrypt'] ); -export const bip32 = await BIP32Factory(ecc); - function get_bigrams(string) { var s = string.toLowerCase(); var v = s.split(''); diff --git a/src/routes/(app)/[username]/generate/+page.svelte b/src/routes/(app)/[username]/generate/+page.svelte index 32a38592..3548ccd4 100644 --- a/src/routes/(app)/[username]/generate/+page.svelte +++ b/src/routes/(app)/[username]/generate/+page.svelte @@ -1,9 +1,6 @@ <script> import { fail, post, wait } from '$lib/utils'; - import { Buffer } from 'buffer'; import { onMount } from 'svelte'; - import { bech32m } from 'bech32'; - import { generateMnemonic, mnemonicToEntropy, mnemonicToSeedSync } from 'bip39'; import { goto, invalidate } from '$app/navigation'; import { Pin } from '$comp'; import { loginRedirect, pin, password, passwordPrompt } from '$lib/store'; diff --git a/src/routes/(app)/[username]/messages/+page.server.js b/src/routes/(app)/[username]/messages/+page.server.js index 8347c184..ec5c5eee 100644 --- a/src/routes/(app)/[username]/messages/+page.server.js +++ b/src/routes/(app)/[username]/messages/+page.server.js @@ -8,8 +8,9 @@ export async function load({ params, parent, url }) { try { messages = await get(`/${user.pubkey}/${since}/messages`); + messages = messages - .filter((m) => m.recipient.id === subject.id || m.author.id === subject.id) + .filter((m) => m.recipient?.id === subject.id || m.author?.id === subject.id) .sort((a, b) => a.created_at - b.created_at); if (user.id === subject.id) messages = messages.filter((m) => m.recipient.id === m.author.id); diff --git a/src/routes/(app)/[username]/messages/+page.svelte b/src/routes/(app)/[username]/messages/+page.svelte index 7a10d605..cfa7f741 100644 --- a/src/routes/(app)/[username]/messages/+page.svelte +++ b/src/routes/(app)/[username]/messages/+page.svelte @@ -10,7 +10,7 @@ import { sign, send, encrypt, decrypt } from '$lib/nostr'; import { event as e, password } from '$lib/store'; import { tick, onMount } from 'svelte'; - import { calculateId } from 'nostr'; + import { getEventHash } from 'nostr-tools'; export let data; @@ -77,8 +77,8 @@ tick().then(() => pane && (pane.scrollTop = pane.scrollHeight)); try { - event.id = await calculateId(event); event.content = await encrypt({ message: event.message, recipient: subject.pubkey, user }); + event.id = getEventHash(event); await sign({ event, user }); await send(event); |
