End-to-end security across the payment lifecycle
This workshop demonstrates how Asynk builds a scalable group communication layer for end-to-end encryption across systems owned by independent organizations. The workshop uses an e-commerce payment lifecycle as a concrete reference scenario: a Payment Gateway, Acquirer and Bank create one cryptographic group offline, then reuse its evolving MLS RFC 9420 state for merchant onboarding, card authorization and settlement.
Estimated time · ~60 minutes end to end
~20 min
Reading sections 01–05: business scenario, pairwise limits, MLS grouping, offline handshake, provider replacement.
~30 min
Hands-on 06.1–06.5: PKI setup, three workspaces, group creation, joins, bulk encrypt and decrypt.
~10 min
Verification and optional detours: certificate inspection, KeyPackage decoding, digest comparison.
Payment lifecycle
Three contact points, three channels, one trust problem
The lifecycle starts when an Acquirer signs a placement agreement with a Merchant, adds that merchant to its backbook and onboards the new position with a Payment Gateway. This first connection enables the merchant to accept e-commerce payments while the gateway simplifies cards, wallets, alternative methods and back-office functions.
In the card flow, a checkout request moves from the merchant to the Payment Gateway, then to the Acquirer and the card network for online authorization. The Acquirer is the merchant’s technical payment provider; a separate Bankenables the liquidity movement behind merchant proceeds.
At accounting close, approved captures and refunds are consolidated into a settlement file. The gateway sends it to the Acquirer, which initiates clearing and settlement with the card network under the Four Corners Model. Onboarding, real-time authorization and settlement therefore cross the same organizations through three different technical channels.
The actors can belong to independent companies, each with its own systems, security governance and certificate lifecycle. The problem is broader than settlement: identities and keys must remain coherent wherever those systems communicate, even though their channels were designed and operated separately.
The pairwise trap
Why separate JOSE and PGP relationships do not scale
Online APIs commonly use JOSE. Sender and recipient first exchange CA-signed certificates. The sender signs content with its identity key, then protects it for one recipient—typically by wrapping a symmetric key with the recipient’s public key, or deriving one from an ephemeral Diffie–Hellman secret and a KDF. This gives object-level protection, but the trust relationship remains 1:1.
Settlement files commonly use PGP, where certificates or public keys are exchanged again. The sender encrypts the data with a symmetric key and protects that key for the recipient. It creates another pairwise key lifecycle, separate from the online channel.
Every new organization must be interconnected with the existing systems across these pairwise relationships. Certificate issuance, distribution, rotation and revocation therefore grow toward quadratic cost O(n²), multiplied again by distinct onboarding, authorization and settlement channels.
Long-lived PGP settlement keys also do not provide the MLS guarantees offorward secrecyand post-compromise security through continuous epoch evolution. If a long-lived private key is compromised, the exposure model is fundamentally different from a group protocol designed to refresh secrets as membership and state change.
MLS grouping
One evolving cryptographic group across independent systems
Asynk uses the organizations’ X.509 identities to create one MLS RFC 9420 group. The Payment Gateway commits the Acquirer and Bank KeyPackages, then distributes recipient-specific Welcome bundles over email, SFTP or any other untrusted route. No always-on shared service is required for bootstrap.
Once each organization imports its Welcome, its systems hold compatible group state. That common context can protect the different application exchanges—from onboarding to authorization— while MLS evolves secrets through forward-secure epochs and updates a ratchet-tree path at O(log n) cost.
Bulk is one path, not the whole architecture: for end-of-day settlement files, the streamMLS evolution adds bounded bulk encryption while retaining the same group identity and membership context.
Bootstrap sequence
The offline handshake, step by step
Every organization performs its part independently on its own reference machine. There is no shared workstation and the machines never need a direct network connection. The only items crossing the organizational boundaries are files: recipients send their KeyPackages to the Payment Gateway, which creates and commits the group, then returns one recipient-specific Welcome bundle to each organization.
Those files can travel over any untrusted channel selected by the parties—SFTP, removable media, an existing document exchange system, or even ordinary email. Confidential group secrets remain protected by the MLS Welcome construction rather than by the delivery channel.
Membership lifecycle
Replacing a provider: remove a member, add another
Acquiring is rarely delegated to the same unit forever. A group may decide to move the service from Acquirer A to Acquirer B, and under DORA (Regulation (EU) 2022/2554) that exit must be practicable: the secure channel cannot become a form of vendor lock-in. In Asynk the change is a normal group operation—one Commit carrying a Remove proposal for the outgoing acquirer and an Add proposal for the incoming one.
The moment that Commit lands, the group moves to a new epoch with a fresh set of secrets. The removed member cannot read anything sent from that epoch onward, because it no longer holds a path in the ratchet tree—this is forward secrecy for the group. Symmetrically, if a member’s keys had been compromised earlier, the rekeying introduced by the Commit heals the group: that is post-compromise security, guaranteed by MLS RFC 9420.
The important part for a regulator or an auditor is where the guarantee lives. Exclusion here is not an entry removed from an access-control list on some server that could be misconfigured, bypassed or restored. The cryptographic history of the group and its membership topology are committed into the shared group state, so a removed participant is mathematically unable to derive the new keys, regardless of what any application layer says.
There is also a plain operational discount. With pairwise PGP, every membership change forces each pair of organizations to renegotiate keys, redistribute them and update revocation: the work grows quadratically with the number of participants. MLS updates a single path in a binary tree, so a full cryptographic refresh costs on the order of log n. A three-party payment group makes this look cheap; a group spanning dozens of systems and counterparties makes it the difference between routine rotation and a project.
streamMLS bounded bulk encryption is covered by a patent application filed with UIBM. It is an Asynk evolution for bulk data exchange; MLS RFC 9420 remains the cryptographic group foundation.
Before you start
This hands-on lab uses the asynk command-line tool. Download and install the latest release for your platform first, then come back here to run the lab.
Hands-on
Build the offline channel for massive file exchange
Lab scope
You will provision three organizational identities, exchange their KeyPackages offline, create one MLS group and produce recipient-specific Welcome files. The resulting group is the foundation used by Asynk for bounded, end-to-end encrypted bulk transfers.
MLS RFC 9420 defines two credential types for a leaf node: basic and x509. Enterprise deployments use x509, because the identity presented in the group is the same identity an organization already governs through its PKI: the certificate binds the organizational subject to the signature key that will authenticate every proposal and commit that member publishes.
The files below are a demo PKI: a self-signed Asynk Demo Root CA and three leaf certificates — Payment Gateway, Acquirer and Bank — each issued from a CSR produced by its own organization and signed by the CA, exactly as a CISO-operated security unit would do. Keys are Ed25519; the certificates carry digitalSignature key usage and are valid for the demo period.
Demo material only. These private keys are public by definition — never reuse them outside this workshop.
Action 1 · Download the PKI material
Do this now: download the full bundle (or pick individual files below) and save them into a working directory on your machine. You need all seven files before the next step.
Individual files (alternative to the .zip)
Root CA
Asynk Demo
CN=Asynk Demo Root CA, O=Asynk Demo
Self-signed trust anchor. Distribute to every member so credentials can be validated.
Payment Gateway
Payment Processor Corporation
CN=payment-processor, O=Payment Processor Corporation, OU=Batch Operations
Group creator (committer) in the offline handshake.
Acquirer
Acquirer Corporation
CN=acquirer, O=Acquirer Corporation, OU=Batch Operations
Technical provider joining through a Welcome bundle.
Bank
Settlement Bank
CN=settlement-bank, O=Settlement Bank, OU=Batch Operations
Liquidity side joining through a Welcome bundle.
OptionalInspect any certificate locally with openssl
openssl x509 -in payment-processor.crt -noout -text
openssl verify -CAfile root-ca.crt payment-processor.crt acquirer.crt settlement-bank.crtCreate one workspace folder per member
In a real deployment each member receives only its own certificate and private key, plus the shared Root CA trust anchor. It then creates its own workspace folder on its reference machine — a directory that will hold that member’s PKI material and, later, its Asynk state. No organization ever holds another member’s private key.
This workshop simulates all three members on one machine, so we create three distinct folders mirroring that separation. Each folder contains the member’s X.509 certificate and private key; the Root CA is placed in a shared folder every member can read for validation.
Action 2 · Create the workspace folders
Do this now: from your working directory, create the folder tree below and move each downloaded file into its matching folder. The root-ca.crt trust anchor goes in the shared root-ca/ folder; each member’s certificate and key go into its own folder.
workspaces/
├── root-ca/
│ └── root-ca.crt ← shared trust anchor (every member)
├── acquirer/
│ ├── acquirer.crt ← identity (public)
│ └── acquirer.key ← private key (secret, member-only)
├── payment-processor/
│ ├── payment-processor.crt
│ └── payment-processor.key
└── settlement-bank/
├── settlement-bank.crt
└── settlement-bank.keyEach member would build this layout from the files it received. In the next step we turn the certificate in each folder into an MLS KeyPackage and run the offline group bootstrap — published next.
Scaffold a workspace: import identity, generate a KeyPackage
With the PKI material in place, each member runs asynk init on its own reference machine. This is the scaffold step: it initializes the member’s workspace, imports its identity (the X.509 certificate + private key + trust anchor), binds a StateStore and ProtectionProvider runtime, and generates the member’s first KeyPackage. In a real deployment every organization does this independently — the command never touches another member’s material.
--no-initialize-group keeps the workspace to identity + KeyPackage provisioning only; the group itself is created later by the committer. The --cipher-suite pins the MLS parameters all members must agree on.
Action 3 · Scaffold the workspace (run once per member)
Do this now: from inside each member’s folder, run asynk init pointing at that member’s certificate, private key and the shared trust anchor. Repeat the command once for Acquirer, once for Payment Processor and once for Settlement Bank — each on its own workspace path.
$ asynk init workspaces/payment-processor \ --member=payment-processor \ --certificate=workspaces/payment-processor/payment-processor.crt \ --private-key=workspaces/payment-processor/payment-processor.key \ --trust-anchor=workspaces/root-ca/root-ca.crt \ --runtime=filesystem-passphrase \ --passphrase-file=secrets/payment-processor.passphrase \ --cipher-suite="MLS10_128_DHKEMX25519_AES128GCM_SHA256_Ed25519" \ --no-initialize-groupParameter reference
Each line of the command, explained.
- 1
--memberAn alias that identifies the current member of the group inside this workspace (here,
payment-processor). It labels the member’s state and KeyPackages, not the cryptographic identity. - 2
--certificateThe X.509 certificate carrying the member’s identity — the public credential whose subject and issuer are committed into the MLS LeafNode.
- 3
--private-keyThe private signing key that belongs to that same certificate. It proves the member controls the identity and signs MLS messages; it never leaves the member’s workspace.
- 4
--trust-anchorThe trust chain (the Root CA) used to validate the certificate and, later, every other member’s credential. Every member pins the same anchor.
- 5
--runtimePicks the runtime: the implementation chosen for where to keep the group state (the StateStore) and how to protect the secrets (the ProtectionProvider). For simplicity this workshop uses
filesystem-passphrase— state on the local filesystem, keys guarded by a passphrase. Other runtimes can target a Vault-backed KMS, an HSM, or an encrypted blob store. See the Runtime concept in the docs for the full picture. - 6
--passphrase-filePath to the file holding the passphrase that unlocks the
filesystem-passphraseruntime’s protected secrets. - 7
--cipher-suitePins the MLS cipher suite (KEM, AEAD, hash, signature) that every member must agree on for the group.
- 8
--no-initialize-groupProvision identity + KeyPackage only; the group is created later by the committer in step
07.
The scaffold leaves each workspace holding a reserved KeyPackage at artifacts/key-packages/<member>/kp-001 plus an asynk-runtime.yaml whose fingerprint is pinned into every later request, so state transitions are auditable and reproducible.
Concept · One identity, many KeyPackages
An identity is the long-lived organizational credential (the X.509 certificate + its signature key). A KeyPackage is a short-lived, single-use ticket derived from that identity: it is the member’s business card that the committer consumes to insert the member into a group.
One identity can mint multiple KeyPackages — typically one per group, or several reserved for different groups or rotations. Each KeyPackage is consumed exactly once on Add; once consumed it cannot be reused. This separation keeps the stable identity decoupled from the per-group cryptographic material.
A KeyPackage is a structured MLS object. In short it carries:
- Protocol version and cipher suite the member supports;
- a LeafNode with the member’s init key (the public half of an ephemeral KEM keypair), the signature key and the X.509 credential;
- capabilities and extensions (e.g. which versions and suites the member will accept);
- a lifetime window and the member’s signature over the whole package, proving the init key was minted by the identity behind the certificate.
The committer never needs the private keys: the KeyPackage’s signed init key is enough to craft a Welcome bundle that only the owning member can open.
Action 4 · Inspect a real KeyPackage
Do this now: download the sample KeyPackage below (generated for the Payment Processor identity in this workshop) and decode it in the browser to see every field — cipher suite, leaf node, capabilities and the embedded X.509 certificate.
payment-processor.keypackage.pem · 1025 bytes · PEM-encoded MLS KeyPackage
Create the group: Add members, Commit, distribute Welcomes
Assume the Payment Gateway is the member responsible for creating the group. The Acquirer and Settlement Bankeach send one unused KeyPackage to the Payment Gateway. The committer first initializes its local group, creates one Add proposal for each incoming member, then applies both proposals in a single Commit.
The Commit advances the group to a new epoch and produces one recipient-specific Welcome for the Acquirer and one for the Bank. A Welcome contains the encrypted material required to join the exact group state created by that Commit; only the owner of the corresponding KeyPackage can open it.
Action 5 · Exchange the KeyPackages
Do this now: copy the Acquirer and Settlement Bank KeyPackage files into the Payment Gateway exchange folder. In a real project, each organization sends only its public KeyPackage; private keys never cross the organizational boundary.
workspaces/payment-processor/exchange/
└── key-packages/
├── acquirer.keypackage.pem
└── settlement-bank.keypackage.pemWhy an untrusted channel is enough
KeyPackages and Welcome files may travel over an untrusted channel—even ordinary email. KeyPackages are signed public objects; Welcome secrets are encrypted to the joining member’s one-time init key. Security comes from MLS verification and encryption, not from trusting the delivery route.
This is practical across independent organizations: project managers and technical coordinators already exchange controlled artifacts by email, while the underlying systems often sit in separate data centers and DMZs, split across on-premises and cloud environments, with no trusted machine-to-machine channel established.
Action 6 · Initialize, Add, and Commit
Do this now: run these commands from the Payment Gateway workspace. The request files declare the runtime fingerprint, group state version, sender identity, input KeyPackage and output paths, following the flow in demo-three-org-bulk.sh.
$ asynk group initialize --input=workspaces/payment-processor/requests/groups/payment-channel/initialize.yaml$ asynk proposal create add --input=workspaces/payment-processor/requests/groups/payment-channel/add-acquirer.yaml$ asynk proposal create add --input=workspaces/payment-processor/requests/groups/payment-channel/add-settlement-bank.yaml$ asynk commit create --input=workspaces/payment-processor/requests/groups/payment-channel/commit.yaml1 · Initialize
Creates the group from the Payment Gateway identity and reserved KeyPackage.
2 · Add × 2
Validates each incoming KeyPackage and records one proposal per organization.
3 · Commit
Applies both proposals, advances the epoch, and emits the two Welcome files.
workspaces/payment-processor/exchange/
├── commit.mls
├── group-info.mls
└── welcomes/
├── welcome-acquirer.mls → send to Acquirer
└── welcome-settlement-bank.mls → send to Settlement BankSend each Welcome only to its intended organization using any agreed artifact route—email is valid.
Action 7 · Download the request files
Do this now: download the three YAML requests consumed by the commands above and place them under workspaces/payment-processor/requests/groups/payment-channel/. Adjust the paths inside each file to match your working directory, and replace the <runtime fingerprint> and <reservation id> placeholders with the values printed by asynk init.
initialize.yaml
GroupInitializeRequest — creates the group locally
apiVersion: asynk.dev/v1alpha1
kind: GroupInitializeRequest
metadata:
requestId: group-initialize-payment-channel
spec:
runtime:
ref: "workspaces/payment-processor/asynk-runtime.yaml"
version: "1"
digest: "<runtime fingerprint>"
state-key: "groups/payment-channel"
group-id-file: ".../groups/payment-channel/group-id.bin"
protocol-version: MLS_1_0
cipher-suite: "MLS10_128_DHKEMX25519_AES128GCM_SHA256_Ed25519"
creator-identity: payment-processor
creator-key-package-state-key: key-packages/payment-processor/kp-001
creator-key-package-reservation-id: "<reservation id>"- state-key
- where the group state is persisted in the StateStore.
- cipher-suite
- the MLS parameters every member must agree on.
- creator-*
- identity and reserved KeyPackage of the committer.
- group-id-file
- the stable group identifier shared by all epochs.
add-acquirer.yaml
ProposalCreateAddRequest — one per joining organization
apiVersion: asynk.dev/v1alpha1
kind: ProposalCreateAddRequest
metadata:
requestId: proposal-add-acquirer
spec:
runtime: { ref: ".../asynk-runtime.yaml", version: "1", digest: "<digest>" }
state-key: "groups/payment-channel"
state-version: "0"
sender-identity: payment-processor
sender-leaf-index: "0"
wire-format: MLS_PUBLIC_MESSAGE
proposal-output: "exchange/proposals/add-acquirer.proposal"
proposal-reference-output: "exchange/proposals/add-acquirer.ref"
key-package-file: "exchange/key-packages/acquirer.keypackage.pem"- key-package-file
- the KeyPackage received from the joining member; it is validated against the trust anchor.
- state-version
- optimistic concurrency: 0 for the first proposal, 1 for the second. A replayed request is rejected instead of forking the group.
- proposal-reference-output
- the reference later listed in the Commit.
commit.yaml
CommitCreateRequest — applies both proposals in one epoch change
apiVersion: asynk.dev/v1alpha1
kind: CommitCreateRequest
metadata:
requestId: commit-add-acquirer-and-bank
spec:
runtime: { ref: ".../asynk-runtime.yaml", version: "1", digest: "<digest>" }
state-key: "groups/payment-channel"
state-version: "2"
sender-identity: payment-processor
force-path: "true"
commit-output: "exchange/commit.mls"
welcome-output-directory: "exchange/welcomes"
group-info-output: "exchange/group-info.mls"
proposals-file: ".../payment-channel/proposals.txt"- proposals-file
- a plain text list of the two proposal references produced above.
- force-path
- forces a fresh path update, so the new epoch rotates key material (forward secrecy).
- welcome-output-directory
- where the recipient-specific Welcome files are written.
- group-info-output
- the public group info describing the new epoch.
Join the group: each member processes its Welcome
The group now exists only in the committer’s StateStore. Every other member must materialize the same epoch locally by processing the Welcome it received. This happens independently, on each organization’s own machine: no online session, no shared key server, no callback to the Payment Gateway.
A Welcome is bound to the KeyPackage that member published: its secrets are encrypted to that KeyPackage’s one-time init key. Only the holder of the matching private key can open it, which is why the file can travel over an untrusted route. Processing it consumes that KeyPackage — it cannot be reused for a second join.
Because the ratchet tree is carried inside the Welcome, ratchet-tree-file: none is enough: the member reconstructs the full group topology and derives the same epoch secrets as the committer.
Action 8 · Process the Welcome in each member workspace
Do this now: copy welcome-acquirer.mls into the Acquirer workspace and welcome-settlement-bank.mls into the Settlement Bank workspace, download the two request files below, then run one command per member.
welcome-acquirer.yaml
WelcomeProcessRequest — run in the joining member’s workspace
apiVersion: asynk.dev/v1alpha1
kind: WelcomeProcessRequest
metadata:
requestId: welcome-process-acquirer
spec:
runtime: { ref: "workspaces/acquirer/asynk-runtime.yaml", version: "1", digest: "<digest>" }
new-state-key: "groups/payment-channel"
joining-identity: acquirer
key-package-state-key: key-packages/acquirer/kp-001
consumed-key-package-ref-file: ".../kp-001/acquirer.kpr"
key-package-reservation-id: "<reservation id>"
welcome-file: "exchange/welcome-acquirer.mls"
ratchet-tree-file: none- new-state-key
- where the joined group state is written locally.
- joining-identity
- the member’s X.509 identity imported during scaffold.
- consumed-key-package-ref-file
- the KeyPackage being consumed by this join.
- ratchet-tree-file: none
- the tree travels inside the Welcome.
$ asynk welcome process --input=workspaces/acquirer/requests/groups/payment-channel/welcome-acquirer.yaml$ asynk welcome process --input=workspaces/settlement-bank/requests/groups/payment-channel/welcome-settlement-bank.yamlThe offline handshake is complete: the same group epoch now lives in three independent state stores, established without a single online interaction between the three organizations.
Encrypt the settlement file in bulk, decrypt it independently
With the handshake settled, the shared group state becomes a key derivation engine. Each bulk operation derives fresh symmetric keys from the current epoch secrets; those keys are consumed and discarded, so a later compromise of the workspace does not expose previously protected files — forward secrecy applies to data at rest in transit, not just to control messages.
The payload here is the settlement file: all approved transactions of the accounting day, produced by the Payment Gateway and delivered to the Acquirer and the Settlement Bank. It is encrypted once for the whole group, and every member decrypts it from its own state.
Bulk protection is handled by streamMLS, the Asynk extension of MLS: the file is processed in bounded chunks, so memory usage stays flat regardless of file size, while the operation stays atomic — the envelope authenticates the whole dataset, so a truncated or tampered ciphertext fails verification instead of yielding partial plaintext.
Envelope (.mls)
MLS message carrying the derived key material and the authenticated metadata for the dataset.
Ciphertext
The chunked, AEAD-protected settlement file. Large, opaque, safe on any transport.
Result (.json)
Audit record: epoch used, segment count, digests — reproducible in CI.
Action 9 · Encrypt the settlement file
Do this now: place your settlement CSV in the Payment Gateway exchange folder as settlement-transactions.csv, download the request below and run the encrypt command.
bulk-encrypt.yaml
BulkEncryptRequest — one encryption for the whole group
apiVersion: asynk.dev/v1alpha1
kind: BulkEncryptRequest
metadata:
requestId: bulk-encrypt-settlement-file
spec:
runtime: { ref: ".../asynk-runtime.yaml", version: "1", digest: "<digest>" }
state-key: "groups/payment-channel"
state-version: "3"
sender-identity: payment-processor
plaintext-file: "exchange/settlement-transactions.csv"
authenticated-data-file: ".../payment-channel/aad.bin"
plaintext-segment-size: "65536"
wire-format: MLS_PRIVATE_MESSAGE
envelope-output: "exchange/settlement-transactions.envelope.mls"
ciphertext-output: "exchange/settlement-transactions.ciphertext"- plaintext-file
- the settlement file with the day’s approved transactions.
- plaintext-segment-size
- the bounded chunk size: memory stays constant on multi-GB files.
- authenticated-data-file
- metadata bound to the ciphertext (dataset, content type) and verified on decrypt.
- envelope-output / ciphertext-output
- the two artifacts to distribute.
$ asynk bulk encrypt --input=workspaces/payment-processor/requests/groups/payment-channel/bulk-encrypt.yamlworkspaces/payment-processor/exchange/
├── settlement-transactions.envelope.mls → send to both members
└── settlement-transactions.ciphertext → send to both membersAction 10 · Decrypt in each member workspace
Do this now: deliver both artifacts to the Acquirer and the Settlement Bank, then run the decrypt command in each workspace. Adapt bulk-decrypt.yaml to the member by changing the runtime reference and the output path.
bulk-decrypt.yaml
BulkDecryptRequest — run independently by each recipient
apiVersion: asynk.dev/v1alpha1
kind: BulkDecryptRequest
metadata:
requestId: bulk-decrypt-settlement-file-acquirer
spec:
runtime: { ref: "workspaces/acquirer/asynk-runtime.yaml", version: "1", digest: "<digest>" }
state-key: "groups/payment-channel"
state-version: "0"
envelope-file: "exchange/settlement-transactions.envelope.mls"
ciphertext-file: "exchange/settlement-transactions.ciphertext"
authenticated-data-file: ".../payment-channel/aad.bin"
plaintext-output: "artifacts/settlement-transactions.decrypted.csv"- envelope-file + ciphertext-file
- the two artifacts received from the sender.
- authenticated-data-file
- must match the sender’s AAD, or verification fails.
- plaintext-output
- the recovered settlement file.
$ asynk bulk decrypt --input=workspaces/acquirer/requests/groups/payment-channel/bulk-decrypt.yaml$ asynk bulk decrypt --input=workspaces/settlement-bank/requests/groups/payment-channel/bulk-decrypt.yamlshasum -a 256 workspaces/payment-processor/exchange/settlement-transactions.csv \
workspaces/acquirer/artifacts/settlement-transactions.decrypted.csv \
workspaces/settlement-bank/artifacts/settlement-transactions.decrypted.csvOne encryption, N independent decryptions. Three legal entities, three PKI identities, one MLS group — and a settlement file that only group members can read.
Patent notice
Bounded bulk encryption (streamMLS) is an evolution of MLS covered by a patent application filed with UIBM. Availability is subject to the licensing terms of that application.