The order of the nodes in the record structure does not matter.
Private box envelopes
A private box envelope has the following record structure:
content empty # content hash encrypted for first 24 bytes of A's hash RSA/OAEP(AES key, A's public key) first 24 bytes of B's hash RSA/OAEP(AES key, B's public key) … signature RSA/PSS(content hash, owner's private key)
The content hash points to the content object (and the tree it spans). This object is encrypted with the AES key (32 bytes), and resides on the same store as the envelope.
The encrypted for section lists the actors entitled to access the content. This typically includes the sender — the actor writing the data — and the actors it entrusts. Actor hashes are shortened to 24 bytes. The RSA-encrypted AES keys are encoded as unsigned big-endian integers.
The signature signs the content, and is encoded as unsigned big-endian integer.
Public box envelopes
A public box envelope follows the same structure, but omits the encrypted for section:
content empty # content hash signature RSA/PSS(content hash, owner's private key)
The content hash points to the public card, which must reside on the same store.
A message envelope in a message box has the following structure:
content content encrypted for first 24 bytes of A's hash RSA/OAEP(AES key, A's public key) first 24 bytes of B's hash RSA/OAEP(AES key, B's public key) … expires (optional) expiration date updated by (optional) first 24 bytes of S's hash first 24 bytes of T's hash … signature RSA/PSS(SHA256(content), sender's private key)
content = AES256CTR(content object bytes, AES key, 0)
The envelope embeds a small content object. Its bytes (not just the data part) are encrypted using AES 256 in CTR mode. The CTR counter starts at 0, and is incremented by 1 for each AES block (16 bytes).
The encrypted for section lists actors entitled to access the content. This typically includes the recipients, and the actors they entrust. Actor hashes are shortened to 24 bytes. The RSA-encrypted AES keys are encoded as unsigned big-endian integers.
If an expiration date is specified, the store may remove the message once it has expired.
The updated by section lists actors entitled to remove the message from the message box — usually for the purpose of updating it. This typically includes the sender.
The signature signs the encrypted content object, and is encoded as unsigned big-endian integer.
The total envelope size must not exceed 16 KiB.
The content object has the following structure:
store sender store URL sender empty # sender hash message content
Sender store URL and sender hash point to the sender's public key, which is used to verify the envelope's signature. The remainder is used for message content, and application-specific.
The content object should not exceed 1 KiB. It typically contains the message type, some metadata, and links to the actual message data on the sender's store. To make sure that such data remains available until the message expires, the sender links it through his private box:
Small messages may be fully included in the content object.
Stream envelopes draft
A stream envelope in a message box has the following structure:
content content ctr ctr head empty # head message hash mac AES256CTR(content hash, AES key, ctr)
whereby content and content hash are calculated as follows:
content = AES256CTR(content object bytes, AES key, ctr + 2) content hash = SHA256(content)
The head points to a message envelope sent earlier. The AES key from the head envelope is reused for the stream envelope.
Every envelope uses a small part of the CTR range from 0 to 2128 - 1:
- The head envelope uses the range starting at 0, and requires one count for every 16 bytes of the content object.
- A stream envelope uses the range starting at ctr, and requires 2 counts for the MAC, and one additional count for every 16 bytes of the content object.
Ranges must be non-overlapping.
The mac protects the content object from being altered. This is not a signature, however: any recipient of the head message may produce valid MACs.
The expires and updated by section on the head envelope are valid for all stream envelopes.
Recipients must keep a reference to the head envelope for as long as they wish to receive the stream. Once the head envelope vanishes, stores may refuse new stream envelopes, since they reference a head envelope that does not exist (any more) on the store.