crypto.mjs raw

   1  // TinyJS Runtime — secp256k1 Crypto Bridge (WASM)
   2  // init() must be called (and awaited) before any crypto operations.
   3  
   4  import { Slice } from './builtin.mjs';
   5  
   6  let _secp = null;
   7  
   8  // init loads and initializes the secp256k1 WASM module.
   9  // Called from $entry.mjs before main().
  10  // Gracefully skips if WASM module is not available (e.g. app delegates crypto to extension).
  11  export async function init() {
  12    // Crypto is handled by schnorr.mjs (jsbridge) — no WASM module needed.
  13  }
  14  
  15  function sliceToU8(s) {
  16    if (s instanceof Uint8Array) return s;
  17    if (typeof s === 'string') return new TextEncoder().encode(s);
  18    const u = new Uint8Array(s.$length);
  19    for (let i = 0; i < s.$length; i++) {
  20      u[i] = s.$array[s.$offset + i];
  21    }
  22    return u;
  23  }
  24  
  25  function u8ToSlice(u8) {
  26    if (u8 === null || u8 === undefined) return null;
  27    const arr = new Array(u8.length);
  28    for (let i = 0; i < u8.length; i++) arr[i] = u8[i];
  29    return new Slice(arr, 0, u8.length, u8.length);
  30  }
  31  
  32  export function PubKeyFromSecKey(seckey) {
  33    const result = _secp.getPublicKey(sliceToU8(seckey));
  34    return u8ToSlice(result);
  35  }
  36  
  37  export function SignSchnorr(seckey, msg, auxRand) {
  38    const result = _secp.sign(sliceToU8(seckey), sliceToU8(msg), sliceToU8(auxRand));
  39    if (result === null || result === undefined) return null;
  40    return u8ToSlice(result);
  41  }
  42  
  43  export function VerifySchnorr(pubkey, msg, sig) {
  44    return _secp.verify(sliceToU8(pubkey), sliceToU8(msg), sliceToU8(sig));
  45  }
  46