2023-05-03 17:10:33 +00:00
|
|
|
# SPDX-FileCopyrightText: ☭ Emery Hemingway
|
2021-09-21 14:39:15 +00:00
|
|
|
# SPDX-License-Identifier: Unlicense
|
|
|
|
|
2023-05-18 10:20:44 +00:00
|
|
|
runnableExamples:
|
|
|
|
from std/unittest import check
|
|
|
|
let sturdy = mint()
|
|
|
|
check $sturdy == """<ref {oid: "syndicate" sig: #x"69ca300c1dbfa08fba692102dd82311a"}>"""
|
|
|
|
|
|
|
|
import std/options
|
2023-05-03 17:10:33 +00:00
|
|
|
from std/sequtils import toSeq
|
|
|
|
import hashlib/misc/blake2
|
|
|
|
|
2021-09-21 14:39:15 +00:00
|
|
|
import preserves
|
2023-05-03 17:10:33 +00:00
|
|
|
import ./protocols/sturdy
|
2023-07-24 15:13:36 +00:00
|
|
|
from ./actors import Cap
|
2021-09-07 10:01:42 +00:00
|
|
|
|
2022-12-08 04:51:26 +00:00
|
|
|
export `$`
|
|
|
|
|
2023-05-03 17:10:33 +00:00
|
|
|
proc hmac(key, data: openarray[byte]): seq[byte] =
|
|
|
|
count[Hmac[BLAKE2S_256]](key, data).data[0..15].toSeq
|
|
|
|
|
2022-12-08 08:15:01 +00:00
|
|
|
proc mint*[T](key: openarray[byte]; oid: Preserve[T]): SturdyRef[T] =
|
2023-05-18 10:20:44 +00:00
|
|
|
SturdyRef[T](parameters: {
|
|
|
|
"oid": oid,
|
|
|
|
"sig": hmac(key, encode(oid)).toPreserve(T),
|
|
|
|
}.toDictionary,
|
|
|
|
)
|
2021-10-27 16:54:20 +00:00
|
|
|
|
2023-07-24 15:13:36 +00:00
|
|
|
proc mint*(): SturdyRef[Cap] =
|
2023-04-10 21:56:51 +00:00
|
|
|
var key: array[16, byte]
|
2023-07-24 15:13:36 +00:00
|
|
|
mint(key, toPreserve("syndicate", Cap))
|
2023-04-10 21:56:51 +00:00
|
|
|
|
2023-05-18 10:20:44 +00:00
|
|
|
proc attenuate*[T](r: SturdyRef[T]; caveats: seq[Caveat]): SturdyRef[T] =
|
2022-12-08 08:15:01 +00:00
|
|
|
result = SturdyRef[T](
|
2021-09-07 10:01:42 +00:00
|
|
|
oid: r.oid,
|
|
|
|
caveatChain: r.caveatChain,
|
2023-05-03 17:10:33 +00:00
|
|
|
sig: hmac(r.sig, encode caveats))
|
2021-09-07 10:01:42 +00:00
|
|
|
result.caveatChain.add caveats
|
|
|
|
|
2023-05-18 10:20:44 +00:00
|
|
|
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)
|
2022-12-08 04:51:26 +00:00
|
|
|
|
|
|
|
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)
|