# Audience Algebra

## The problem

Encrypting a secret for one person is solved. `.me` already does it by wrapping a key to that person's public key.

Real audiences are rarely one person, though. Sometimes "anyone of us" can open a secret, and sometimes it takes "all of us together." Sometimes it's a mix, like "alice and bob together, or carol alone." People join and leave. Whatever the audience says has to be enforced by the ciphertext itself, not by a server that promises to check.

## The model

An audience is a formula over identities built from two operators, OR and AND, which can nest.

```plaintext
(alice AND bob) OR carol
```

*   **OR** wraps the same key once for each member.
    
*   **AND** splits the key into XOR shares, one per member, so no single member can rebuild it alone.
    
*   **Every audience reduces to its minimal coalitions,** meaning the smallest groups of people who can open it. Equivalent formulas get the same id.
    
*   **There is no NOT and no XOR operator.** Encryption can only grant access, never take it away from someone who already holds a key.
    
*   **Removing someone happens at seal time.** Revoking means sealing a new version with a new key.
    
*   **Groups are immutable values** identified by the hash of their members. Adding a member creates a new group.
    

```typescript
const A = [{ and: [alice, bob] }, carol];

const env = await sealAudience({ budget: "120k" }, A);

await openAudience(env, [carolKey]);          // opens
await openAudience(env, [aliceKey, bobKey]);  // opens
await openAudience(env, [aliceKey]);          // throws
```

## What's tested

There are 16 passing tests.

*   **The laws:** one test per law, L1 through L9.
    
*   **alice AND bob:** neither alice nor bob can open alone, and together they can.
    
*   **(alice AND bob) OR carol:** carol opens alone, alice and bob open together, and alice alone can't.
    
*   **AND of three:** all three open, and no pair can.
    
*   **Canonical ids:** equivalent formulas produce the same id.
    
*   **Empty audiences:** if removing members leaves nobody, seal refuses.
    
*   **Revocation:** after carol is removed and the secret is resealed, she can't open the new version, though she can still open the old one.
    
*   **Tampering:** changing any byte of the ciphertext, the header or a share makes open fail.
    

Everything is built on the kernel's existing wrapping and encryption, with no new crypto dependencies.

## Status

This is on a branch and not yet on npm. It hasn't been audited yet. Declaring audiences directly in the tree comes next.

Spec: [https://suign.github.io/AudienceAlgebra.html](https://suign.github.io/AudienceAlgebra.html)
