tink-py
Google's misuse-resistant cryptography library for Python, providing safe AEAD, MAC, digital signature, and hybrid encryption APIs.
Repository Health
Technical Analysis
Tink is the Python implementation of Google’s Tink cryptography library, built by the same cryptographers and security engineers who fix crypto weaknesses across Google’s products. Rather than exposing low-level primitives that are easy to misuse, Tink wraps authenticated encryption, message authentication codes, digital signatures, hybrid encryption, streaming AEAD, and JWT operations behind small, purpose-built interfaces so that a correct implementation is also the easiest one to write. Keys are managed through keysets rather than raw byte strings, which lets Tink enforce safe defaults, key rotation, and versioning without requiring the caller to understand the underlying cryptographic construction.
Under the hood, tink-py is a thin Python layer over Tink’s C++ core, compiled with Bazel and exposed through pybind11 bindings, so the same audited cryptographic implementations used across Google’s own services back the Python API. It ships integrations for AWS KMS, GCP KMS, and HashiCorp Vault so applications can envelope-encrypt data with keys that never leave a managed key-management service, making it a common choice for teams that need FIPS-adjacent, defense-in-depth encryption without hand-rolling key handling.
What You Get
- AEAD, deterministic AEAD, and streaming AEAD primitives for encrypting data at rest and in transit, including large file streams
- MAC and digital signature primitives for authenticating and verifying data integrity
- Hybrid encryption (public-key) support built on modern constructions like HPKE
- A keyset-handle abstraction that manages key material, versioning, and rotation instead of exposing raw key bytes
- Built-in integration with AWS KMS, GCP KMS, and HashiCorp Vault for envelope encryption with externally managed keys
- JWT signing and verification APIs that apply the same misuse-resistant design to token handling
Common Use Cases
- Encrypting sensitive fields (PII, credentials, tokens) before storing them in a database or object store
- Envelope-encrypting application data with keys held in AWS KMS or GCP KMS so raw key material never leaves the KMS
- Signing and verifying JWTs or other tokens with a safe, well-reviewed API instead of a general-purpose crypto library
- Encrypting large files or streams incrementally with streaming AEAD rather than loading everything into memory
- Rotating encryption keys over time via keysets without changing application code or breaking old ciphertext
Under The Hood
Architecture
The Python package is a binding layer, not a from-scratch crypto implementation: primitive interfaces (tink/aead/_aead.py, tink/mac/, tink/signature/, tink/hybrid/, tink/streaming_aead/) define abstract base classes with abc.ABCMeta, while _keyset_handle.py and core/_key_manager.py route key material and operations through a KeysetHandle that wraps a protobuf-serialized keyset rather than exposing raw keys to callers. The tink/cc/ directory holds the pybind11 glue (cc_key_manager.h, python_input_stream.cc/python_output_stream.cc) that adapts Python file-like objects to Tink’s C++ streaming I/O, and tink/integration/ layers KMS-specific Aead implementations (AWS, GCP, HashiCorp Vault) on top of the same interfaces so envelope encryption is just another primitive from the caller’s point of view. This keeps the primitive surface small and uniform: every crypto operation, whether local or KMS-backed, is reached through the same handful of interfaces.
Tech Stack
tink-py is primarily Python (roughly three-quarters of the codebase) glued to a C++ core (Tink’s canonical implementation) via pybind11, with Starlark/Bazel (MODULE.bazel, BUILD.bazel files throughout) driving the build and Protocol Buffers used for keyset and key-template serialization (tink/proto/). setup.py compiles the C++ extension through Bazel or bazelisk at install time rather than shipping a pure-Python wheel, and optional requirements_awskms.in/requirements_gcpkms.in/requirements_hcvault.in pin the boto3/google-cloud/hvac clients needed for each KMS integration only when that extra is installed.
Code Quality
Every primitive and integration module is paired with a co-located _test.py file (84+ test files across the tree), and the codebase leans on Python type hints throughout its public interfaces (def encrypt(self, plaintext: bytes, associated_data: bytes) -> bytes). Error handling is explicit and centralized around a single TinkError type raised from primitive operations, documented in each method’s docstring rather than left to generic exceptions. The project’s CI badges (visible in the README) cover Bazel and pip builds with and without KMS extras across Linux, macOS, and Windows, indicating cross-platform build verification is part of the standard workflow.
API Design
The public API deliberately narrows what a caller can do: primitives are reached only through interfaces like Aead, Mac, and PublicKeySign, obtained from a KeysetHandle, so there is no direct path to raw key bytes or low-level cipher parameters that could be misused. Getting started requires generating or importing a keyset and selecting a key template rather than choosing algorithm parameters directly, which adds a small amount of upfront ceremony but removes an entire class of common cryptographic mistakes (weak modes, reused nonces, unauthenticated ciphertext) from the caller’s responsibility.