import * as ed25519 from "@noble/ed25519"; import { AsBytes, DIDKey, InsecureCryptoKeyPair, Result, Signature, Signer, Verifier, } from "../interface.ts"; import { AuthorizationError, bytesToDid, didToBytes } from "./utils.ts"; export class NobleEd25519Signer implements Signer { #keypair: InsecureCryptoKeyPair; #verifier: NobleEd25519Verifier | null = null; constructor(keypair: InsecureCryptoKeyPair) { this.#keypair = keypair; } did() { return this.verifier.did(); } get verifier(): NobleEd25519Verifier { if (!this.#verifier) { this.#verifier = new NobleEd25519Verifier(this.#keypair.publicKey); } return this.#verifier; } serialize(): InsecureCryptoKeyPair { return this.#keypair; } async sign(payload: AsBytes): Promise, Error>> { try { const signature = await ed25519.signAsync( payload, this.#keypair.privateKey, ); return { ok: signature as Signature }; } catch (cause) { return { error: cause as Error }; } } static async fromRaw( privateKey: Uint8Array, ): Promise> { const publicKey = await ed25519.getPublicKeyAsync(privateKey); return new NobleEd25519Signer({ publicKey, privateKey }); } static async generate(): Promise> { const privateKey = ed25519.utils.randomPrivateKey(); return await NobleEd25519Signer.fromRaw(privateKey); } static deserialize(keypair: InsecureCryptoKeyPair) { return Promise.resolve(new NobleEd25519Signer(keypair)); } } export class NobleEd25519Verifier implements Verifier { #publicKey: Uint8Array; #did: ID; constructor(publicKey: Uint8Array) { this.#publicKey = publicKey; this.#did = bytesToDid(publicKey) as ID; } async verify( { signature, payload }: { payload: Uint8Array; signature: Uint8Array }, ) { if (await ed25519.verifyAsync(signature, payload, this.#publicKey)) { return { ok: {} }; } else { return { error: new AuthorizationError("Invalid signature") }; } } did(): ID { return this.#did; } static async fromDid( did: ID, ): Promise> { const bytes = didToBytes(did); return await NobleEd25519Verifier.fromRaw(bytes); } static fromRaw( rawPublicKey: Uint8Array, ): Promise> { return Promise.resolve(new NobleEd25519Verifier(rawPublicKey)); } }