Metadata-Version: 2.4
Name: gtec_attest
Version: 0.1.0
Summary: g.tec attestation verifier (contains only public keys)
Author-email: "g.tec medical engineering GmbH" <support@gtec.at>
License-Expression: LicenseRef-GNCL
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Developers
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE-GNCL.txt
Provides-Extra: test
Requires-Dist: pytest>=8.0; extra == "test"
Requires-Dist: pytest-cov>=5.0.0; extra == "test"
Requires-Dist: pytest-html>=4.1.1; extra == "test"
Requires-Dist: coverage>=7.6.1; extra == "test"
Requires-Dist: setuptools_scm; extra == "test"
Requires-Dist: cryptography>=46.0.3; extra == "test"
Provides-Extra: build
Requires-Dist: setuptools>=75.3.2; extra == "build"
Requires-Dist: build>=1.2.2; extra == "build"
Requires-Dist: wheel>=0.45.1; extra == "build"
Requires-Dist: setuptools_scm; extra == "build"
Provides-Extra: lint
Requires-Dist: flake8==7.3.0; extra == "lint"
Requires-Dist: black==25.1.0; extra == "lint"
Requires-Dist: isort==6.0.1; extra == "lint"
Provides-Extra: pypi
Requires-Dist: twine; extra == "pypi"
Provides-Extra: release
Requires-Dist: requests; extra == "release"
Provides-Extra: vectors
Requires-Dist: cryptography>=46.0.3; extra == "vectors"
Dynamic: license-file

# gtec_attest

**Contains only public keys. The signing keys live in the amplifier packages.**

Verification of g.tec amplifier attestations. An amplifier package signs a
challenge with a private key held in its compiled layer; this package checks
that signature against a public key it carries.

It returns a **verdict about a device** — never a permission, tier or
entitlement. Mapping verdicts onto entitlements is the consuming product's job.

## Install

```
pip install gtec_attest
```

Wheels are published for Windows, macOS (universal2) and manylinux across
CPython 3.10 to 3.14.

## Use

```python
import gtec_attest

nonce = gtec_attest.mint_nonce()              # 32 bytes, once per device
attestation = amp.attest(nonce)               # 67 bytes from the amplifier

verdict = gtec_attest.verify(
    attestation,
    serial=amp.serial_number,                 # byte-identical to the handle
    nonce=nonce,
)

if verdict:
    ...                                       # genuine device
else:
    log.warning("unattested source: %s", verdict.reason.name)
```

`verify()` is a pure function: no I/O, no clock, no network.

| Field | Meaning |
|---|---|
| `verified` | `True` only if the signature checks out against an accepted key |
| `key_id` | The key ID carried in the attestation |
| `serial` | Echo of the serial you passed in |
| `reason` | `OK`, `BAD_SIGNATURE`, `UNKNOWN_KEY_ID`, `MALFORMED`, `SERIAL_MISMATCH`, `RETIRED_KEY` |

Mint one nonce per device per pipeline start with `mint_nonce()`. Never reuse
one and never cache one.

## Integration notes

Products that **enforce** on the verdict should not rely on importing this
module. Contact g.tec for the integration component and guidance.

---

© g.tec medical engineering GmbH — support@gtec.at
