OverviewFilesCommitsIssuesDocsReleasesPeers

anproto / examples / cli.js

111 lines · javascript ref:
#!/usr/bin/env node
/**
 * Mini CLI example for anproto
 *
 * Demonstrates the canonical 4 functions: gen → hash → sign → open
 *
 * Usage:
 *   node examples/cli.js gen                        Generate a new keypair
 *   node examples/cli.js hash <data>                Hash some data
 *   node examples/cli.js sign <hash> <keypair>      Sign a hash
 *   node examples/cli.js open <signature>           Open a signature
 *   node examples/cli.js demo                       Run a full round-trip
 *   node examples/cli.js challenges                 Demo the Challenges helper
 */

import { an, Challenges } from '../index.js'

const args = process.argv.slice(2)
const cmd = args[0]

async function main () {
  if (cmd === 'gen') {
    const k = await an.gen()
    console.log('keypair: %s', k)
    console.log('pubkey:  %s', an.publicKey(k))
  } else if (cmd === 'hash') {
    const data = args[1]
    if (!data) { console.error('Usage: cli.js hash <data>'); process.exit(1) }
    const h = await an.hash(data)
    console.log(h)
  } else if (cmd === 'sign') {
    const h = args[1]
    const k = args[2]
    if (!h || !k) { console.error('Usage: cli.js sign <hash> <keypair>'); process.exit(1) }
    const sig = await an.sign(h, k)
    console.log(sig)
  } else if (cmd === 'open') {
    const sig = args[1]
    if (!sig) { console.error('Usage: cli.js open <signature>'); process.exit(1) }
    try {
      const opened = await an.open(sig)
      const parsed = an.parse(opened)
      console.log('opened:    %s', opened)
      console.log('timestamp: %d (%s)', parsed.timestamp, new Date(parsed.timestamp).toISOString())
      console.log('hash:      %s', parsed.hash)
    } catch (err) {
      console.error('Invalid signature: %s', err.message)
      process.exit(1)
    }
  } else if (cmd === 'demo') {
    console.log('--- ANProto round-trip demo ---\n')

    const message = args[1] || 'Hello, ANProto!'
    console.log('1. Generate keypair')
    const k = await an.gen()
    console.log('   keypair: %s\n', k)

    console.log('2. Hash message: %j', message)
    const h = await an.hash(message)
    console.log('   hash: %s\n', h)

    console.log('3. Sign hash')
    const sig = await an.sign(h, k)
    console.log('   sig:  %s\n', sig)

    console.log('4. Open signature')
    const opened = await an.open(sig)
    const parsed = an.parse(opened)
    console.log('   opened:    %s', opened)
    console.log('   timestamp: %d (%s)', parsed.timestamp, new Date(parsed.timestamp).toISOString())
    console.log('   hash:      %s\n', parsed.hash)

    console.log('5. Verify hash matches')
    console.log('   match: %s', parsed.hash === h ? 'YES ✓' : 'NO ✗')
  } else if (cmd === 'challenges') {
    console.log('--- Challenges helper demo ---\n')
    const c = new Challenges({ ttl: 5000 })

    console.log('Generate 3 challenges:')
    const c1 = c.generate()
    const c2 = c.generate()
    const c3 = c.generate()
    console.log('  c1: %s', c1)
    console.log('  c2: %s', c2)
    console.log('  c3: %s', c3)
    console.log('  active: %d\n', c.size)

    console.log('Consume c2:')
    console.log('  consume(c2):  %s', c.consume(c2))
    console.log('  consume(c2):  %s (single-use)', c.consume(c2))
    console.log('  active: %d\n', c.size)

    console.log('Verify c1 still active:')
    console.log('  has(c1): %s', c.has(c1))
    console.log('  has(c2): %s', c.has(c2))
    console.log('  has(c3): %s', c.has(c3))

    c.destroy()
  } else {
    console.log('anproto example CLI')
    console.log('  gen                          Generate a keypair')
    console.log('  hash <data>                  Hash data')
    console.log('  sign <hash> <keypair>        Sign a hash')
    console.log('  open <signature>             Open a signature')
    console.log('  demo [message]               Full round-trip demo')
    console.log('  challenges                   Replay-protection helper demo')
  }
}

main().catch((err) => { console.error(err.message); process.exit(1) })