noise-core.ts

4.0 KB · raw

1import {2  initSync,3  WasmNoiseSession,4} from "./noise-core-wasm/peach_noise_core";5import { PEACH_NOISE_CORE_WASM_BASE64 } from "./noise-core-wasm/peach_noise_core_bytes";67export interface RustNoiseSession {8  encrypt(plaintext: Uint8Array): Uint8Array;9  decrypt(ciphertext: Uint8Array): Uint8Array;10  readonly handshakeHash: Uint8Array;11  rekeyOutgoing(): void;12  rekeyIncoming(): void;13  close(): void;14}1516export interface RustNoiseKeyPair {17  publicKey: Uint8Array;18  secretKey: Uint8Array;19}2021let initialized = false;2223function ensureInitialized(): void {24  if (initialized) return;25  const binary = atob(PEACH_NOISE_CORE_WASM_BASE64);26  const bytes = new Uint8Array(binary.length);27  for (let index = 0; index < binary.length; index += 1) {28    bytes[index] = binary.charCodeAt(index);29  }30  try {31    initSync({ module: bytes });32    initialized = true;33  } finally {34    bytes.fill(0);35  }36}3738function session(native: WasmNoiseSession): RustNoiseSession {39  let closed = false;40  const requireOpen = () => {41    if (closed) throw new Error("Noise session is closed");42  };43  return {44    encrypt(plaintext) {45      requireOpen();46      return native.encrypt(plaintext);47    },48    decrypt(ciphertext) {49      requireOpen();50      return native.decrypt(ciphertext);51    },52    get handshakeHash() {53      requireOpen();54      return native.handshakeHash;55    },56    rekeyOutgoing() {57      requireOpen();58      native.rekeyOutgoing();59    },60    rekeyIncoming() {61      requireOpen();62      native.rekeyIncoming();63    },64    close() {65      if (closed) return;66      closed = true;67      native.free();68    },69  };70}7172async function driveInitiator(73  native: WasmNoiseSession,74  send: (message: Uint8Array) => Promise<void>,75  receive: () => Promise<Uint8Array>,76): Promise<RustNoiseSession> {77  try {78    await send(native.writeHandshake(new Uint8Array(0)));79    native.readHandshake(await receive());80    return session(native);81  } catch (error) {82    native.free();83    throw error;84  }85}8687async function driveResponder(88  native: WasmNoiseSession,89  send: (message: Uint8Array) => Promise<void>,90  receive: () => Promise<Uint8Array>,91): Promise<RustNoiseSession> {92  try {93    native.readHandshake(await receive());94    await send(native.writeHandshake(new Uint8Array(0)));95    return session(native);96  } catch (error) {97    native.free();98    throw error;99  }100}101102export async function rustNoiseNkInitiator(103  responderStaticPublicKey: Uint8Array,104  send: (message: Uint8Array) => Promise<void>,105  receive: () => Promise<Uint8Array>,106): Promise<RustNoiseSession> {107  ensureInitialized();108  const native = WasmNoiseSession.nkInitiator(responderStaticPublicKey);109  return driveInitiator(native, send, receive);110}111112export async function rustNoiseNkResponder(113  ourStaticPrivateKey: Uint8Array,114  ourStaticPublicKey: Uint8Array,115  send: (message: Uint8Array) => Promise<void>,116  receive: () => Promise<Uint8Array>,117): Promise<RustNoiseSession> {118  ensureInitialized();119  const native = WasmNoiseSession.nkResponder(ourStaticPrivateKey, ourStaticPublicKey);120  return driveResponder(native, send, receive);121}122123export async function rustNoiseKkInitiator(124  ourStaticPrivateKey: Uint8Array,125  ourStaticPublicKey: Uint8Array,126  responderStaticPublicKey: Uint8Array,127  send: (message: Uint8Array) => Promise<void>,128  receive: () => Promise<Uint8Array>,129): Promise<RustNoiseSession> {130  ensureInitialized();131  const native = WasmNoiseSession.kkInitiator(132    ourStaticPrivateKey,133    ourStaticPublicKey,134    responderStaticPublicKey,135  );136  return driveInitiator(native, send, receive);137}138139export async function rustNoiseKkResponder(140  ourStaticPrivateKey: Uint8Array,141  ourStaticPublicKey: Uint8Array,142  expectedInitiatorStaticPublicKey: Uint8Array,143  send: (message: Uint8Array) => Promise<void>,144  receive: () => Promise<Uint8Array>,145): Promise<RustNoiseSession> {146  ensureInitialized();147  const native = WasmNoiseSession.kkResponder(148    ourStaticPrivateKey,149    ourStaticPublicKey,150    expectedInitiatorStaticPublicKey,151  );152  return driveResponder(native, send, receive);153}154