pamoja-session
X25519 key agreement, HKDF, and ChaCha20-Poly1305 with an anti-replay window, with no TLS stack. One capability of pamoja, one memory-safe Rust core with bindings for TypeScript, Python, and C#.
Install
pip install pamoja-session
from pamoja import session
This pulls in pamoja-native, the compiled engine. pip install pamoja is the whole framework in one package.
Example
The script the test suite runs, spliced here as it ran.
From bindings/python/guides/session.py:
import os
from pamoja.core import PamojaError
from pamoja.session import AgreementKey, Role, Session
# Each device is provisioned with a 32-byte seed and publishes the key it derives. A real
# seed comes from the factory or a secure element; any 32 bytes stand in here.
node = AgreementKey(bytes([7]) * 32)
gateway = AgreementKey(bytes([9]) * 32)
# Neither side sends the session key. Both derive it from the shared secret, a salt that
# travels in the clear, and both public keys, with opposite roles.
#
# The salt must be fresh for every session: reusing one derives the same key from the same
# pair of devices twice. The initiator draws it and sends it in the clear, so the responder
# uses the salt it received rather than one of its own.
salt = os.urandom(16)
uplink = Session(node, gateway.public_key, salt, Role.INITIATOR)
downlink = Session(gateway, node.public_key, salt, Role.RESPONDER)
print("agreed both sides derived a key without sending one")
# The pump id is authenticated but not encrypted, so a router still reads it while any
# change to it fails the tag.
sealed = uplink.seal(b"flow=41.2", b"pump-3")
hidden = "still" if sealed.ciphertext == b"flow=41.2" else "no longer"
print(f"sealed counter {sealed.counter}, and what goes on the wire is {hidden} the reading")
print(f"opened {downlink.open(sealed, b'pump-3').decode()}")
# The anti-replay window refuses a counter it has already accepted, so a frame captured
# off the air and sent again is not delivered a second time.
try:
downlink.open(sealed, b"pump-3")
print("a replayed frame was accepted, which should never happen")
except PamojaError as error:
print(f"replay refused: {error}")
# A router that rewrites the pump id breaks the tag, so the gateway refuses the frame rather
# than file the reading under the wrong pump. A frame that fails to open leaves its counter
# unused.
later = uplink.seal(b"flow=41.3", b"pump-3")
try:
downlink.open(later, b"pump-4")
print("a rewritten pump id was accepted, which should never happen")
except PamojaError as error:
print(f"altered refused: {error}")
# Radio frames can arrive out of order. The window accepts any counter it has not seen
# among the 64 below the newest, so the frame that was held up still opens.
newest = uplink.seal(b"flow=41.5", b"pump-3")
first = downlink.open(newest, b"pump-3").decode()
second = downlink.open(later, b"pump-3").decode()
print(f"late counter {newest.counter} opened first, then counter {later.counter}: {first}, then {second}")
# The gateway answers on the same session. Its frames carry the other direction in their
# nonce, so a reply can never be taken for, or replayed as, one from the node.
order = downlink.seal(b"valve=close", b"pump-3")
print(f"reply {uplink.open(order, b'pump-3').decode()}, sealed by the gateway and opened by the node")
The same capability in every language
| Language | Package | Reference |
|---|---|---|
| Rust | pamoja-session |
reference, docs.rs, install |
| TypeScript | @pamoja/session |
reference, install |
| Python | pamoja-session |
reference, install |
| C# | Pamoja.Session |
reference, install |
Documentation
pamoja.sessionreference, every class and function in this module.- The Secured session guide, with the same example in Rust, TypeScript, and C#.
- Every capability, and the install page.
License
MIT
Release files for pamoja-session 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pamoja_session-0.2.0.tar.gz | 5.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pamoja_session-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 10.9 kB
Release files / pamoja_session-0.2.0.tar.gz
| Download URL | pamoja_session-0.2.0.tar.gz |
|---|---|
| Size | 5.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3e945c272370a8a1104bbca5c4b630b24d8f906b9dfc591a573053a603dfd7f0
|
|
BLAKE2b-256 checksum How to use checksums |
fb4c87095f792d38c2c40c8c29968346600e192dc243b8aa3adf8ec1255e2a25
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.15
|
Release files / pamoja_session-0.2.0-py3-none-any.whl
| Download URL | pamoja_session-0.2.0-py3-none-any.whl |
|---|---|
| Size | 5.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
613828f129717fea166cb8ef0e2323294c7fcf57ad06aa898dd7e474ecbc58f6
|
|
BLAKE2b-256 checksum How to use checksums |
f9898292474b5adc789f96e9fa22130efbbb19f273633a6f4330196bd4f855fb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.15
|