A ubirch-protocol implementation for python.
Project description
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 APIubirch.Protocol
- the protocol compiler which packages messages and handles signing and verificationubirch.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 ubirch.ubirch_protocol import CHAINED
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 on the ubirch.Protocol to use the just created
# keys to sign the message and add methods to save and load the last signature
class ProtocolImpl(ubirch.Protocol):
def _sign(self, uuid: UUID, message: bytes) -> bytes:
return keystore.find_signing_key(uuid).sign(message)
proto = ProtocolImpl(CHAINED)
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 the generic key/value payload.
You will need an authentication token for the ubirch backend. Feel free to contact us, self on-bording is on it's way!
import ubirch
import uuid
import binascii
from datetime import datetime
uuid = uuid.uuid4()
proto = ubirch.Protocol()
api = ubirch.API()
# message 1
msg = proto.message_chained(uuid, 0x53, {'ts': int(datetime.utcnow().timestamp()), 'v': 99})
print(binascii.hexlify(msg))
r = api.send(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))
r = api.send(msg)
print("{}: {}".format(r.status_code, r.content))
Verification of received message
import ubirch
import hashlib
from ed25519 import VerifyingKey
from uuid import UUID
from ubirch.ubirch_protocol import SIGNED
remote_uuid = UUID(hex="6eac4d0b-16e6-4508-8c46-22e7451ea5a1")
remote_vk = VerifyingKey("b12a906051f102881bbb487ee8264aa05d8d0fcc51218f2a47f562ceb9b0d068", encoding='hex')
# a random signed ubirch-protocol message
keystore = ubirch.KeyStore("demo-device.jks", "keystore")
keystore.insert_ed25519_verifying_key(remote_uuid, remote_vk)
class ProtocolImpl(ubirch.Protocol):
def _verify(self, uuid: UUID, message: bytes, signature: bytes) -> dict:
hash = hashlib.sha512(message).digest()
return keystore.find_verifying_key(uuid).verify(signature, hash)
proto = ProtocolImpl(SIGNED)
message = bytes.fromhex(
"9512b06eac4d0b16e645088c4622e7451ea5a1ccef01da0040578a5b22ceb3e1"
"d0d0f8947c098010133b44d3b1d2ab398758ffed11507b607ed37dbbe006f645"
"f0ed0fdbeb1b48bb50fd71d832340ce024d5a0e21c0ebc8e0e")
print(proto.message_verify(message))
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:
- checks the existence of the device and deletes the device if it exists
- registers the device with the backend
- generates a new identity for that device and stores it in the key store
- registers the new identity with the backend
- sends two consecutive chained messages to the backend
Example: Web-of-Trust
Before First Execution
python3 -m venv venv3
pip install -r requirements.txt
Running The Example
. venv3/bin/activate
PYTHONPATH=. python3 examples/test-web-of-trust.py
During first launch the script generates key pairs for two users. Each user has one device and key pairs are created for
these, too. All key pairs are stored in test-web-of-trust.jks
while the association of users, their device and the
respective key pair is stored in demo-web-of-trust.ini
. In consecutive runs no new key pairs are generated and instead
the ones referenced in demo-web-of-trust.ini
are used.
The script always uploads all public keys, followed by creating and uploading a web-of-trust and searching all public
keys trusted by deviceA
. This search is repeated with different parameters. The results are then printed onto the
terminal.
The web-of-trust created looks as follows (trust knows a direction; always bidirectional in this example):
deviceA <--trustLevel=100--> user1 <--trustLevel=50--> user2 <--trustLevel=100--> deviceB
The first search for all trusted keys is for a minimum trust of 50 and a depth of 3 resulting in the the following keys being found:
- user1
- user2
- deviceB
The second search increases the minimum trust to 60 resulting in:
- user1
And the third search is with a minimum trust of 50 again while the depth is now 2 resulting in:
- user1
- user2
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.