Brands

The brand pattern divides the capability of establishing a secure communication channel into two facets, called a sealer and unsealer.

def [ana, cata] := makeBrandPair("finney")
def box := ana.seal(42)
cata.unseal(box)

The resulting channel has the following properties:

  • Authentic and Unforgeable: Boxes created by the sealer cannot be unsealed by any object other than the unsealer; to the contrapositive, any object that the unsealer unseals must have been sealed with the corresponding sealer.
  • Asynchronous: Boxes created by the sealer can be unwrapped on any subsequent turn.
  • Untyped: Any object can be transmitted along the channel.

Up & Down

To create a new brand, call makeBrandPair(nickname :Str). The nickname is purely cosmetic, to aid readability and debugging; it does not have to be unique.

# Make a sealer named `ana` and an unsealer named `cata`.
def [ana, cata] := makeBrandPair("finney")

The brand itself is an opaque object which proves that a sealer and unsealer are paired with each other. It is accessible via the .getBrand/0 method:

# Hey, these two are a pair!
ana.getBrand() == cata.getBrand() # should be true

Brands are usable as map keys:

def brandMap := [ana.getBrand() => [ana, cata]]
brandMap[cata.getBrand()] # should be `[ana, cata]`

The fundamental operation of a sealer is to .seal/1 an object into a box:

def box := ana.seal(42)
box # <box sealed by finney>

The unsealer, unsurprisingly, provides .unseal/1, which opens a box and returns its contents:

cata.unseal(box) # should be 42

The box is opaque and yields only one useful method, .getBrand/0, which can be useful for determining which unsealer might be the correct one to use for unsealing:

brandMap[box.getBrand()] # should be `[ana, cata]`

Note

The implementation of makeBrandPair in the Typhon prelude has other methods defined on boxes, but they do not affect the security guarantees of the implementation.