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.7.0

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.7.0.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.7.0-cp311-cp311-win_arm64.whl (25.4 kB view details)

Uploaded CPython 3.11Windows ARM64

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

Uploaded CPython 3.11Windows x86-64

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

Uploaded CPython 3.11

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

Uploaded CPython 3.11

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

Uploaded CPython 3.11macOS 11.0+ x86-64

gbp_stack-1.7.0-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.7.0.tar.gz.

File metadata

  • Download URL: gbp_stack-1.7.0.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.7.0.tar.gz
Algorithm Hash digest
SHA256 c60fb71b42703e58032c94eb9fa132b612f4c6cac7be1d3c27044e3aa50287fa
MD5 1867112370ffb908056c8fdcbe5e97b5
BLAKE2b-256 c99dae4c2793e0991edc808de69361241e827a762c0158eaeb9356587fb29b52

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbp_stack-1.7.0.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.7.0-cp311-cp311-win_arm64.whl.

File metadata

  • Download URL: gbp_stack-1.7.0-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.7.0-cp311-cp311-win_arm64.whl
Algorithm Hash digest
SHA256 a958c7a82e8a0231574bc242cb17325ab5e114aa58283bb47a791d69d17545e7
MD5 a73fc257544ce9c84f9084c32bcbe8d4
BLAKE2b-256 66acea3954f984be4317b9114f6605ee2ab1f465f014c19f8fe6b9731c555f26

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbp_stack-1.7.0-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.7.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: gbp_stack-1.7.0-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.7.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 078cf04125f681a8b69ff57bf7b777ee2a70028c516eeedb9cfb883f42e05600
MD5 dbd43db0826c89057c96c5a202b191dc
BLAKE2b-256 ae6ce32a84f3852809eae637a3768ae823748cc3e0bf9b11d050bea644c8e107

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbp_stack-1.7.0-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.7.0-cp311-cp311-manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for gbp_stack-1.7.0-cp311-cp311-manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a8d2cc3e0f1767fdddba870dbcb86578cfb27fcc711422659d86eb55f6472242
MD5 f49769e088d41e9d429e03156e64349d
BLAKE2b-256 0ff0341936d52b3db69d7235914e9b09e87dcb3b027a5e7f5f8a9eac98ba9088

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbp_stack-1.7.0-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.7.0-cp311-cp311-manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for gbp_stack-1.7.0-cp311-cp311-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 11452cd8a49579c08679886afbe3292db3782a0e1a6bb13f3bdfe8802ff30636
MD5 ac60a63a6bb15e51c1c8103ab7e006b7
BLAKE2b-256 f01db730b909b74a1c577d9995c828935f3cf1a6492406f84501084fb3101ffd

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbp_stack-1.7.0-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.7.0-cp311-cp311-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for gbp_stack-1.7.0-cp311-cp311-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 ba565471d1c011d0e6dd672e18683482dd73c5bc3aa11f2292d97fb6aed20963
MD5 96cda64c894b4f74da9b63061ecad785
BLAKE2b-256 9de3f5174718e5a82f79d43c9485544ffa8c52b4a812571e76a8446c60ec2730

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbp_stack-1.7.0-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.7.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for gbp_stack-1.7.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 959eeb5de5761976aac57af79e33c325ae710d1799f7c01832183e7f8df7aec3
MD5 c4bf181f9f889be335c23ebbd946987f
BLAKE2b-256 bbc5205bd8f8084e92e63189efa0f6e946539700db4a495a636c40c3e4c6fa9b

See more details on using hashes here.

Provenance

The following attestation bundles were made for gbp_stack-1.7.0-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