diff options
| author | Adam Soltys <[email protected]> | 2024-08-30 18:44:33 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2024-08-30 18:44:33 -0700 |
| commit | cb2edf24e48a49417ed6ec4a386e566470ff046c (patch) | |
| tree | 4c773eea453252ed7211c9b65bf1ef4a7f4c2670 /src/lib/nostr.js | |
| parent | cdf0174a1a5d37b34c1078d6dcc87a5d7fb162ce (diff) | |
| download | coinos-ui-cb2edf24e48a49417ed6ec4a386e566470ff046c.tar.gz coinos-ui-cb2edf24e48a49417ed6ec4a386e566470ff046c.zip | |
typescript
Diffstat (limited to 'src/lib/nostr.js')
| -rw-r--r-- | src/lib/nostr.js | 177 |
1 files changed, 0 insertions, 177 deletions
diff --git a/src/lib/nostr.js b/src/lib/nostr.js deleted file mode 100644 index 5209418a..00000000 --- a/src/lib/nostr.js +++ /dev/null @@ -1,177 +0,0 @@ -import { browser } from "$app/environment"; -import { hexToUint8Array } from "uint8array-extras"; -import { get } from "svelte/store"; -import { Buffer } from "buffer"; -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, - finalizeEvent, - getEventHash, - nip04, - nip19, -} from "nostr-tools"; - -import { - encrypt as nip49encrypt, - decrypt as nip49decrypt, -} from "nostr-tools/nip49"; - -import { mnemonicToEntropy, entropyToMnemonic } from "@scure/bip39"; -import wordlist from "$lib/english"; -import { bech32m } from "@scure/base"; - -import { generateSeedWords, privateKeyFromSeedWords } from "nostr-tools/nip06"; -const { encode, decode, toWords, fromWords } = bech32m; - -export let generate = async (user) => { - if (!get(pin)?.length === 6) return; - - 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(await getPassword(), salt), - Uint8Array.from(Buffer.from(mnemonicToEntropy(mnemonic, wordlist), "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 sk = await getPrivateKey(user); - return nip04.encrypt(sk, recipient, message); -}; - -export let decrypt = async ({ event, user }) => { - let cache = get(decrypted); - try { - let { content, pubkey, id } = event; - if (cache[id]) return cache[id]; - if (pubkey === user.pubkey) pubkey = event.tags[0][1]; - - let message = await nip04.decrypt( - await getPrivateKey(user), - pubkey, - content - ); - - cache[id] = Buffer.from(message).toString("utf8"); - decrypted.set(cache); - - return cache[id]; - } catch (e) { - // console.log(e); - } -}; - -function typedArrayToBuffer(array) { - return array.buffer.slice( - array.byteOffset, - array.byteLength + array.byteOffset - ); -} - -export let getPrivateKey = async (user) => { - let k; - if (browser) { - k = localStorage.getItem("nsec"); - if (k) { - return nip19.decode(k).data; - } - } - - let { nsec, username, salt } = user; - - if (nsec) { - k = nip49decrypt(nsec, await getPassword()); - } else k = hexToUint8Array(privateKeyFromSeedWords(await getMnemonic(user))); - - localStorage.setItem("nsec", nip19.nsecEncode(k)); - return k; -}; - -export let getMnemonic = async (user) => { - let { cipher, username, salt } = user; - let mnemonic, key, seed, entropy, child, privkey; - - entropy = new Uint8Array( - await crypto.subtle.decrypt( - { name: "AES-GCM", iv: new Uint8Array(16) }, - await stretch(await getPassword(), Buffer.from(salt, "hex")), - Uint8Array.from(fromWords(decode(cipher, 180).words)) - ) - ); - - return entropyToMnemonic(entropy, wordlist); -}; - -export let getNsec = async (user) => { - return nip19.nsecEncode(await getPrivateKey(user)); -}; - -export let setNsec = async (user, nsec) => { - let { data: sk } = nip19.decode(nsec); - user.pubkey = getPublicKey(sk); - user.nsec = await encryptNsec(nsec); -}; - -export let encryptNsec = async (nsec) => { - let { type, data } = nip19.decode(nsec); - if (type === "nsec" && data.length === 32) { - return nip49encrypt(data, await getPassword()); - } else { - fail("invalid nsec"); - } -}; - -export let sign = async ({ event, user }) => { - event = finalizeEvent(event, await getPrivateKey(user)); -}; - -export let send = (event) => { - return post("/events", { event }); -}; - -let getPassword = async () => { - if (!get(pw)) passwordPrompt.set(true); - await wait(() => !!get(pw)); - return get(pw); -}; - -export let reEncryptEntropy = async (user, newPassword) => { - let { cipher, username, salt } = user; - - let mnemonic, key, seed, entropy, child, privkey; - entropy = Buffer.from( - await crypto.subtle.decrypt( - { name: "AES-GCM", iv: new Uint8Array(16) }, - await stretch(await getPassword(), Buffer.from(salt, "hex")), - Uint8Array.from(fromWords(decode(cipher, 180).words)) - ), - "hex" - ).toString("hex"); - - let bytes = new Uint8Array( - await crypto.subtle.encrypt( - { name: "AES-GCM", iv: new Uint8Array(16) }, - await stretch(newPassword, Buffer.from(salt, "hex")), - Uint8Array.from(Buffer.from(entropy, "hex")) - ) - ); - - return encode("en", toWords(bytes), 180); -}; |
