A cryptographic protocol for proving boot integrity and hardware security without revealing machine identity, software configuration, or platform measurements.
Proving System
Groth16 / BLS12-381
Proof Size
192 bytes
Verifying Key
872 bytes
Version
1.0.0 / March 2026
The Problem With Remote Attestation
Current attestation protocols sacrifice privacy for security. We propose a different approach.
When a machine proves it runs authorized software, today's protocols force complete disclosure. The verifier receives exact firmware versions, bootloader configurations, kernel hashes, and TPM measurements. Each attestation quote carries a permanent hardware identifier that links every session to the same physical device.
This creates surveillance infrastructure disguised as security. Attestation services accumulate detailed histories of what software runs where, when configurations change, and how machines behave over time. A feature designed to establish trust instead enables tracking.
What Gets Disclosed
Platform Configuration Registers encode a hash chain of every software component loaded during boot. The sequence of firmware, bootloader, kernel modules, and configuration files produces a unique fingerprint. TPM endorsement keys serve as permanent identifiers. Attestation quotes bind these together into complete machine profiles.
The Resulting Threat
Verifiers accumulate boot histories. They correlate activity across sessions, identify configuration changes, and build detailed profiles of infrastructure. What begins as security verification becomes comprehensive surveillance. The attestation relationship inverts from authentication to tracking.
Our Approach
We separate proof from disclosure. Zero-knowledge proofs allow a machine to demonstrate satisfaction of security requirements without revealing any private information. The verifier learns exactly one bit: whether the attestation is valid.
The prover demonstrates knowledge of valid PCR measurements, hardware attestation credentials, and kernel identity. The proof reveals nothing about what those values actually are. Two machines running identical proofs cannot be distinguished. Two proofs from the same machine cannot be linked.
This preserves the security guarantees of remote attestation while eliminating the privacy costs. Verifiers confirm that machines meet requirements. They learn nothing else.
Privacy Guarantees
The zero-knowledge property provides information-theoretic hiding. Even an unbounded adversary with unlimited computational power cannot extract private witness values from a valid proof. The proof system reveals only that a valid witness exists, not what that witness contains.
Machine identifiers never leave the proving environment. The machine_id field binds the attestation to specific hardware through a 32-byte identifier derived from TPM endorsement credentials. This identifier appears as a public input to enable revocation and audit, but the underlying hardware identity remains hidden behind a one-way derivation. No verifier can reverse the derivation to recover the original TPM endorsement key.
Boot measurements stay private. The pcr_preimage field contains the raw TPM Platform Configuration Register values, a 64-byte concatenation of PCR readings that encode the complete boot sequence. The circuit verifies entropy requirements and validity constraints on these measurements without exposing them. Verifiers confirm the measurements satisfy policy without learning what software actually booted.
Target Properties
What we aim to achieve with this system.
Property
Description
Status
Kernel Binding
Proof cryptographically bound to specific kernel binary hash
Implemented
Hardware Verification
Demonstrate TPM presence and attestation capability without revealing endorsement key
Implemented
PCR Privacy
Platform measurements verified within circuit but never disclosed to verifier
Implemented
Replay Prevention
Fresh nonce per boot session prevents proof reuse
Implemented
Machine ID Attestation
Hardware-bound identifier for revocation without revealing TPM EK
Implemented
Threshold Signing
Key distribution across multiple parties using FROST protocol
Implemented
Build Provenance
Reproducible build verification through source and toolchain hashes
Implemented
Capsule Commitment
Application-specific data binding for workload attestation
Implemented
Set Membership
Prove kernel belongs to authorized set without revealing which one
Planned
Recursive Composition
Chain multiple attestation proofs into single succinct proof
Planned
What Makes This Different
Traditional attestation requires disclosure. Intel SGX remote attestation reveals the enclave identity and signer. AMD SEV attestation exposes the measurement of the guest image. ARM TrustZone attestation transmits device certificates containing hardware identifiers. Every major platform ties security verification to identity disclosure.
Our approach breaks this coupling. The attestation proves security properties hold without revealing which specific values satisfy them. A machine can attest repeatedly without creating a linkable trail. Multiple machines can provide indistinguishable attestations. The security guarantee transfers without the tracking capability.
Implementation Status
Core infrastructure operational. Production artifacts generated.
The attestation circuit, key generation infrastructure, proof embedding system, and bootloader verification logic are complete and tested. The system produces valid proofs that verify correctly on target hardware. All cryptographic primitives use audited implementations from the arkworks ecosystem.
192Proof Bytes
872VK Bytes
1.68MPK Bytes
10Public Inputs
Completed Components
Circuit Implementation
R1CS constraint system encoding kernel hash verification, PCR entropy requirements, hardware attestation level checks, and program identity binding. The circuit operates over the BLS12-381 scalar field with approximately 15,000 constraints. Constraint generation uses arkworks for R1CS synthesis with optimized variable allocation.
Key Generation
Deterministic key derivation from structured seed material using the nonos-attestation-v1 seed. The proving key enables proof generation and weighs 1,681,008 bytes. The verifying key is embedded in the bootloader for runtime verification at 872 bytes. Both keys derived from the same ceremony output with reproducible generation.
Proof Generation
Groth16 prover generating constant-size 192-byte proofs regardless of circuit complexity. The proof consists of three curve points: A in G1 (48 bytes compressed), B in G2 (96 bytes compressed), and C in G1 (48 bytes compressed). Proofs embed in kernel images alongside Ed25519 signatures and structured public inputs.
Bootloader Verification
Runtime verification using arkworks BLS12-381 implementation with constant-time pairing operations. Verification checks signature validity, proof correctness, and hash binding in sequence. Failure at any stage aborts boot. The verifying key fingerprint is checked against a compile-time constant before use.
Production Build Artifacts
The following cryptographic material was generated on March 29, 2026. The verifying key BLAKE3 fingerprint provides a compact identifier for the key material. The SHA-256 hash enables cross-verification with systems that use different hash functions. Both values are computed over the canonical 872-byte serialization.
Command-line utilities for the attestation workflow.
The attestation system comprises six command-line tools that handle different stages of the workflow. Key generation runs once to produce the proving and verifying keys. Proof generation runs for each kernel build. Embedding combines the kernel binary with its cryptographic attestation. The signing tools support both single-party and threshold key management.
Tool
Location
Purpose
generate-keys
nonos-attestation-circuit/
Proving and verifying key generation from seed
generate-proof
nonos-attestation-circuit/
Groth16 proof generation from witness
embed-zk-proof
embed-zk-proof/
Proof embedding in kernel binary images
sign-kernel
sign-kernel/
Ed25519 signature generation
threshold-sign
threshold-sign/
FROST distributed key generation and signing
zk-ceremony
zk-ceremony/
Multi-party trusted setup coordination
Build Integration
The toolchain integrates with the standard build process. After compiling the kernel binary, the build system invokes generate-proof with the kernel hash, boot nonce, machine identifier, and PCR preimage. The resulting proof passes to embed-zk-proof which appends the ZK block and footer. Finally, sign-kernel applies the Ed25519 signature over the complete package.
For production deployments, threshold-sign replaces sign-kernel. The signing key is split across multiple parties using FROST key generation. Producing a signature requires t-of-n parties to participate in a two-round signing protocol. No single party ever possesses the complete signing key.
System Architecture
How components interact at build time and boot time.
The attestation system operates in two distinct phases with different security requirements. Build time happens in a controlled environment with access to private keys and witness data. Boot time happens on potentially hostile hardware where only public verification material is available. The architecture ensures that private data never crosses from build to boot.
Build Phase
Key generation produces the proving key used during proof creation and the verifying key embedded in the bootloader. This step runs once during initial setup or when upgrading the attestation circuit. The proving key must remain confidential to prevent unauthorized proof generation. The verifying key is public and distributed with the bootloader.
Proof generation takes the proving key and private witness data to produce a constant-size proof. The witness includes the PCR preimage, hardware attestation level, and other sensitive values. These values never appear in the output. The proof demonstrates knowledge of valid witnesses without revealing them.
The kernel signer applies an Ed25519 signature over the kernel binary. This provides authentication independent of the ZK proof. A valid boot requires both a valid signature and a valid proof. The signature confirms the kernel comes from an authorized source. The proof confirms the kernel satisfies attestation requirements.
Finally, the embedding tool combines the kernel, signature, proof, and structured metadata into a single bootable image. The output format places components at deterministic offsets for efficient bootloader parsing.
Boot Phase
The bootloader performs four verification steps before transferring control to the kernel. Each step must pass for boot to proceed. Failure at any stage halts the boot process and displays an error code.
Image loading parses the footer to locate component boundaries. The footer appears at a fixed 64-byte offset from the end of the image, containing magic bytes, version information, and size fields for each component. Invalid magic bytes or inconsistent sizes abort loading.
Signature verification checks the Ed25519 signature over the kernel binary using the embedded public key. This confirms the kernel was signed by an authorized party. The public key is compiled into the bootloader and cannot be changed at runtime.
Proof verification performs the Groth16 pairing check using the embedded verifying key. This confirms the proof was generated by someone with access to the proving key and valid witness data. The verification equation requires three pairing operations regardless of circuit size.
Hash verification computes the BLAKE3 hash of the kernel binary and confirms it matches the public input in the ZK block. This binds the proof to the specific kernel being loaded. A proof generated for one kernel cannot be used to boot a different kernel.
Cryptographic Primitives
The mathematical foundations underlying the protocol.
The system combines multiple cryptographic primitives to achieve its security goals. Each primitive addresses a specific requirement. The combination provides layered security where failure of one component does not compromise the others.
Component
Algorithm
Size
Security
Zero-knowledge proof
Groth16
192 bytes
Knowledge soundness
Pairing curve
BLS12-381
~381 bits
~128-bit discrete log
Digital signature
Ed25519
64 bytes
~128-bit ECC
Cryptographic hash
BLAKE3
32 bytes
Collision resistant
Threshold signatures
FROST
64 bytes
t-of-n security
Groth16 Verification Equation
Groth16 is a pairing-based SNARK with the shortest known proofs for R1CS constraint systems. The proof consists of three group elements: A and C in G1, B in G2. Verification checks a single equation involving bilinear pairings.
Given a proof (A, B, C) and public inputs x1 through xl, verification computes:
e(A, B) = e(α, β) · e(Σᵢ xᵢ·γᵢ, γ) · e(C, δ)
The left side evaluates the pairing of the proof elements A and B. The right side combines three pairings: a constant term from the verifying key, a public input commitment, and the proof element C. Equality holds if and only if the proof is valid for the given public inputs.
Verification requires exactly three pairing computations regardless of the original circuit size. This constant verification cost makes Groth16 attractive for resource-constrained environments like bootloaders. The tradeoff is a trusted setup requirement addressed through multi-party ceremonies.
BLS12-381 Curve Parameters
BLS12-381 is a pairing-friendly elliptic curve designed for use with BLS signatures and zkSNARKs. The curve provides approximately 128 bits of security against discrete logarithm attacks. The embedding degree of 12 balances efficient pairing computation against security requirements.
Field Modulus p (381 bits)0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
Scalar Order r (255 bits)0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001
G1 elements serialize to 48 bytes in compressed form. G2 elements serialize to 96 bytes compressed. The scalar field has order r, a 255-bit prime with efficient arithmetic due to its special form. Field operations use Montgomery multiplication for constant-time execution.
Binary Format
Structure of an attested kernel image.
The attested kernel image concatenates four components: the kernel binary, Ed25519 signature, ZK block, and footer. The footer appears at a fixed offset from the end, allowing the bootloader to locate components without scanning the entire image.
The ZK block uses magic bytes 0x4E 0xC3 0x5A 0x50 (chosen to not appear in typical binary executables) followed by a version number. Version 2 is the current format. The block contains five 32-byte hashes: program hash, capsule commitment, kernel hash, boot nonce, and machine identifier. These serve as public inputs to the proof.
The footer uses magic bytes "NONOSIMG" (8 bytes) for format identification. It contains version information, flags for optional features, algorithm identifiers, and byte counts for each component. The bootloader reads the footer first, validates its structure, then uses the size fields to locate other components.
Circuit Design
The constraint system that defines valid attestations.
The attestation circuit encodes security requirements as R1CS constraints. A valid proof demonstrates that the prover possesses private witness values satisfying all constraints, without revealing those values. The circuit separates inputs into public values visible to verifiers and private witnesses known only to the prover.
Input Structure
Public Input Details
The kernel_hash field contains the BLAKE3 hash of the kernel binary. This binds the attestation to a specific executable. The bootloader computes this hash at load time and compares it against the public input. Any modification to the kernel invalidates the proof.
The boot_nonce field provides freshness. Each boot session generates a new 32-byte random value. Including the nonce as a public input prevents replay attacks where an old proof might be presented for a new boot. The nonce appears in the ZK block and can be verified externally.
The machine_id field identifies the hardware without revealing the underlying TPM endorsement key. The identifier derives from the TPM EK through a one-way function, preserving unlinkability while enabling revocation. A compromised machine can be blocked by its machine_id without exposing the EK.
The capsule_commitment field supports application-specific attestation. Applications can bind additional data into the proof through this commitment. The circuit verifies the commitment against witness data without revealing the committed values. This enables workload-specific attestation beyond base boot integrity.
The program_hash field identifies the attestation circuit itself. This prevents attacks where a malicious prover might use a modified circuit with weakened constraints. The verifier checks that the program hash matches the expected value for the legitimate attestation program.
Private Witness Details
The pcr_preimage field contains raw TPM Platform Configuration Register values. These 64 bytes encode the complete boot measurement chain. The circuit verifies entropy and structural requirements on these values without exposing them. Verifiers learn that the measurements satisfy policy without learning what actually booted.
The hardware_attestation field encodes the hardware security level as a 64-bit integer. Higher values indicate stronger security features. The circuit enforces a minimum threshold, proving the hardware meets requirements without revealing the exact capability level.
Constraint Categories
Program Identity Verification
The circuit enforces that the program hash matches a compile-time constant. This binds the proof to a specific version of the attestation program, preventing substitution attacks where an adversary might attempt to use a modified circuit that accepts invalid witnesses. The expected hash derives from the program identifier string using domain-separated BLAKE3.
constants.rs:101-105
pub fn expected_program_hash_bytes() -> [u8; 32] {
let mut h = blake3::Hasher::new_derive_key("NONOS:ZK:PROGRAM:v1");
h.update(b"zkmod-attestation-program-v1");
*h.finalize().as_bytes()
}
Non-Zero Hash Enforcement
Critical hashes must contain at least one non-zero byte. This prevents trivial attacks where all-zero values might bypass verification logic or indicate uninitialized data. The constraint counts non-zero bytes across the hash and requires the sum to be positive. This applies to kernel_hash, boot_nonce, machine_id, and capsule_commitment.
PCR Entropy Requirements
The PCR preimage must contain sufficient entropy to indicate a genuine boot measurement rather than a fabricated value. The circuit counts non-zero bytes in the measurement and enforces a minimum threshold of 32 non-zero bytes (from the 64-byte preimage). This prevents attestation with zeroed or low-entropy PCR values that might indicate measurement bypass or trivial forgery.
Hardware Attestation Level
The attested hardware security level must exceed a minimum threshold. The circuit defines four levels with increasing security requirements. The minimum threshold is 0x1000, requiring at least TPM 2.0 presence. Higher levels indicate additional security features.
Level
Value
Requirements
Base
0x1000
TPM 2.0 present and functional
Verified Boot
0x2000
Secure boot chain verified by TPM
Enclave
0x4000
Trusted execution environment available
Hardware Root
0x8000
Hardware root of trust with remote attestation
Build Provenance
Reproducible build verification through cryptographic commitments.
The attestation system optionally supports build provenance verification. This extends the attestation from "this kernel is authorized" to "this kernel was built from this source with this toolchain." Build provenance enables supply chain verification without requiring access to build infrastructure.
Provenance encodes four components: source tree hash, dependency lock hash, compiler version hash, and build configuration hash. Each component uses domain-separated BLAKE3 to prevent cross-component collisions.
Component
Domain
Inputs
Source Tree
NONOS:BUILD:SOURCE_TREE:v1
Git commit hash + tree hash
Cargo Lock
NONOS:BUILD:CARGO_LOCK:v1
Complete Cargo.lock contents
Rustc Version
NONOS:BUILD:RUSTC_VERSION:v1
Version string + compiler commit
Build Config
NONOS:BUILD:CONFIG:v1
Cargo.toml + .cargo/config.toml
The four component hashes combine into a single 32-byte composite hash using the NONOS:BUILD:PROVENANCE:v1 domain. This composite can serve as a public input for provenance-aware attestation circuits, binding the proof to specific build conditions.
Domain Separation
Preventing cross-protocol attacks through cryptographic isolation.
All BLAKE3 hash operations use domain separation strings. This ensures that hashes computed for one purpose cannot be reinterpreted as valid hashes for a different purpose. Each domain string follows the format NONOS:CATEGORY:PURPOSE:version, providing clear namespacing and version control.
The domain separation approach prevents an attacker from taking a hash computed in one context and presenting it as valid in another. Even if two different inputs happen to produce the same raw hash, the domain-separated versions will differ. This is essential when the same underlying data might appear in multiple protocol contexts.
BLAKE3's keyed derivation mode incorporates the domain string into the hash function's initial state. This provides stronger separation than simply prepending the domain to the input, as it modifies the compression function's behavior rather than just the input data.
Trusted Setup
Distributing trust across multiple independent parties.
Groth16 proofs require a structured reference string generated during a setup phase. This reference string contains encodings of secret field elements tau, alpha, and beta. If any party recovers these secrets, they can forge proofs for arbitrary statements. The multi-party ceremony ensures that as long as one participant honestly destroys their randomness, the combined secret remains unrecoverable.
The security guarantee is strong: recovery requires obtaining the secret randomness from every single participant. With n participants, an attacker must compromise all n to forge proofs. A single honest participant who genuinely destroys their contribution makes forgery computationally infeasible.
Ceremony Structure
Each participant generates fresh randomness, applies it to transform the existing parameters, and destroys their contribution. The final parameters incorporate all contributions multiplicatively. The combined secret equals the product of all individual secrets. Recovering this product requires knowing every factor.
Powers of Tau Transformation
The ceremony applies each participant's randomness to the structured reference string elements. The transformation computes powers of the participant's tau value and multiplies them into the corresponding elements of the proving key. Alpha and beta values modify the verification key components through scalar multiplication.
Each transformation preserves the algebraic relationships required for proof verification while incorporating fresh randomness. The circuit-specific setup takes the universal powers-of-tau output and specializes it for the attestation circuit's constraint system.
5+Participants
1Honest Required
unlimitedMaximum
YesDestruction Attestation
Contribution Records
Each participant produces a signed record documenting their contribution. The record includes hashes of the parameters before and after their transformation, a commitment to their randomness source, and an optional destruction attestation describing how they eliminated their secret values. These records form an auditable chain from initialization to final parameters.
The destruction attestation documents the method used to destroy randomness. Common methods include physical destruction of the machine used for computation, cryptographic erasure of storage, and witnessed destruction ceremonies with video documentation. The attestation provides evidence for security audits without requiring trust in any single participant.
Distributing signing authority across multiple parties.
FROST (Flexible Round-Optimized Schnorr Threshold) enables t-of-n signing where any t parties can collaborate to produce a valid signature, but fewer than t parties learn nothing about the key. The protocol operates over the Ristretto255 group and produces signatures compatible with Ed25519 verification.
Threshold signing addresses operational concerns around key management. A single signing key represents a single point of failure. If compromised, all future kernels can be maliciously signed. If lost, no more kernels can be signed. Threshold distribution eliminates both failure modes. Compromise requires breaching t parties. Recovery requires only t surviving parties.
Key Generation
Distributed key generation produces shares for each signer and a combined public key. The public key corresponds to a secret that no single party possesses. Each party's share allows them to participate in signing without ever reconstructing the complete secret.
The protocol uses Shamir secret sharing with threshold t. A random polynomial of degree t-1 encodes the group secret as its constant term. Each party receives an evaluation of this polynomial at a unique point. Any t evaluations suffice to recover the polynomial via Lagrange interpolation, but t-1 evaluations reveal nothing about the constant term.
The public key derives from the constant term through scalar multiplication with the group generator. This public key is identical to what a single-party key generation would produce. Verifiers cannot distinguish threshold keys from single-party keys.
Signature Generation
Signing proceeds in two rounds. In the first round, each participating signer generates a commitment and broadcasts it to the group. In the second round, each signer computes their partial signature using the aggregated commitments, their secret share, and the message. The coordinator combines partial signatures into the final signature.
The resulting signature is indistinguishable from a single-party Ed25519 signature. Verifiers cannot determine that threshold signing was used or how many parties participated. This provides operational flexibility without revealing the signing infrastructure to potential attackers.
For the attestation system, threshold signing protects the kernel signing key. The key is generated and distributed during initial setup. Signing a new kernel release requires participation from t parties. This prevents any single party from unilaterally signing malicious kernels while ensuring the signing capability survives individual party compromise or unavailability.
Generated Artifacts
Production cryptographic material from the current build.
The following artifacts were generated on March 29, 2026 from seed nonos-attestation-v1 at commit d69afa2fc4d625cee3256fe02662f4c37c86d7ae. These values can be independently verified by repeating the deterministic key generation process with the same inputs. The generation process is reproducible given the same seed, circuit definition, and toolchain version.
1,681,008Proving Key Bytes
872Verifying Key Bytes
10Public Inputs
192Proof Bytes
Verifying Key
The verifying key is embedded in the bootloader binary and used for runtime proof verification. Its integrity is critical to system security. Compromise of the verifying key would allow acceptance of invalid proofs. The key is compiled into the bootloader as a constant, preventing runtime modification.
Multiple hash algorithms provide defense in depth. The BLAKE3 fingerprint uses domain-separated keyed derivation for collision resistance. The SHA-256 hash enables cross-verification with systems using different hash functions. Both values are computed over the canonical 872-byte serialization.
Complete provenance information for the generated keys. This metadata enables reproducibility verification. Given the same tool version, compiler, and seed, key generation produces identical outputs. The commit hash identifies the exact source code version used.
The verifying key fingerprint uses BLAKE3 in keyed derivation mode with domain separation. This fingerprint identifies the key material independently of serialization format. Bootloaders embed the fingerprint as a compile-time constant and verify it matches the loaded verifying key at runtime. This prevents attacks where a modified verifying key might be substituted.
The domain string NONOS:VK:FINGERPRINT:v1 ensures the fingerprint cannot collide with other BLAKE3 hashes in the system. Version tagging allows fingerprint format evolution without breaking existing deployments.
examples/compute_fingerprint.rs
use std::fs;
fn main() {
let vk_bytes = fs::read("new_keys/attestation_verifying_key.bin").unwrap();
let mut h = blake3::Hasher::new_derive_key("NONOS:VK:FINGERPRINT:v1");
h.update(&vk_bytes);
let fp = h.finalize();
print!("pub const VK_FINGERPRINT_BOOT_AUTHORITY: [u8; 32] = [\n ");
for (i, b) in fp.as_bytes().iter().enumerate() {
print!("0x{:02x}, ", b);
if (i + 1) % 16 == 0 && i < 31 {
print!("\n ");
}
}
println!("];\n");
}
Running this utility produces a Rust constant suitable for direct inclusion in bootloader source code. The output format matches the bootloader's expected constant definition. During compilation, this fingerprint becomes a fixed reference point. At runtime, the bootloader hashes the loaded verifying key and compares against this constant before using the key for proof verification.