import { bytesToString, createEddsaKeyPair, decodeCrock, decryptWithDerivedKey, eddsaGetPublic, encodeCrock, encryptWithDerivedKey, getRandomBytesF, stringToBytes, } from "@gnu-taler/taler-util"; export interface Account { accountId: AccountId; signingKey: SigningKey; } /** * Restore previous session and unlock account with password * * @param salt string from which crypto params will be derived * @param key secured private key * @param password password for the private key * @returns */ export async function unlockAccount( account: LockedAccount, password: string, ): Promise { const rawKey = decodeCrock(account); const rawPassword = stringToBytes(password); const signingKey = (await decryptWithDerivedKey( rawKey, rawPassword, password, ).catch((e: Error) => { throw new UnwrapKeyError(e.message); })) as SigningKey; const publicKey = eddsaGetPublic(signingKey); const accountId = encodeCrock(publicKey) as AccountId; return { accountId, signingKey }; } declare const opaque_Account: unique symbol; export type LockedAccount = string & { [opaque_Account]: true }; declare const opaque_AccountId: unique symbol; export type AccountId = string & { [opaque_AccountId]: true }; declare const opaque_SigningKey: unique symbol; export type SigningKey = Uint8Array & { [opaque_SigningKey]: true }; /** * Create new account (secured private key) * secured with the given password * * @param sessionId * @param password * @returns */ export async function createNewAccount( password: string, ): Promise { const { eddsaPriv, eddsaPub } = createEddsaKeyPair(); const key = stringToBytes(password); const protectedPrivKey = await encryptWithDerivedKey( getRandomBytesF(24), key, eddsaPriv, password, ); const signingKey = eddsaPriv as SigningKey; const accountId = encodeCrock(eddsaPub) as AccountId; const safe = encodeCrock(protectedPrivKey) as LockedAccount; return { accountId, signingKey, safe }; } export class UnwrapKeyError extends Error { public cause: string; constructor(cause: string) { super(`Recovering private key failed on: ${cause}`); this.cause = cause; } }