From 9185213a502bfb6aecbad149b2be039b58419841 Mon Sep 17 00:00:00 2001 From: zmeyer44 Date: Mon, 30 Oct 2023 11:09:46 -0400 Subject: [PATCH] encrypted nsec storage --- app/_providers/ndk/context/instance.ts | 2 - components/Modals/AddPassphrase.tsx | 70 ++++++++++++++++++++++++++ components/Modals/Login.tsx | 68 +++++++++++++++++++++---- lib/actions/create.ts | 2 - 4 files changed, 127 insertions(+), 15 deletions(-) create mode 100644 components/Modals/AddPassphrase.tsx diff --git a/app/_providers/ndk/context/instance.ts b/app/_providers/ndk/context/instance.ts index f9a116a..377514c 100644 --- a/app/_providers/ndk/context/instance.ts +++ b/app/_providers/ndk/context/instance.ts @@ -9,7 +9,6 @@ import NDK, { type NDKCacheAdapter, } from "@nostr-dev-kit/ndk"; import NDKCacheAdapterDexie from "@nostr-dev-kit/ndk-cache-dexie"; -import { db } from "@/lib/ndk/db"; export default function NDKInstance(explicitRelayUrls: string[]) { const loaded = useRef(false); @@ -81,7 +80,6 @@ export default function NDKInstance(explicitRelayUrls: string[]) { } if (signer) { - console.log("SIGNER", signer); _setSigner(signer); } diff --git a/components/Modals/AddPassphrase.tsx b/components/Modals/AddPassphrase.tsx new file mode 100644 index 0000000..0fd6c88 --- /dev/null +++ b/components/Modals/AddPassphrase.tsx @@ -0,0 +1,70 @@ +"use client"; +import { useState, useRef, useEffect } from "react"; +import Template from "./Template"; +import { Button } from "@/components/ui/button"; +import { useModal } from "@/app/_providers/modal/provider"; +import { nip19 } from "nostr-tools"; +// import { useKeys } from "@/app/_providers/keysProvider"; +import { useNDK } from "@/app/_providers/ndk"; +import useCurrentUser from "@/lib/hooks/useCurrentUser"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { encryptMessage } from "@/lib/nostr"; + +export default function AddPassphrase({ nsec }: { nsec: string }) { + const { signer } = useNDK(); + const { currentUser } = useCurrentUser(); + const [isLoading, setIsLoading] = useState(false); + const [passphrase, setPassphrase] = useState(""); + + const modal = useModal(); + + useEffect(() => { + if (currentUser) { + console.log("Current signer", currentUser.ndk?.signer); + console.log("Current signer alt", signer); + } + }, [currentUser]); + + async function handleAddPassphrase() { + setIsLoading(true); + console.log("loging in"); + const encryptedNsec = encryptMessage(nsec, passphrase); + if (encryptedNsec) { + localStorage.setItem("encrypted-nsec", encryptedNsec); + } + setIsLoading(false); + modal?.hide(); + } + + return ( + + ); +} diff --git a/components/Modals/Login.tsx b/components/Modals/Login.tsx index 6204820..8699be6 100644 --- a/components/Modals/Login.tsx +++ b/components/Modals/Login.tsx @@ -9,23 +9,29 @@ import { useNDK } from "@/app/_providers/ndk"; import useCurrentUser from "@/lib/hooks/useCurrentUser"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; +import AddPassphrase from "./AddPassphrase"; +import { decryptMessage } from "@/lib/nostr"; +import { toast } from "sonner"; export default function LoginModal() { const { loginWithNip07, loginWithSecret } = useNDK(); const { loginWithPubkey, currentUser } = useCurrentUser(); const [isLoading, setIsLoading] = useState(false); + const [showExtensionLogin, setShowExtensionLogin] = useState(true); const [nsec, setNsec] = useState(""); + const [passphrase, setPassphrase] = useState(""); + const [encryptedNsec, setEncryptedNsec] = useState(""); const modal = useModal(); useEffect(() => { const shouldReconnect = localStorage.getItem("shouldReconnect"); - const savedNsec = localStorage.getItem("nsec"); + const encryptedNsec_ = localStorage.getItem("encrypted-nsec"); const getConnected = async (shouldReconnect: string) => { let enabled: boolean | void = false; if (typeof window.nostr === "undefined") { - return; + return setShowExtensionLogin(false); } if (shouldReconnect === "true") { @@ -53,12 +59,13 @@ export default function LoginModal() { } return enabled; }; - if (savedNsec) { - handleLoginNsec(savedNsec); + if (encryptedNsec_) { + setEncryptedNsec(encryptedNsec_); } else if (shouldReconnect === "true") { getConnected(shouldReconnect); } }, []); + useEffect(() => { if (currentUser) { modal?.hide(); @@ -83,6 +90,27 @@ export default function LoginModal() { setIsLoading(false); modal?.hide(); } + async function handleLoginPassphrase() { + if (!encryptedNsec || passphrase) return; + setIsLoading(true); + + const decryptedNsec = decryptMessage(encryptedNsec, passphrase); + if (!decryptedNsec) { + setIsLoading(false); + toast.error("An error has occured"); + return; + } + const user = await loginWithSecret(decryptedNsec); + if (!user) { + throw new Error("NO auth"); + } + await loginWithPubkey(nip19.decode(user.npub).data.toString()); + if (typeof window.webln !== "undefined") { + await window.webln.enable(); + } + setIsLoading(false); + modal?.hide(); + } async function handleLoginNsec(nsec_?: string) { setIsLoading(true); console.log("loging in"); @@ -93,22 +121,40 @@ export default function LoginModal() { } console.log("LOGIN", user); await loginWithPubkey(nip19.decode(user.npub).data.toString()); - localStorage.setItem("nsec", nsec); - if (typeof window.webln !== "undefined") { await window.webln.enable(); } - console.log("connected "); setIsLoading(false); - modal?.hide(); + modal?.swap(); } return (