mirror of
https://github.com/dergigi/boris.git
synced 2026-02-16 04:24:25 +01:00
- Add project structure with TypeScript, React, and Vite - Implement nostr authentication using browser extension (NIP-07) - Add NIP-51 compliant bookmark fetching and display - Create minimal UI with login and bookmark components - Integrate applesauce-core and applesauce-react libraries - Add responsive styling with dark/light mode support - Include comprehensive README with setup instructions This is a minimal MVP for a nostr bookmark client that allows users to view their bookmarks according to NIP-51 specification.
88 lines
2.1 KiB
TypeScript
88 lines
2.1 KiB
TypeScript
import { ProjPointType } from '@noble/curves/abstract/weierstrass';
|
|
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
import { bytesToHex, hexToBytes, randomBytes } from '@noble/hashes/utils';
|
|
import { bytesToNumber } from '../util/utils.js';
|
|
import type {
|
|
BlindSignature,
|
|
Proof,
|
|
SerializedBlindedMessage,
|
|
SerializedProof
|
|
} from '../common/index.js';
|
|
import { hashToCurve, pointFromHex } from '../common/index.js';
|
|
import { Witness } from '../common/index';
|
|
|
|
export type BlindedMessage = {
|
|
B_: ProjPointType<bigint>;
|
|
r: bigint;
|
|
secret: Uint8Array;
|
|
};
|
|
|
|
export function createRandomBlindedMessage(): BlindedMessage {
|
|
return blindMessage(randomBytes(32));
|
|
}
|
|
|
|
export function blindMessage(secret: Uint8Array, r?: bigint): BlindedMessage {
|
|
const Y = hashToCurve(secret);
|
|
if (!r) {
|
|
r = bytesToNumber(secp256k1.utils.randomPrivateKey());
|
|
}
|
|
const rG = secp256k1.ProjectivePoint.BASE.multiply(r);
|
|
const B_ = Y.add(rG);
|
|
return { B_, r, secret };
|
|
}
|
|
|
|
export function unblindSignature(
|
|
C_: ProjPointType<bigint>,
|
|
r: bigint,
|
|
A: ProjPointType<bigint>
|
|
): ProjPointType<bigint> {
|
|
const C = C_.subtract(A.multiply(r));
|
|
return C;
|
|
}
|
|
|
|
export function constructProofFromPromise(
|
|
promise: BlindSignature,
|
|
r: bigint,
|
|
secret: Uint8Array,
|
|
key: ProjPointType<bigint>
|
|
): Proof {
|
|
const A = key;
|
|
const C = unblindSignature(promise.C_, r, A);
|
|
const proof = {
|
|
id: promise.id,
|
|
amount: promise.amount,
|
|
secret,
|
|
C
|
|
};
|
|
return proof;
|
|
}
|
|
|
|
export const serializeProof = (proof: Proof): SerializedProof => {
|
|
return {
|
|
amount: proof.amount,
|
|
C: proof.C.toHex(true),
|
|
id: proof.id,
|
|
secret: new TextDecoder().decode(proof.secret),
|
|
witness: JSON.stringify(proof.witness)
|
|
};
|
|
};
|
|
|
|
export const deserializeProof = (proof: SerializedProof): Proof => {
|
|
return {
|
|
amount: proof.amount,
|
|
C: pointFromHex(proof.C),
|
|
id: proof.id,
|
|
secret: new TextEncoder().encode(proof.secret),
|
|
witness: proof.witness?JSON.parse(proof.witness):undefined
|
|
};
|
|
};
|
|
export const serializeBlindedMessage = (
|
|
bm: BlindedMessage,
|
|
amount: number
|
|
): SerializedBlindedMessage => {
|
|
return {
|
|
B_: bm.B_.toHex(true),
|
|
amount: amount
|
|
};
|
|
};
|