Store the bunkerSeckey in the keyring, include only the pubkey in the plaintext connection storage
This commit is contained in:
parent
36427f52d7
commit
fdb53c8906
|
@ -2,6 +2,7 @@ import { NostrSigner, NRelay1, NSecSigner } from '@nostrify/nostrify';
|
|||
import { generateSecretKey } from 'nostr-tools';
|
||||
|
||||
import { NBunker } from 'soapbox/features/nostr/NBunker';
|
||||
import { keyring } from 'soapbox/features/nostr/keyring';
|
||||
import { useBunkerStore } from 'soapbox/hooks/nostr/useBunkerStore';
|
||||
import { type AppDispatch } from 'soapbox/store';
|
||||
|
||||
|
@ -53,11 +54,13 @@ function logInNostr(signer: NostrSigner, relay: NRelay1) {
|
|||
const accessToken = dispatch(authLoggedIn(token)).access_token as string;
|
||||
const bunkerState = useBunkerStore.getState();
|
||||
|
||||
keyring.add(authorization.seckey);
|
||||
|
||||
bunkerState.connect({
|
||||
pubkey,
|
||||
accessToken,
|
||||
authorizedPubkey,
|
||||
bunkerSeckey: authorization.seckey,
|
||||
bunkerPubkey,
|
||||
});
|
||||
|
||||
await dispatch(verifyCredentials(accessToken));
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { NSchema as n } from '@nostrify/nostrify';
|
||||
import { produce } from 'immer';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { z } from 'zod';
|
||||
import { create } from 'zustand';
|
||||
// eslint-disable-next-line import/extensions
|
||||
|
@ -19,15 +19,15 @@ interface BunkerConnection {
|
|||
accessToken: string;
|
||||
/** Pubkey of the app authorized to sign events with this connection. */
|
||||
authorizedPubkey: string;
|
||||
/** Secret key for this connection. NIP-46 responses will be signed by this key. */
|
||||
bunkerSeckey: Uint8Array;
|
||||
/** Pubkey for this connection. Secret key is stored in the keyring. NIP-46 responses will be signed by this key. */
|
||||
bunkerPubkey: string;
|
||||
}
|
||||
|
||||
const connectionSchema = z.object({
|
||||
pubkey: z.string(),
|
||||
const connectionSchema: z.ZodType<BunkerConnection> = z.object({
|
||||
pubkey: n.id(),
|
||||
accessToken: z.string(),
|
||||
authorizedPubkey: z.string(),
|
||||
bunkerSeckey: z.custom<Uint8Array>((value) => value instanceof Uint8Array),
|
||||
authorizedPubkey: n.id(),
|
||||
bunkerPubkey: n.id(),
|
||||
});
|
||||
|
||||
interface BunkerState {
|
||||
|
@ -65,7 +65,7 @@ export const useBunkerStore = create<BunkerState>()(
|
|||
getItem(name) {
|
||||
const value = localStorage.getItem(name);
|
||||
|
||||
const connections = jsonSchema(nsecReviver)
|
||||
const connections = jsonSchema()
|
||||
.pipe(filteredArray(connectionSchema))
|
||||
.catch([])
|
||||
.parse(value);
|
||||
|
@ -73,7 +73,7 @@ export const useBunkerStore = create<BunkerState>()(
|
|||
return { state: { connections } };
|
||||
},
|
||||
setItem(name, { state }) {
|
||||
localStorage.setItem(name, JSON.stringify(state.connections, nsecReplacer));
|
||||
localStorage.setItem(name, JSON.stringify(state.connections));
|
||||
},
|
||||
removeItem(name) {
|
||||
localStorage.removeItem(name);
|
||||
|
@ -82,21 +82,3 @@ export const useBunkerStore = create<BunkerState>()(
|
|||
},
|
||||
),
|
||||
);
|
||||
|
||||
/** Encode Uint8Arrays into nsec strings. */
|
||||
function nsecReplacer(_key: string, value: unknown): unknown {
|
||||
if (value instanceof Uint8Array) {
|
||||
return nip19.nsecEncode(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/** Decode nsec strings into Uint8Arrays. */
|
||||
function nsecReviver(_key: string, value: unknown): unknown {
|
||||
if (typeof value === 'string' && value.startsWith('nsec1')) {
|
||||
return nip19.decode(value as `nsec1${string}`).data;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
|
@ -1,6 +1,4 @@
|
|||
import { NSecSigner } from '@nostrify/nostrify';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { keyring } from 'soapbox/features/nostr/keyring';
|
||||
import { useAppSelector } from 'soapbox/hooks';
|
||||
|
@ -16,7 +14,7 @@ export function useSigner() {
|
|||
}
|
||||
});
|
||||
|
||||
const { pubkey, bunkerSeckey, authorizedPubkey } = connection ?? {};
|
||||
const { pubkey, bunkerPubkey, authorizedPubkey } = connection ?? {};
|
||||
|
||||
const { data: signer, ...rest } = useQuery({
|
||||
queryKey: ['nostr', 'signer', pubkey ?? ''],
|
||||
|
@ -35,15 +33,9 @@ export function useSigner() {
|
|||
enabled: !!pubkey,
|
||||
});
|
||||
|
||||
const bunkerSigner = useMemo(() => {
|
||||
if (bunkerSeckey) {
|
||||
return new NSecSigner(bunkerSeckey);
|
||||
}
|
||||
}, [bunkerSeckey]);
|
||||
|
||||
return {
|
||||
signer: signer ?? undefined,
|
||||
bunkerSigner,
|
||||
bunkerSigner: bunkerPubkey ? keyring.get(bunkerPubkey) : undefined,
|
||||
authorizedPubkey,
|
||||
...rest,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue