Client key

This commit is contained in:
2026-08-18 18:49:31 +02:00
parent e9fe71784a
commit bb8994bb7e
7 changed files with 47 additions and 24 deletions
+2 -2
View File
@@ -12,7 +12,7 @@ pub struct Account {
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct AccountsFile { pub struct AccountsFile {
pub active_account: Option<usize>, pub active_account: usize,
pub accounts: Vec<Account>, pub accounts: Vec<Account>,
} }
@@ -39,7 +39,7 @@ pub fn get_accounts(app: AppHandle) -> Result<AccountsFile, String> {
let path = accounts_file_path(&app)?; let path = accounts_file_path(&app)?;
if !path.exists() { if !path.exists() {
return Ok(AccountsFile { return Ok(AccountsFile {
active_account: None, active_account: 0,
accounts: Vec::new(), accounts: Vec::new(),
}); });
} }
+7 -2
View File
@@ -1,23 +1,28 @@
import { useRef } from "react"; import { useReducer, useRef } from "react";
import Enclave from "@/app/app"; import Enclave from "@/app/app";
import ServerList from "./components/view/serverList"; import ServerList from "./components/view/serverList";
import { NewProfilePage } from "./components/view/NewProfileView"; import { NewProfilePage } from "./components/view/NewProfileView";
export default function App() { export default function App() {
const appRef = useRef<Enclave | null>(null); const appRef = useRef<Enclave | null>(null);
const [, forceRender] = useReducer((x) => x + 1, 0);
if (!appRef.current) { if (!appRef.current) {
appRef.current = new Enclave(); appRef.current = new Enclave();
appRef.current.forceRender = forceRender;
appRef.current appRef.current
.init() .init()
.then(() => { .then(() => {
console.log("Encalve initialized"); console.log("Encalve initialized");
forceRender();
}) })
.catch(console.error); .catch(console.error);
} }
return ( return (
<main className="size-screen"> <main className="size-screen">
{!appRef.current.accounts || {appRef.current?.accounts &&
appRef.current.accounts.accounts.length === 0 ? ( appRef.current.accounts.accounts.length === 0 ? (
<NewProfilePage appRef={appRef} /> <NewProfilePage appRef={appRef} />
) : ( ) : (
+23 -7
View File
@@ -1,8 +1,7 @@
import { import {
getHostname,
getHTTPUrl, getHTTPUrl,
getServerList, getServerList,
getWSUrl,
KnownServer,
ServerList, ServerList,
} from "@/lib/serverList"; } from "@/lib/serverList";
import EnclaveServer from "./server"; import EnclaveServer from "./server";
@@ -29,16 +28,14 @@ ed.hashes.sha512 = sha512;
* reach into `EnclaveServer` or `EnclaveWebSocket` directly. * reach into `EnclaveServer` or `EnclaveWebSocket` directly.
*/ */
export default class Enclave { export default class Enclave {
private clientSecretKey: Uint8Array;
private clientPublicKey: Uint8Array;
public accounts?: AccountsFile; public accounts?: AccountsFile;
public server?: EnclaveServer; public server?: EnclaveServer;
public serverList: ServerList; public serverList: ServerList;
public forceRender: () => void;
public constructor() { public constructor() {
this.clientSecretKey = ed.utils.randomSecretKey();
this.clientPublicKey = ed.getPublicKey(this.clientSecretKey);
this.serverList = {}; this.serverList = {};
this.forceRender = () => {};
} }
public async init() { public async init() {
@@ -51,7 +48,18 @@ export default class Enclave {
this.server.disconnect(); this.server.disconnect();
} }
this.server = new EnclaveServer(getWSUrl(hostname, isSecure)); this.server = new EnclaveServer(getHostname(hostname), isSecure);
const clientSecretKey = this.getClientSecretKey();
if (!clientSecretKey) {
console.error("Failed to get client key");
return;
}
const clientPublicKey = ed.getPublicKey(clientSecretKey);
await this.server.connect(clientPublicKey, clientSecretKey);
if (!this.server.serverPublicKey) { if (!this.server.serverPublicKey) {
console.error("Failed to get public key"); console.error("Failed to get public key");
@@ -68,4 +76,12 @@ export default class Enclave {
publicKey: base58.encode(this.server.serverPublicKey), publicKey: base58.encode(this.server.serverPublicKey),
}; };
} }
public getClientSecretKey() {
if (!this.accounts) return null;
const account = this.accounts?.accounts[this.accounts.activeAccount];
return account ? base58.decode(account.privateKey) : null;
}
} }
+7 -2
View File
@@ -2,6 +2,7 @@ import { base58 } from "@scure/base";
import * as ed from "@noble/ed25519"; import * as ed from "@noble/ed25519";
import EnclaveWebSocket from "./ws"; import EnclaveWebSocket from "./ws";
import { sha512 } from "@noble/hashes/sha2.js"; import { sha512 } from "@noble/hashes/sha2.js";
import { getWSUrl } from "@/lib/serverList";
ed.hashes.sha512 = sha512; ed.hashes.sha512 = sha512;
@@ -24,10 +25,12 @@ ed.hashes.sha512 = sha512;
export default class EnclaveServer { export default class EnclaveServer {
public serverPublicKey?: Uint8Array; public serverPublicKey?: Uint8Array;
public hostname: string; public hostname: string;
public isSecure: boolean;
public websocket?: EnclaveWebSocket; public websocket?: EnclaveWebSocket;
public constructor(hostname: string) { public constructor(hostname: string, isSecure: boolean) {
this.hostname = hostname; this.hostname = hostname;
this.isSecure = isSecure;
} }
public disconnect() { public disconnect() {
@@ -39,7 +42,9 @@ export default class EnclaveServer {
clientPublicKey: Uint8Array, clientPublicKey: Uint8Array,
clientSecretKey: Uint8Array, clientSecretKey: Uint8Array,
) { ) {
this.websocket = new EnclaveWebSocket(this.hostname); this.websocket = new EnclaveWebSocket(
getWSUrl(this.hostname, this.isSecure),
);
const publicKeyString = base58.encode(clientPublicKey); const publicKeyString = base58.encode(clientPublicKey);
+1 -1
View File
@@ -14,7 +14,7 @@ export default class EnclaveWebSocket {
public constructor(hostname: string) { public constructor(hostname: string) {
this.onOpenQueue = new Array(); this.onOpenQueue = new Array();
this.websocket = new WebSocket("ws://" + hostname); this.websocket = new WebSocket(hostname);
this.websocket.onopen = () => { this.websocket.onopen = () => {
this.onOpenQueue.forEach((fun) => fun()); this.onOpenQueue.forEach((fun) => fun());
}; };
+1 -1
View File
@@ -6,7 +6,7 @@ export interface Account {
} }
export interface AccountsFile { export interface AccountsFile {
activeAccount: number | null; activeAccount: number;
accounts: Account[]; accounts: Account[];
} }
+6 -9
View File
@@ -18,16 +18,13 @@ export async function getServerList(): Promise<ServerList> {
} }
export function getHTTPUrl(hostname: string, isSecure: boolean, path: string) { export function getHTTPUrl(hostname: string, isSecure: boolean, path: string) {
return ( return (isSecure ? "https://" : "http://") + getHostname(hostname) + path;
(isSecure ? "https://" : "http://") +
(hostname.includes(":") ? hostname : hostname + ":3415") +
path
);
} }
export function getWSUrl(hostname: string, isSecure: boolean) { export function getWSUrl(hostname: string, isSecure: boolean) {
return ( return (isSecure ? "wss://" : "ws://") + getHostname(hostname);
(isSecure ? "wss://" : "ws://") + }
(hostname.includes(":") ? hostname : hostname + ":3415")
); export function getHostname(hostname: string) {
return hostname.includes(":") ? hostname : hostname + ":3415";
} }