ib1-provenance
Python library to create, sign and verify records that follow the IB1 Provenance Records 1.0 specification.
Requires Python 3.11 or later. See CHANGELOG.md for changes between versions.
Install
pip install ib1-provenance
To sign with a key held in AWS KMS, install the kms extra:
pip install "ib1-provenance[kms]"
Use
A record is built from steps, then signed with a signing certificate issued by the Directory. A participant who receives a record verifies it, adds its own steps, and signs it again.
from ib1.provenance import Record
from ib1.provenance.certificates import CertificatesProviderSelfContainedRecord
from ib1.provenance.signing import SignerFiles
TRUST_FRAMEWORK_URL = "https://registry.core.trust.ib1.org/trust-framework"
with open("signing-ca-root.pem", "rb") as f:
provider = CertificatesProviderSelfContainedRecord(f.read())
# Create and sign a record
record = Record(TRUST_FRAMEWORK_URL)
origin_id = record.add_step({"type": "origin", "scheme": "...", ...})
record.add_step({"type": "transfer", "of": origin_id, "scheme": "...", ...})
signer = SignerFiles(provider, "signing-bundle.pem", "signing-key.pem")
signed = record.sign(signer)
attachment = signed.encoded() # JSON-serialisable dict to send with the data
# Receive and verify a record
received = Record(TRUST_FRAMEWORK_URL, attachment)
received.verify(provider)
transfer = received.find_step({"type": "transfer", "to": "https://directory.core.trust.ib1.org/member/81524"})
received.require_signer(transfer["id"], role="https://registry.core.trust.ib1.org/scheme/perseus/role/energy-data-provider")
main.py has a full example of a record passed between three members.
Certificate providers
CertificatesProviderSelfContainedRecordincludes the signing certificate and its issuer chain in the record, and uses them to verify. Use this one unless you have a reason not to.CertificatesProviderLocalreads certificates from a local directory and leaves them out of the record, which makes it smaller.
Both take the signing root CA certificate from the Directory. A root CA certificate included in a record is never trusted.
Signers
SignerFilesreads the certificate bundle and private key from PEM files.SignerInMemorytakescryptographycertificate and key objects.SignerKMSsigns with a key in AWS KMS. It needs thekmsextra.
Checks
add_step() and sign() check that new steps follow the specification: step types, timestamps, references between steps, and at least one origin step. They raise ValidationError, and sign() raises before the signer is called.
verify() checks signatures, certificates and the structure of the signed record. It does not repeat the step checks, so records signed by older versions still verify. To check the steps of a received record, call validate() after verify(). It returns a list of problems and does not raise.
Revocation is not checked yet, see directory#272.
Exceptions
All exceptions raised by the library subclass ProvenanceError, which can be imported from ib1.provenance:
ValidationError, a record or step does not follow the specificationVerificationError, a signed record could not be verifiedCertificateError, a certificate is missing or does not have the expected contentsCertificateNotFoundError, a certificate serial number is not available. It is also aKeyError.
A bad signature raises cryptography.exceptions.InvalidSignature. A certificate chain which is not valid at the signing time raises cryptography.x509.verification.VerificationError.
Develop
pipx install poetry
poetry install
poetry run pytest
poetry run ruff check .
tests/vectors/ holds a signed record and the exact data that was signed, for checking other implementations against this one. tests/vectors/generate.py regenerates them.
Run the example
main.py needs a set of test certificates, which scripts/certmaker.sh creates. The certificates expire, so run it again if the example fails with "cert is not valid at validation time".
mkdir certs
cd certs
sh ../scripts/certmaker.sh
cd ..
poetry run python main.py
Decode a record
poetry run python decode-self-contained-provenance.py path/to/signing-CA-root.pem < record.json
Publish the library
- Add the release notes to
CHANGELOG.md. - Change
versioninpyproject.toml. - Merge to
main, then tag the merge commit, for examplegit tag v0.6.0 && git push origin v0.6.0. - Build and publish:
poetry build
poetry publish
Metadata
Release files for ib1-provenance 0.6.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 | Provenance | Actions |
|---|---|---|---|---|
| ib1_provenance-0.6.0.tar.gz | 13.9 kB | Without provenance | Details for ib1_provenance-0.6.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| ib1_provenance-0.6.0-py3-none-any.whl | Python 3 | none | any | Details for ib1_provenance-0.6.0-py3-none-any.whl |
Total release size: 28.6 kB
Release files / ib1_provenance-0.6.0.tar.gz
| Download URL | ib1_provenance-0.6.0.tar.gz |
|---|---|
| Size | 13.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
884ac0002390bdfafda1d7d62e13617db6406dcc0dd770198565337e71fc06bb
|
|
BLAKE2b-256 checksum How to use checksums |
d7dbc0b12aeeea906fe5305acc91b5c66924ef370d39a8a7f00f93c9f5aa0d69
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.3 CPython/3.12.16 Darwin/24.6.0
|
Release files / ib1_provenance-0.6.0-py3-none-any.whl
| Download URL | ib1_provenance-0.6.0-py3-none-any.whl |
|---|---|
| Size | 14.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bc650d6677a7c6e3b192907c5941d2d630ad7097118e56ec22112d9dffd3d013
|
|
BLAKE2b-256 checksum How to use checksums |
c4fffbfc2e3c0660bb13e33e3cc8405cf74c274b91f0f2a8e48f2001dd87e0e7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.3 CPython/3.12.16 Darwin/24.6.0
|
Security for ib1-provenance 0.6.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.