# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-License-Identifier: Unlicense runnableExamples: from std/unittest import check let sturdy = mint() check $sturdy == """""" import std/options from std/sequtils import toSeq import hashlib/misc/blake2 import preserves import ./protocols/sturdy from ./actors import Ref export `$` proc hmac(key, data: openarray[byte]): seq[byte] = count[Hmac[BLAKE2S_256]](key, data).data[0..15].toSeq proc mint*[T](key: openarray[byte]; oid: Preserve[T]): SturdyRef[T] = SturdyRef[T](parameters: { "oid": oid, "sig": hmac(key, encode(oid)).toPreserve(T), }.toDictionary, ) proc mint*(): SturdyRef[Ref] = var key: array[16, byte] mint(key, toPreserve("syndicate", Ref)) proc attenuate*[T](r: SturdyRef[T]; caveats: seq[Caveat]): SturdyRef[T] = result = SturdyRef[T]( oid: r.oid, caveatChain: r.caveatChain, sig: hmac(r.sig, encode caveats)) result.caveatChain.add caveats proc validate*[T](key: openarray[byte]; sturdy: SturdyRef[T]): bool = let oid = step(sturdy.parameters, Symbol"oid") if oid.isSome: let ctrl = step(sturdy.parameters, Symbol"sig") if ctrl.isSome: var sig = hmac(key, oid.get.encode) let caveats = step(sturdy.parameters, Symbol"caveats") if caveats.isSome and caveats.get.isSequence: for cav in caveats.get.sequence: sig = hmac(sig, encode cav) result = (sig == ctrl.get.bytes) when isMainModule: from os import commandLineParams var key: array[16, byte] case readBytes(stdin, key, 0, 16) of 16: discard of 0: stderr.writeLine "using null key" else: quit "expected sixteen bytes of key from stdin" var oids: seq[Preserve[void]] for p in commandLineParams(): add(oids, parsePreserves p) if oids.len == 0: oids.add(toPreserve "syndicate") for oid in oids: let sturdy = mint(key, oid) doAssert validate(key, sturdy) stdout.writeLine(sturdy)