This repository has been archived on 2026-08-20. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
el-retired/engrams/el-seal/src/artifact.rs
T
Will Anderson a42429012e rename crates/ to engrams/; add el-compiler el package with bootstrap artifact
- crates/ → engrams/ (Rust engrams live here)
- el-compiler/ added: el self-hosting compiler as an el package
  - src/{compiler,lexer,parser,codegen}.el
  - bootstrap/el-compiler.elc (114KB, Rust-compiled seed)
- el.toml Cargo.toml workspace paths updated
- neuron-rs cross-repo path deps fixed (were pointing to products/ instead of foundation/)
2026-04-29 03:27:32 -05:00

140 lines
5.3 KiB
Rust

//! Sealed artifact format definition.
//!
//! Binary layout (big-endian):
//!
//! ```text
//! Offset Size Field
//! ────── ───── ─────────────────────────────────────────────────────────
//! 0 8 magic: b"ENGRAM01"
//! 8 2 version: u16 (currently 1)
//! 10 * JSON-encoded SealedArtifact body (algorithm_id, nonce, …)
//! ```
//!
//! The body is JSON so the format is self-describing and forward-compatible.
//! Future versions can add new fields without breaking older parsers.
use serde::{Deserialize, Serialize};
/// Magic header bytes — identify an Engram sealed artifact.
pub const MAGIC: [u8; 8] = *b"ENGRAM01";
/// Current artifact format version.
pub const FORMAT_VERSION: u16 = 1;
// ── Configuration ─────────────────────────────────────────────────────────────
/// Which algorithm was used to seal the artifact.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum SealAlgorithm {
/// AES-256-GCM — current default, quantum-resistant at 256-bit.
Aes256Gcm,
/// CRYSTALS-Kyber 768 — when ml-kem crate stabilizes.
MlKem768,
/// CRYSTALS-Kyber 1024 — when ml-kem crate stabilizes.
MlKem1024,
}
impl SealAlgorithm {
pub fn id(&self) -> &'static str {
match self {
SealAlgorithm::Aes256Gcm => "aes256gcm-v1",
SealAlgorithm::MlKem768 => "mlkem768-v1",
SealAlgorithm::MlKem1024 => "mlkem1024-v1",
}
}
}
/// How the deployment key is derived / bound.
#[derive(Debug, Clone)]
pub enum DeploymentBinding {
/// Read the seal key from an environment variable (e.g. `ENGRAM_SEAL_KEY`).
EnvironmentKey(String),
/// Bind to this machine's hostname + OS + CPU model (BLAKE3 hash of all three).
MachineFingerprint,
/// No binding — key is the zero vector. For testing only; offers no security.
None,
}
/// Configuration for the sealing operation.
#[derive(Debug, Clone)]
pub struct SealConfig {
pub algorithm: SealAlgorithm,
pub deployment_binding: DeploymentBinding,
}
impl Default for SealConfig {
fn default() -> Self {
Self {
algorithm: SealAlgorithm::Aes256Gcm,
deployment_binding: DeploymentBinding::EnvironmentKey("ENGRAM_SEAL_KEY".into()),
}
}
}
// ── Artifact ──────────────────────────────────────────────────────────────────
/// A quantum-sealed bytecode artifact.
///
/// This is the output of `el seal` / the `prod` compilation target.
/// It is serialized to disk as: `MAGIC || VERSION_u16_be || JSON(body)`.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SealedArtifact {
/// Algorithm identifier — matches [`SealAlgorithm::id()`].
pub algorithm_id: String,
/// BLAKE3-keyed MAC over `(algorithm_id || nonce || ciphertext)`.
/// Used to detect tampering before attempting decryption.
/// In the PQ upgrade path, this becomes an ML-DSA signature.
pub signature: Vec<u8>,
/// The binding-protected symmetric key.
///
/// In the current scheme: `symmetric_key XOR BLAKE3(binding_material)`.
/// Without the deployment key, the binding material cannot be derived,
/// so the symmetric key cannot be recovered.
///
/// In the ML-KEM upgrade: this becomes the KEM-encapsulated key ciphertext.
pub encapsulated_key: Vec<u8>,
/// 96-bit AES-GCM nonce.
pub nonce: Vec<u8>,
/// Encrypted bytecode (AES-256-GCM ciphertext including the 128-bit auth tag).
pub ciphertext: Vec<u8>,
/// BLAKE3 hash of the binding material. Allows the unsealer to verify
/// it is running in the correct deployment environment before decryption.
/// `None` if [`DeploymentBinding::None`] was used.
pub deployment_fingerprint: Option<Vec<u8>>,
}
impl SealedArtifact {
/// Serialize to the on-disk wire format: `MAGIC || version_be16 || JSON`.
pub fn to_bytes(&self) -> Result<Vec<u8>, serde_json::Error> {
let mut out = Vec::with_capacity(256);
out.extend_from_slice(&MAGIC);
out.extend_from_slice(&FORMAT_VERSION.to_be_bytes());
let json = serde_json::to_vec(self)?;
out.extend_from_slice(&json);
Ok(out)
}
/// Deserialize from the on-disk wire format.
pub fn from_bytes(bytes: &[u8]) -> Result<Self, crate::SealError> {
if bytes.len() < 10 {
return Err(crate::SealError::Serialization("artifact too short".into()));
}
let magic: [u8; 8] = bytes[..8].try_into().unwrap();
if magic != MAGIC {
return Err(crate::SealError::InvalidMagic(magic));
}
// Version check (bytes 8..10) — currently we only support v1
let version = u16::from_be_bytes([bytes[8], bytes[9]]);
if version != FORMAT_VERSION {
return Err(crate::SealError::UnsupportedAlgorithm(format!("format v{version}")));
}
let body = &bytes[10..];
serde_json::from_slice(body).map_err(|e| crate::SealError::Serialization(e.to_string()))
}
}