Skip to main content

Python bindings for the Group Protocol Stack: a layered, end-to-end encrypted group-messaging protocol family built on top of MLS (RFC 9420).

Project description

gbp-stack — Python bindings for the Group Protocol Stack

License: Apache 2.0

Python bindings for the Group Protocol Stack: a layered, end-to-end encrypted group-messaging protocol family built on top of MLS (RFC 9420).

This package wraps the native gbp_stack shared library through ctypes. The wheel for each supported platform bundles the appropriate native binary under gbp_stack/_native/<rid>/.

Layers

┌── application ──────────────────────────────────────────────────────┐
│   GtpClient · GapClient · GspClient   (TCP / UDP / SCTP-like)       │
├─────────────────────────────────────────────────────────────────────┤
│   GroupNode (GBP — IP-like base)                                    │
├─────────────────────────────────────────────────────────────────────┤
│   MlsContext (RFC 9420)                                             │
└─────────────────────────────────────────────────────────────────────┘

Payload codec

Each sub-protocol payload can be encoded as CBOR (default), Protobuf, or FlatBuffers. Pass PayloadCodec to send and accept; the chosen codec is surfaced in ev.codec on payload_received events.

from gbp_stack import GtpClient, PayloadCodec

frame = gtp_alice.send(alice, alice_mls, target=2, message_id=1,
                       text="hello", codec=PayloadCodec.FLATBUFFERS)
for ev in bob.on_wire(bob_mls, frame.wire):
    if ev.kind == "payload_received":
        codec = ev.codec or PayloadCodec.CBOR
        result = gtp_bob.accept(ev.plaintext, bob_mls.epoch, codec=codec)
        print(result.text)
Value Name Description
0 PayloadCodec.CBOR Default; pf field omitted from wire
1 PayloadCodec.PROTOBUF Protobuf via gbp-proto
2 PayloadCodec.FLATBUFFERS FlatBuffers via gbp-flat; lowest latency

Sub-protocol toolkits

Beyond the protocol clients, the package ships ready-made helpers:

  • MessageHistory + Watermark — bounded GTP message log + per-sender high-water mark for serving and consuming resync requests.
  • JitterBuffer — bounded GAP reorder window keyed by media_source_id, with push, pop_in_order, pop_force and late-frame detection.
  • RoleRegistry + Permissions — bind numeric role ids to permission bit-masks and check them with require / has.
  • CapabilitiesNegotiator — track per-member advertisements and query the intersection, union, group_supports and missing views.
  • SFrameSession + SFrameEncryptor — SFrame (draft-ietf-sframe-enc) E2EE for GAP audio frames; per-sender AES-GCM keys derived from MLS exporter, 1024-entry sliding-window replay protection.
  • encode_gbp_frame — low-level helper to construct a raw CBOR GBP frame.
  • lookup_error — return the CBOR ErrorObject for a known error code.

Coordinator events

NodeEvent surfaces three new event kinds for coordinator election:

kind Extra fields Meaning
coordinator_election_needed The local node should initiate GSP COORDINATOR_CLAIM
became_coordinator This node won the election
coordinator_claim claimant A peer sent COORDINATOR_CLAIM with this member id

Install

pip install gbp-stack==1.8.2

Quick start

from gbp_stack import MlsContext, GroupNode, GtpClient

with MlsContext.create("alice") as alice_mls, \
     MlsContext.create("bob")   as bob_mls:

    bob_kp  = bob_mls.export_key_package()
    welcome = alice_mls.invite(bob_kp)       # alice auto-finalizes; epoch advances to 1
    bob_mls.accept_welcome(welcome)

    group_id = alice_mls.group_id
    with GroupNode.create(member_id=1, group_id=group_id) as alice, \
         GroupNode.create(member_id=2, group_id=group_id) as bob, \
         GtpClient.create() as gtp_alice, \
         GtpClient.create() as gtp_bob:

        alice.bootstrap_as_creator(alice_mls.epoch)
        bob.bootstrap_as_joiner(bob_mls.epoch)

        frame = gtp_alice.send(alice, alice_mls, target=2,
                                message_id=0xCAFE_F00D, text="hello")
        for ev in bob.on_wire(bob_mls, frame.wire):
            if ev.kind == "payload_received" and ev.stream_type == 2:  # StreamType.Text
                result = gtp_bob.accept(ev.plaintext, bob_mls.epoch)
                print(result.text)   # → "hello"
                # result.status is "new" (first message from this sender)
                # subsequent messages → "new"; duplicates → "duplicate"

