syndicate-nim/src/syndicate/capabilities.nim

53 lines
1.5 KiB
Nim

# SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense
runnableExamples:
from std/unittest import check
let sturdy = mint()
check $sturdy == """<ref {oid: "syndicate" sig: #x"69ca300c1dbfa08fba692102dd82311a"}>"""
import std/options
from std/sequtils import toSeq
import hashlib/misc/blake2
import preserves
import ./protocols/sturdy
from ./actors import Cap
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[Cap] =
var key: array[16, byte]
mint(key, toPreserve("syndicate", Cap))
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)
# mint utility moved to syndicate_utils/src/mintsturdyref.nim