This is a rust implementation of the original runes library by Rusty Russell https://github.com/rustyrussell/runes.
Runes are extendable authorization cookies, similar to Macaroons https://research.google/pubs/pub41892/ but simpler. Extendable meaning that a client that has access to a cookie issued by a server can derive a cookie with extra restrictions that can not be removed from the derived cookie. This cookie can then possibly be passed to some other party to authenticate at the server.
To find out more about the motivation of runes see the original repository.
This implementation is fully compliant with the given set of test vectors. However, a clean implementation of functional values for alternatives to check on are currently missing. These will be part of a future update.
- Compliant with test vectors
- Functional checks on values
- Full crate documentation
(See the original repository for an in-depth explanation)
A rune is a set of restrictions that have to be passed. A restriction consists of one or more alternatives where at least one alternative has to pass.
An alternative is a string of the form (no spaces):
ALTERNATIVE := FIELDNAME CONDITION VALUE
FIELDNAME
contains only UTF-8 characters excluding punctuation characters:
! " # $ % & ' ( ) * +, - . / : ; < = > ? @ [ \ ] ^ _ \` { | } ~
Still, the punctuation characters can appear inside a VALUE
but &
, |
and \\
must be escaped with \
, as these are used to separate alternatives and restrictions.
CONDITION
is one of the following values with the corresponding check
CONDITION |
check |
---|---|
! |
field is missing |
= |
exists and exactly equals |
/ |
exists and is not exactly equal |
^ |
exists and begins with |
$ |
exists and ends with |
~ |
exists and contains |
< |
exists, is valid integer (may be signed), and numerically less than |
> |
exists, is valid integer (may be signed), and numerically greater than |
{ |
exists and lexicographically less than (or shorter) |
} |
exists and lexicographically greater than (or longer) |
# |
comment (always pass) |
A restriction is a group of alternatives chained by a logically OR
condition represented by |
; restrictions are separated by &
. Example rune:
cmd=foo|cmd=bar&subcmd!|subcmd={get
The first restriction requires cmd
to be foo
or bar
, the second requires that subcmd
is not present, or is lexicographically less than (or shorter) get
.
Every rune comes with a SHA-256 authentication code that ensures that no restriction can be striped from the rune. The basis for every authcode
is a secret (less than 56 bytes), that is only known by the server that issues the rune.
From this authbase
every restriction is appended to a rune with the following update to the authcode
, assuming that the secret has been treated the same way:
- Pad the restriction (the secret for the
authbase
) as per SHA-256 such that the result is a multiple of 64:- append
0x80
. - append
0
s (such that the result is a multiple of 64). - append the big-endian 64-bit bitcount (len) of the restriction.
- append
This way, the authcode
is always a SHA-256 digest.
A derivation is then achieved by adding a new restriction to the rune and updating the authcode
.
Runes are base64 encoded (URL safe), starting with the SHA-256 authcode
, followed by the restrictions (one or more) separated by &
.
For more insights additional infos and examples visit the original repo https://github.com/rustyrussell/runes.