GSP signals with per-signal arguments

Signals that target a specific member or resource require CBOR-encoded args. The send method accepts an optional args: bytes keyword argument.

import struct
from gbp_stack import GspClient, SignalType

# Minimal CBOR helpers
def cbor_uint(n: int) -> bytes:
    if n <= 23:     return bytes([n])
    if n <= 0xFF:   return bytes([0x18, n])
    if n <= 0xFFFF: return bytes([0x19, n >> 8, n & 0xFF])
    return bytes([0x1A, (n>>24)&0xFF, (n>>16)&0xFF, (n>>8)&0xFF, n&0xFF])

def cbor_map1(k: int, v: int) -> bytes:
    return bytes([0xA1]) + cbor_uint(k) + cbor_uint(v)

def cbor_map2(k0: int, v0: int, k1: int, v1: int) -> bytes:
    return bytes([0xA2]) + cbor_uint(k0) + cbor_uint(v0) + cbor_uint(k1) + cbor_uint(v1)

# Signal-specific args schemas:
#   MUTE / UNMUTE  → {0: target_member_id}
#   ROLE_CHANGE    → {0: target_member_id, 1: new_role_id}
#   STREAM_START / STREAM_STOP → {0: stream_type}
#   CODEC_UPDATE   → {0: codec_id}
#   JOIN / LEAVE   → no args required

with GspClient.create() as gsp_alice:
    # Mute member 3 (no role_claim needed for self-moderation)
    frame = gsp_alice.send(
        alice_node, alice_mls,
        target=0,  # 0 = broadcast
        signal=SignalType.MUTE,
        role_claim=0,
        request_id=1,
        args=cbor_map1(0, 3),  # {0: target_member_id=3}
    )

MLS multi-member group pattern

When inviting a member to an existing group (not the first invite), use invite_full so that existing members can process the commit:

# Alice adds Carol to an alice+bob group
commit, welcome = alice_mls.invite_full(carol_mls.export_key_package())
alice_mls.finalize_commit()          # alice's epoch advances
bob_mls.process_message(commit)      # bob stages the commit
bob_mls.finalize_commit()            # bob's epoch advances to match alice
carol_mls.accept_welcome(welcome)    # carol joins
assert alice_mls.epoch == bob_mls.epoch == carol_mls.epoch

Persisting MLS state

Serialise a context so it survives a restart, then restore it later — the restored context is at the same epoch and can send / receive again. The blob holds private key material, so store it encrypted at rest.

blob = mls.export_state()                   # persist (encrypted) to disk
# ... later / after restart ...
with MlsContext.restore_state(blob, "alice") as restored:
    assert restored.epoch == mls.epoch
    assert restored.group_id == mls.group_id

License

