Runes - Simple Cookies You Can Extend (similar to Macaroons)

Overview

Runes - Simple Cookies You Can Extend (similar to Macaroons)

https://research.google/pubs/pub41892/ is a paper called "Macaroons: Cookies with Contextual Caveats for Decentralized Authorization in the Cloud". It has one good idea, some extended ideas nobody implements, and lots and lots of words.

The idea: a server issues a cookie to Alice. She can derive cookies with extra restrictions and hand them to Bob and Carol to send back to the server, and they can't remove the restrictions.

But they did it using a Message Authetication Code (MAC, get it?), which is actually counter-productive, since it's simpler and better to use Length Extension to achieve the same results. I call that a Rune; this version really only handles strings, but you can use hex or another encoding.

Rune Language

A rune is a series of restrictions; you have to pass all of them (so appending a new one always makes the rune less powerful). Each restriction is one or more alternatives ("cmd=foo OR cmd=bar"), any one of which can pass.

The form of each alternative is a simple string:

ALTERNATIVE := FIELDNAME CONDITION VALUE

FIELDNAME contains only UTF-8 characters, exclusive of ! " # $ % & ' ( ) * +, - . / : ; ? @ [ \ ] ^ _ ` { | } ~ (C's ispunct()). These can appear inside a VALUE, but &, | and \\ must be escaped with \ (escaping is legal for any character, but unnecessary).

