vectorpin
Verifiable integrity for AI embedding stores. Rust reference implementation of the VectorPin attestation protocol.
VectorPin pins each embedding to its source content and the producing model via an Ed25519 signature over a canonical byte representation. Any post-pinning modification of the vector or source text — including covert steganographic exfiltration attacks that current vector databases ingest without complaint — breaks signature verification on read.
This crate is byte-for-byte compatible with the Python reference (pip install vectorpin) and the TypeScript reference (npm install vectorpin). A pin produced by any of the three implementations verifies on the other two; the contract is enforced by shared test vectors that every port consumes in CI.
Part of the ThirdKey Trust Stack, alongside Symbiont — the Rust-native policy-governed agent runtime that consumes these attestations in-process without a Python sidecar.
Quick start
[]
= "0.1"
use ;
// Ingestion: produce an embedding, sign a pin for it.
let signer = generate;
let embedding: = my_model_embed;
let pin = signer.pin?;
// Persist `pin.to_json()` alongside the embedding in your vector DB.
let stored: String = pin.to_json;
// Read/audit: parse the stored JSON and verify against ground truth.
let parsed = from_json?;
let mut verifier = new;
verifier.add_key;
let result = verifier.verify_full;
assert!;
What gets pinned
Each Pin commits to:
- The source text, by SHA-256 of UTF-8 NFC-normalized bytes.
- The model, by identifier (and optionally by content hash).
- The vector itself, by SHA-256 of canonical little-endian f32/f64 bytes.
- The producer, by Ed25519 signing-key identifier (
kid). - The time, by RFC 3339 timestamp.
Verification distinguishes failure modes via the VerifyError enum so callers can route them differently:
| Variant | Meaning |
|---|---|
SignatureInvalid |
Pin was forged or re-signed by an attacker |
VectorTampered |
Embedding modified after pinning — the steganography kill shot |
SourceMismatch |
Source text differs from what was pinned |
ModelMismatch |
Pin produced by a different embedding model than expected |
UnknownKey |
Pin signed by a key not in the verifier's registry |
UnsupportedVersion |
Protocol version mismatch |
ShapeMismatch |
Supplied vector's dim disagrees with the pin header |
Threat model
VectorPin is designed against an attacker who can:
- Modify vectors after they are produced — via a poisoned ingestion pipeline, a compromised vector DB, or backup-level access.
- See the public verification key but not the private signing key.
- Replay or selectively delete pins.
It does not defend against:
- An attacker with the private signing key (key custody is the user's responsibility).
- An attacker who modifies the source documents before embedding (use upstream content integrity controls).
- An attacker who uses a legitimate signing key to attest a malicious vector at ingestion time (use upstream input validation).
For the empirical evaluation of the attack class VectorPin is built to defeat, see the companion preprint at https://doi.org/10.5281/zenodo.20058256.
Status
Alpha (v0.1). Protocol v1 stable; covered by the cross-language test vectors. The wire format will not break compatibility without a major-version bump.
See the full protocol specification and docs.rs for the complete API reference.
License
Apache 2.0.