Licensed under Apache License, Version 2.0.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gbp_stack-1.8.2.tar.gz (27.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

gbp_stack-1.8.2-cp311-cp311-win_arm64.whl (25.4 kB view details)

Uploaded CPython 3.11Windows ARM64

gbp_stack-1.8.2-cp311-cp311-win_amd64.whl (1.3 MB view details)

Uploaded CPython 3.11Windows x86-64

gbp_stack-1.8.2-cp311-cp311-manylinux2014_x86_64.whl (1.4 MB view details)

Uploaded CPython 3.11

gbp_stack-1.8.2-cp311-cp311-manylinux2014_aarch64.whl (25.2 kB view details)

Uploaded CPython 3.11

gbp_stack-1.8.2-cp311-cp311-macosx_11_0_x86_64.whl (1.4 MB view details)

Uploaded CPython 3.11macOS 11.0+ x86-64

gbp_stack-1.8.2-cp311-cp311-macosx_11_0_arm64.whl (1.2 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

File details

Details for the file gbp_stack-1.8.2.tar.gz.

File metadata

  • Download URL: gbp_stack-1.8.2.tar.gz
  • Upload date:
  • Size: 27.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gbp_stack-1.8.2.tar.gz
Algorithm Hash digest
SHA256 1a39eb4dc9428833066915e4a3cf84e1b88d92b673540de6b0952fa8dd2931e9
MD5 cb94d0951cde4a654e24aa42b8fe7ac7
BLAKE2b-256 5138e85a893cd8b09bd04aca9cdfdfc6eeb6b728538fbb2e17fd15fe6ad8e994

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbp_stack-1.8.2.tar.gz:

Publisher: release.yml on F000NKKK/Group-Protocol-Stack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gbp_stack-1.8.2-cp311-cp311-win_arm64.whl.

File metadata

  • Download URL: gbp_stack-1.8.2-cp311-cp311-win_arm64.whl
  • Upload date:
  • Size: 25.4 kB
  • Tags: CPython 3.11, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gbp_stack-1.8.2-cp311-cp311-win_arm64.whl
Algorithm Hash digest
SHA256 b1b5228f878d70150f0135ab99873cef4a973820901e77e6671628ab6a70523d
MD5 48acf4674d221c49ce6b779c8699e919
BLAKE2b-256 938ec291a5e5742c7d3388f62aa69e65189787a5d8f8d3b72baf34ad5b8de933

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbp_stack-1.8.2-cp311-cp311-win_arm64.whl:

Publisher: release.yml on F000NKKK/Group-Protocol-Stack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gbp_stack-1.8.2-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: gbp_stack-1.8.2-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gbp_stack-1.8.2-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 2d08e606c2e5bc1139a2632aa8eef1168aa7a496ec5074e2b2d0fd27e1f96db0
MD5 f16c5b9576cf425071b13735d2555aab
BLAKE2b-256 8f4016877415017f3b61e0ad7dd039ee51cd9bc125c74e47497c201d64ab8481

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbp_stack-1.8.2-cp311-cp311-win_amd64.whl:

Publisher: release.yml on F000NKKK/Group-Protocol-Stack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gbp_stack-1.8.2-cp311-cp311-manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for gbp_stack-1.8.2-cp311-cp311-manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 9e4f7bbf2bbf364c136822ce63d2f38aababda93a7a6d54846288a68b5e60bdc
MD5 4880296bbeddd0fbe222cd98783b67e7
BLAKE2b-256 0e906f07eed794707ad24ef08a70322b059c2e266e7550a5de9ce78c495f7c5e

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbp_stack-1.8.2-cp311-cp311-manylinux2014_x86_64.whl:

Publisher: release.yml on F000NKKK/Group-Protocol-Stack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gbp_stack-1.8.2-cp311-cp311-manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for gbp_stack-1.8.2-cp311-cp311-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 ae0dc2135c09aae493c3cdff69548abc0870a67f5beb80ab0a1ca785966127c2
MD5 70a17fec8d093ea1baca46ba41acc603
BLAKE2b-256 d59da70c2471087ad502aa8e781a8e813c8c3fa29385d601cc6d00057a2ec4e2

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbp_stack-1.8.2-cp311-cp311-manylinux2014_aarch64.whl:

Publisher: release.yml on F000NKKK/Group-Protocol-Stack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gbp_stack-1.8.2-cp311-cp311-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for gbp_stack-1.8.2-cp311-cp311-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 cfae04c007af23cafbb0d77b7e74eb41e6dfa731c963507d4872f052e9d98438
MD5 79dc4cca00e686028eeb2165b1dfad68
BLAKE2b-256 b53f32f727ff2a490a78dacab63e8396334f2e7cbe013e2ef00fd285879d6e6e

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbp_stack-1.8.2-cp311-cp311-macosx_11_0_x86_64.whl:

Publisher: release.yml on F000NKKK/Group-Protocol-Stack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gbp_stack-1.8.2-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for gbp_stack-1.8.2-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 58b5affafe3df0ba13f184ce8b6c26347bf0ee11e3ca23e55d052c78dfbc489e
MD5 3c00cb5ac729655d825ec5d2fb399bcb
BLAKE2b-256 b5da48573d53ed3bf189b33db5b7940f89af37e73178b62e8a9b0e7fde7989fe

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbp_stack-1.8.2-cp311-cp311-macosx_11_0_arm64.whl:

Publisher: release.yml on F000NKKK/Group-Protocol-Stack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page