From 9c2fba56e0f68f976c1abe486f9fd3c6e93b437e Mon Sep 17 00:00:00 2001 From: polwex Date: Wed, 16 Jul 2025 11:59:08 +0700 Subject: 'm' --- components/login/ShipCredsForm.tsx | 39 ++++- lib/urbit/constants.ts | 288 +++++++++++++++++++++++++++++++++++++ lib/urbit/wallet.ts | 79 ++++++++++ lib/utils/bit.ts | 35 +++++ 4 files changed, 440 insertions(+), 1 deletion(-) create mode 100644 lib/urbit/constants.ts create mode 100644 lib/urbit/wallet.ts create mode 100644 lib/utils/bit.ts diff --git a/components/login/ShipCredsForm.tsx b/components/login/ShipCredsForm.tsx index ac58e86..d84a474 100644 --- a/components/login/ShipCredsForm.tsx +++ b/components/login/ShipCredsForm.tsx @@ -9,8 +9,15 @@ import { } from "react-native"; import PrimaryButton from "../PrimaryButton"; import { useState } from "react"; -import { createFancyPasskey, pkDecrypt, pkEncrypt } from "@/lib/passkey"; +import { + createFancyPasskey, + createPasskey, + pkDecrypt, + pkEncrypt, +} from "@/lib/passkey"; import toast, { Toaster } from "react-hot-toast"; +import { makeWalletFromP } from "@/lib/urbit/wallet"; +import { hex2buf } from "@/lib/utils/bit"; export function ShipForm() { const colors = lightColors; @@ -20,11 +27,35 @@ export function ShipForm() { const [encryptedTicket, setenc] = useState(""); const [isLoading, setIsLoading] = useState(false); async function onSubmit() { + const wallet = await makeWalletFromP(patp, ticket); + console.log("seed", wallet.ownership.seed); + const privkey = wallet.ownership.keys.private; + const clean = privkey.replace(/^0x/i, ""); + const byteLength = clean.length / 2; + toast(`bytes: ${byteLength}`); + const bufer = hex2buf(privkey); + toast(`buffer size: ${bufer.byteLength}`); + const ba = Uint8Array.fromHex(clean); + toast(`uintarray byte length: ${ba.byteLength}`); + console.log({ + bufl: bufer.length, + bufbl: bufer.byteLength, + ul: ba.length, + ubl: ba.byteLength, + }); + } + async function makeFPk() { console.log("running", { patp, ticket }); const passkey = await createFancyPasskey(); console.log({ passkey }); toast(passkey); } + async function makePk() { + console.log("running", { patp, ticket }); + const passkey = await createPasskey(); + if ("error" in passkey) return toast.error(passkey.error); + console.log({ passkey }); + } async function enc() { const done = await pkEncrypt(ticket); console.log({ encryptedTicket }); @@ -64,6 +95,12 @@ export function ShipForm() { style={{ marginTop: 0 }} isLoading={isLoading} /> + + point < MIN_STAR + ? GALAXY_ENTROPY_BITS + : point < MIN_PLANET + ? STAR_ENTROPY_BITS + : PLANET_ENTROPY_BITS; + +export const stripHexPrefix = (hex: string) => { + return hex.startsWith("0x") ? hex.slice(2) : hex; +}; +export const makeDeterministicTicket = (point: number, seed: string) => { + const bits = getTicketBitSize(point); + + const bytes = bits / 8; + + const pointSalt = Buffer.concat([ + Buffer.from(point.toString()), + Buffer.from("invites"), + ]); + const normalizedSeed = stripHexPrefix(seed); + const entropy = shas(Buffer.from(normalizedSeed, "hex"), pointSalt); + + const buf = entropy.slice(0, bytes); + const patq = ob.hex2patq(buf.toString("hex")); + return patq; +}; + +// return a wallet object +export const makeWalletFromP = async (patp: string, ticket: string) => { + const point = Number(ob.patp2dec(patp)); + return await makeWallet({ point, ticket }); +}; +export const makeWallet = async (data: { + point: number; + ticket: string; + boot?: boolean; + revision?: number; +}) => { + const config = { + ticket: data.ticket, + seedSize: SEED_LENGTH_BYTES, + point: data.point, + password: "", + revision: data.revision || 1, + boot: data.boot || false, + }; + + // This is here to notify anyone who opens console because the thread + // hangs, blocking UI updates so this cannot be done in the UI + console.log("Generating Wallet for point address: ", data.point); + + const wallet = await generateWallet(config); + console.log({ wallet }); + + return wallet; + // return new Promise(async (resolve, reject) => { + // // Use a web worker to process the data + // try { + // const processed = await walletgenWorker.generate(JSON.stringify(config)); + // resolve(processed); + // } catch (error) { + // reject(error); + // } + // }); +}; diff --git a/lib/utils/bit.ts b/lib/utils/bit.ts new file mode 100644 index 0000000..bc1ed1a --- /dev/null +++ b/lib/utils/bit.ts @@ -0,0 +1,35 @@ +import { sha256 } from "urbit-key-generation/src/utils"; + +export function shas(buf: Buffer, salt: Buffer) { + return sha256(xor(salt, sha256(buf))); +} + +export function xor(a: Buffer, b: Buffer) { + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + console.log("a", a); + console.log("b", b); + throw new Error("only xor buffers!"); + } + const length = Math.max(a.byteLength, b.byteLength); + const result = new Uint8Array(length); + for (let i = 0; i < length; i++) { + result[i] = a[i] ^ b[i]; + } + return result; +} + +export function shaf(buf: Buffer, salt: Buffer) { + const result = shas(buf, salt); + const halfway = result.length / 2; + const front = result.slice(0, halfway); + const back = result.slice(halfway, result.length); + return xor(front, back); +} + +export function hex2buf(hex: string) { + return Buffer.from(hex, "hex").reverse(); +} + +export function buf2hex(buf: Uint8Array) { + return Buffer.from(buf).reverse().toString("hex"); +} -- cgit v1.2.3