Skip to main content

ubirch-protocol for python

This is an implementation of the ubirch-protocol for Python 3. Please see ubirch-protocol for details.

The library consists of three parts which can be used individually:

  • ubirch.API - a python layer covering the ubirch backend REST API
  • ubirch.Protocol - the protocol compiler which packages messages and handles signing and verification
  • ubirch.KeyStore - a simple key store based on pyjks to store keys and certificates

the ubirch protocol uses the Ed25519 signature scheme by default.

Usage

Install the library: pip install ubirch-protocol

Creating keypair and messages

import ubirch
from uuid import UUID
import binascii

# create a keystore for the device keypair
keystore = ubirch.KeyStore("demo-device.jks", "keystore")

# create a UUID that identifies the device and load or create a keypair
uuid = UUID(hex="575A5601FD744F8EB6AEEF592CDEE12C")
if not keystore.exists_signing_key(uuid):
    keystore.create_ed25519_keypair(uuid)

# implement the _sign method of the ubirch.Protocol to use the just created keys to sign the message
class ProtocolImpl(ubirch.Protocol):
    def _sign(self, uuid: UUID, message: bytes) -> bytes:
        return keystore.find_signing_key(uuid).sign(message)        

# create an instance of the ubirch protocol
proto = ProtocolImpl()

# create ubirch protocol messages
print(binascii.hexlify(proto.message_chained(uuid, 0x00, [1, 2, 3])))
print(binascii.hexlify(proto.message_chained(uuid, 0x00, [4, 5, 6])))

Sending messages using the ubirch API

Please see test-protocol.py for a comprehensive example, how to create a device and send data. Below is a snipped that will send two chained messages, using a generic key/value payload.

You will need a password for the ubirch backend. Go to https://console.demo.ubirch.com to register your UUID under Things. Then click on your device and copy the password from the apiConfig-field.

import ubirch
from uuid import UUID
import binascii
from datetime import datetime

# create a keystore for the device key pair
keystore = ubirch.KeyStore("demo-device.jks", "keystore")

# create a UUID that identifies the device and load or create a key pair
uuid = UUID(hex="575A5601FD744F8EB6AEEF592CDEE12C")
if not keystore.exists_signing_key(uuid):
    keystore.create_ed25519_keypair(uuid)


# implement the _sign method of the ubirch.Protocol
class ProtocolImpl(ubirch.Protocol):
    def _sign(self, _uuid: UUID, message: bytes) -> bytes:
        return keystore.find_signing_key(uuid).sign(message)


# create an instance of the ubirch protocol
proto = ProtocolImpl()

# create an instance of the ubirch API and set the password
api = ubirch.API()
api.set_authentication(uuid, "<< password for the ubirch backend >>")  # register your UUID at https://console.demo.ubirch.com and retrieve your password

# message 1
msg = proto.message_chained(uuid, 0x53, {'ts': int(datetime.utcnow().timestamp()), 'v': 99})
print(binascii.hexlify(msg))
# send message to ubirch backend
r = api.send(uuid, msg)
print("{}: {}".format(r.status_code, r.content))

# message 2 (chained to message 1)
msg = proto.message_chained(uuid, 0x53, {"ts": int(datetime.utcnow().timestamp()), "v": 100})
print(binascii.hexlify(msg))
# send message to ubirch backend
r = api.send(uuid, msg)
print("{}: {}".format(r.status_code, r.content))

Verification of received message

import ubirch
from ed25519 import VerifyingKey, BadSignatureError
from uuid import UUID

remote_uuid = UUID(hex="9d3c78ff22f34441a5d185c636d486ff")
remote_vk = VerifyingKey("a2403b92bc9add365b3cd12ff120d020647f84ea6983f98bc4c87e0f4be8cd66", encoding='hex')

# create a keystore and insert the verifying key
keystore = ubirch.KeyStore("demo-device.jks", "keystore")
keystore.insert_ed25519_verifying_key(remote_uuid, remote_vk)