CONDITION is one of the following values:

  • !: Pass if field is missing (value ignored)
  • =: Pass if exists and exactly equals
  • ^: Pass if exists and begins with
  • $: Pass if exists and ends with
  • ~: Pass if exists and contains
  • <: Pass if exists, is a valid decimal (may be signed), and numerically less than
  • >: Pass if exists, is a valid decimal (may be signed), and numerically greater than
  • }: Pass if exists and lexicograpically greater than (or longer)
  • {: Pass if exists and lexicograpically less than (or shorter)
  • #: Always pass: no condition, this is a comment.

Grouping using ( and ) may be added in future.

A restriction is a group of alternatives separated by |; restrictions are separated by &. e.g.

cmd=foo | cmd=bar
& subcmd! | subcmd{get

The first requires cmd be present, and to be foo or bar. The second requires that subcmd is not present, or is lexicographically less than get. Both must be true for authorization to succeed.

Rune Authorization

A run also comes with a SHA-256 authentication code. This is generated as SHA-256 of the following bytestream:

  1. The secret (less than 56 bytes, known only to the server which issued it).
  2. For every restriction:
    1. Pad the stream as per SHA-256 (i.e. append 0x80, then zeroes, then the big-endian 64-bit bitcount so far, such that it's a multiple of 64 bytes).
    2. Append the restriction.

By using the same padding scheme as SHA-256 usually uses to end the data, we have the property that we can initialize the SHA-256 function with the result from any prior restriction, and continue.

The server can validate the rune authorization by repeating this procedure and checking the result.

Rune Encoding

Runes are encoded as base64, starting with the 256-bit SHA256 authentication code, the followed by one or more restrictions separated by &.

Not because base64 is good, but because it's familiar to Web people; we use RFC3548 with + and / replaced by - and _ to make it URL safe.

API Example

Here's the server, making you a rune! (spoiler: it's "-YpZTBZ4Tb5SsUz3XIukxBxR619iEthm9oNJnC0LxZM=")

import runes
import secrets

# Secret determined by fair dice roll.
secret = bytes([5] * 16)

# Make an unrestricted rune.
rune = runes.MasterRune(secret)

# We could add our own restrictions here, if we wanted.
print("Your rune is {}".format(rune.to_base64()))

Here's the server, checking a rune. You will need to define what conditions you provide for the rune to test; one of the most useful ones is time, but other common things are the resource being accessed, (e.g. URL, or command and parameters), or who is accessing it (assuming you have authenticated them already in some way).

import runes
import time
import sys

secret = bytes([5] * 16)

# In real life, this would come from the web data.
runestring = sys.argv[1]

# This checks the format is correct, it's authorized, an that it meets
# our values.  I assume we have values time (UNIX, seconds since
# 1970), command and optional id.
# (You can also use rune.check() if you don't care *why* it failed)
ok, whyfail = rune.check_with_reason(secret, runestring,
                                     {'time': int(time.time()),
                                      'command': 'somecommand',
                                      'id': 'DEADBEEF'})
if not ok:
    print("Rune restrictions failed: {}".format(whyfail))
    sys.exit(1)

print("Yes, you passed!")

Here's the client Alice. She gets the rune and gives Bob a variant that can only be used for 1 minute:

import runes
import time

# In real life, this would come from the web data.
runestring = sys.argv[1]

# You'd catch exceptions here, usually.
rune = runes.from_base64(runestring)

# You can construct a Restriction class from a sequence of Alternative
# but it's easier to use decode() to translate a string
rune.add_restriction(rune.Restriction.decode("time < {}".format((int)time.time() + 60))

print("Your restricted rune is {}".format(rune.to_base64()))

You can find more examples in the examples/ subdirectory.

Author

Rusty Russell wrote it; but I blame @roasbeef for raving about them long enough at LnConf that I actually read the paper. It only took me 18 months to find a day to implement them.

Owner
Rusty Russell
GPG: 15EE 8D6C AB0E 7F0C F999 BFCB D920 0E6C D1AD B8F1 Rusty Russell
Rusty Russell
A random cats photos python module

A random cats photos python module

Fayas Noushad 6 Dec 01, 2021
A python tool give n number of inputs and parallelly you will get a output by separetely

http-status-finder Hello Everyone!! This is kavisurya, In this tool you can give n number of inputs and parallelly you will get a output by separetely

KAVISURYA V 3 Dec 05, 2021
Writing Alfred copy/paste scripts in Python

Writing Alfred copy/paste scripts in Python This repository shows how to create Alfred scripts in Python. It assumes that you using pyenv for Python v

Will Fitzgerald 2 Oct 26, 2021
python package for generating typescript grpc-web stubs from protobuf files.

grpc-web-proto-compile NOTE: This package has been superseded by romnn/proto-compile, which provides the same functionality but offers a lot more flex

Roman Dahm 0 Sep 05, 2021
Cleaning-utils - a collection of small Python functions and classes which make cleaning pipelines shorter and easier

cleaning-utils [] [] [] cleaning-utils is a collection of small Python functions

4 Aug 31, 2022
An online streamlit development platform

streamlit-playground An online streamlit development platform Run, Experiment and Play with streamlit Components Develop full-fledged apps online All

Akshansh Kumar 3 Nov 06, 2021
A python package containing all the basic functions and classes for python. From simple addition to advanced file encryption.

A python package containing all the basic functions and classes for python. From simple addition to advanced file encryption.

PyBash 11 May 22, 2022
A collection of common regular expressions bundled with an easy to use interface.

CommonRegex Find all times, dates, links, phone numbers, emails, ip addresses, prices, hex colors, and credit card numbers in a string. We did the har

Madison May 1.5k Dec 31, 2022
ticktock is a minimalist library to view Python time performance of Python code.

ticktock is a minimalist library to view Python time performance of Python code.

Victor Benichoux 30 Sep 28, 2022
A simple tool that updates your pubspec.yaml file, of a Flutter project, without altering the structure of your file.

A simple tool that updates your pubspec.yaml file, of a Flutter project, without altering the structure of your file.

3 Dec 10, 2021
Standard implementations of FedLab and its provided benchmarks.

FedLab-benchmarks This repo contains standard implementations of FedLab and its provided benchmarks. Currently, following algorithms or benchrmarks ar

SMILELab-FL 104 Dec 05, 2022
Kanye West Lyrics Generator

aikanye Kanye West Lyrics Generator Python script for generating Kanye West lyrics Put kanye.txt in the same folder as the python script and run "pyth

4 Jan 21, 2022
Simple integer-valued time series bit packing

Smahat allows to encode a sequence of integer values using a fixed (for all values) number of bits but minimal with regards to the data range. For example: for a series of boolean values only one bit

Ghiles Meddour 7 Aug 27, 2021
EVE-NG tools, A Utility to make operations with EVE-NG more friendly.

EVE-NG tools, A Utility to make operations with EVE-NG more friendly. Also it support different snapshot operations with same style as Libvirt/KVM

Bassem Aly 8 Jan 05, 2023
Etherium unit conversation and arithmetic library

etherunit Etherium unit conversation and arithmetic library Install pip install -u etherunit Usage from etherunit import Ether, Gwei, Wei, E Creat

Yasin Özel 1 Nov 10, 2021
Networkx with neo4j back-end

Dump networkx graph into nodes/relations TSV from neo4jnx.tsv import graph_to_tsv g = pklload('indranet_dir_graph.pkl') graph_to_tsv(g, 'docker/nodes.

Benjamin M. Gyori 1 Oct 27, 2021
Manage your exceptions in Python like a PRO

A linter to manage all your python exceptions and try/except blocks (limited only for those who like dinosaurs).

Guilherme Latrova 353 Dec 31, 2022
Cardano Stakepools: Check for scheduled blocks in current epoch.

ReLeaderLogs For Cardano Stakepool Operators: Lightweight Scheduled Blocks Checker for Current Epoch. No cardano-node Required, data is taken from blo

SNAKE (Cardano Stakepool) 2 Oct 19, 2021
Simple Python tool that generates a pseudo-random password with numbers, letters, and special characters in accordance with password policy best practices.

Simple Python tool that generates a pseudo-random password with numbers, letters, and special characters in accordance with password policy best practices.

Joe Helle 7 Mar 25, 2022
Teleport Ur Logs with Love

Whatever you pipe into tull, will get a unique UUID and the data gets stored locally - accessible via a flask server with simple endpoints. You can use ngrok or localtunnel then to share it outside L

Lokendra Sharma 11 Jul 30, 2021