# implement the _verify method of the ubirch.Protocol
class ProtocolImpl(ubirch.Protocol):
    def _verify(self, uuid: UUID, message: bytes, signature: bytes) -> dict:
        return keystore.find_verifying_key(uuid).verify(signature, message)

# create an instance of the ubirch protocol
proto = ProtocolImpl()

message = bytes.fromhex(
    "9623c4109d3c78ff22f34441a5d185c636d486ffc440a5b371acdfc8495790ee86802399585da50401b0d3c87f60946719338eb0283d36c0bac9b8a6a75a5385342e62932335da988b97c0ec211556db082e9f8478070081a76d657373616765bf796f7572207265717565737420686173206265656e207375626d6974746564c440c8529623a4c2335f7a8ae1eeea655768d2e9a0df141f481ced557c9dac7216e8f64ca9f6970fc6c1096ed49bcc6f7fa77d8f85d05bff5e1301588597edc9770e")

# verify the message (throws an exception if the message could not be verified)
try:
    print(proto.message_verify(message))
    print("verification successful!")
except BadSignatureError as e:
    print("ERROR: verification failed!")

Existing keys

In case you create a key pair from our demo website, use the following code to insert it into the key store:

import ubirch
import ed25519
import uuid

hwDeviceId = uuid.uuid4()
keystore = ubirch.KeyStore("demo-device.jks", "keystore")
key_encoded = input("paste the encoded private key here:")
sk = ed25519.SigningKey(key_encoded, encoding='hex')
vk = sk.get_verifying_key() 

keystore.insert_ed25519_keypair(hwDeviceId, vk, sk)

Running the example

python3 -m venv venv3
. venv3/bin/activate
pip install -r requirements.txt
pip install ubirch-protocol
PYTHONPATH=. python3 examples/test-protocol.py

At the first launch the script generates a random UUID for your device and you will be asked about the authentication token and the device group. You can safely ignore the device group, just press Enter. The script creates a file demo-device.ini which is loaded upon running the script again. If you need to change anything edit that file.

The script goes through a number of steps:

  1. checks the existence of the device and deletes the device if it exists
  2. registers the device with the backend
  3. generates a new identity for that device and stores it in the key store
  4. registers the new identity with the backend
  5. sends two consecutive chained messages to the backend

Testing

Unit tests are added to test the functionality of all objects provided in this library.

pip install -r requirements.test.txt
python3 -m pytest tests

License

The protocol and its implementation are publicized under the Apache License 2.0.

Metadata

Release files for ubirch-protocol 3.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ubirch-protocol 3.1.0
File Size Uploaded Provenance Actions
ubirch-protocol-3.1.0.tar.gz 15.2 kB Without provenance Details for ubirch-protocol-3.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for ubirch-protocol 3.1.0
File Interpreter ABI Platform Actions
ubirch_protocol-3.1.0-py3-none-any.whl Python 3 none any Details for ubirch_protocol-3.1.0-py3-none-any.whl

Total release size: 30.5 kB

Release files / ubirch-protocol-3.1.0.tar.gz

Download URL ubirch-protocol-3.1.0.tar.gz
Size 15.2 kB
Tags Source
SHA-256 checksum
How to use checksums
3791f62991cd9881fcee8014972ae2cd0ae5e9f3da1b9a829b8d0f9d2932b4c2
BLAKE2b-256 checksum
How to use checksums
165a466dae0503f5c343b7f7913c5e2c55390b3e737d652cbf184deabf07dac0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.1 CPython/3.10.4

Release files / ubirch_protocol-3.1.0-py3-none-any.whl

Download URL ubirch_protocol-3.1.0-py3-none-any.whl
Size 15.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2b298dd33fe9180ea4a9ad524b38664e115e8ad7c213ce7f071eb9cbce29a697
BLAKE2b-256 checksum
How to use checksums
2ad663c72afee61da1bc68ec426770fbf81c89cf8e5810d0df7bd0e7642fa6ee
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.1 CPython/3.10.4

Security for ubirch-protocol 3.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page