| Crates.io | lllv-core |
| lib.rs | lllv-core |
| version | 0.1.1 |
| created_at | 2026-01-09 15:08:58.398879+00 |
| updated_at | 2026-01-10 16:05:45.267766+00 |
| description | LLLV — Cryptographic capsules for verifiable retrieval. |
| homepage | https://logline.foundation |
| repository | https://github.com/LogLine-Foundation/lllv-core |
| max_upload_size | |
| id | 2032226 |
| size | 62,670 |
lllv-core define a Vector Capsule com cabeçalho binário assinado e manifesto canônico (Paper II), endereçada por BLAKE3 (CID) e selada com Ed25519. É a base do Retrieval Atom (Paper III).
MAGIC | VER | FLAGS | TS | CID | DIM | LEN | SIGblake3(payload) — endereçamento por conteúdoEd25519.sign(header_without_sig || payload)[dependencies]
lllv-core = "0.1.0"
# integrações recomendadas
logline-core = { version = "0.1.1", features = ["serde"] }
json_atomic = "0.1.1" # já incluso via feature "manifest"
ed25519-dalek = "2"
rand = "0.8"
use ed25519_dalek::SigningKey;
use rand::rngs::OsRng;
use lllv_core::{Capsule, CapsuleHeader, CapsuleFlags, encrypt_chacha20poly1305, decrypt_chacha20poly1305};
fn main() {
// Chave de assinatura (Ed25519)
let sk = SigningKey::generate(&mut OsRng);
// Payload vetorial (pode ser embedding quantizado)
let dim: u16 = 3;
let payload = vec![1u8, 2, 3, 4, 5, 6]; // exemplo
// (Opcional) criptografia do payload com AAD=(vector_id||CID)
let vector_id = "doc:1";
let key = [7u8; 32];
let nonce = [9u8; 12];
let aad = [vector_id.as_bytes(), &[]].concat(); // simples; use CID real em prod.
// Cria a cápsula (sem criptografia)
let cap = Capsule::create(dim, &payload, CapsuleFlags::NONE, &sk).unwrap();
cap.verify_cid().unwrap(); // verifica integridade
cap.verify_with(&sk.verifying_key()).unwrap(); // verifica autenticidade
// Cria a cápsula (criptografada) — payload = nonce || ciphertext
let enc = encrypt_chacha20poly1305(&payload, &key, &nonce, &aad).unwrap();
let cap_enc = Capsule::create(dim, &enc, CapsuleFlags::ENCRYPTED, &sk).unwrap();
cap_enc.verify_with(&sk.verifying_key()).unwrap();
// Decriptar depois
let (nonce2, ct2) = enc.split_at(12);
let pt = decrypt_chacha20poly1305(ct2, nonce2.try_into().unwrap(), &key, &aad).unwrap();
assert_eq!(pt, payload);
}
pub struct CapsuleHeader { /* MAGIC, VER, FLAGS, TS, CID, DIM, LEN, SIG */ }
pub struct Capsule { pub header: CapsuleHeader, pub payload: Vec<u8> }
impl Capsule {
pub fn create(dim: u16, payload: &[u8], flags: CapsuleFlags, sk: &ed25519_dalek::SigningKey)
-> Result<Self, LllvError>;
pub fn to_bytes(&self) -> Vec<u8>;
pub fn from_bytes(raw: &[u8]) -> Result<Self, LllvError>;
pub fn verify_cid(&self) -> Result<(), LllvError>; // integridade (CID)
pub fn verify_with(&self, pk: &ed25519_dalek::VerifyingKey) -> Result<(), LllvError>; // integridade + autenticidade
#[deprecated] pub fn verify(&self) -> Result<(), LllvError>; // use verify_cid() ou verify_with()
}
pub fn encrypt_chacha20poly1305(plain: &[u8], key: &[u8;32], nonce: &[u8;12], aad: &[u8])
-> Result<Vec<u8>, LllvError>;
pub fn decrypt_chacha20poly1305(cipher: &[u8], nonce: &[u8;12], key: &[u8;32], aad: &[u8])
-> Result<Vec<u8>, LllvError>;
Se a feature manifest estiver ativa, use json_atomic para canonizar, hashear e selar o manifesto (DV25-Seal).
use lllv_core::{CapsuleManifest, seal_manifest};
let mf = CapsuleManifest::minimal("doc:1", "text/plain", dim, "q8");
let fact = seal_manifest(&mf, &sk)?; // SignedFact (json_atomic)
capsule.verify_cid()? — verifica se o CID corresponde ao payloadcapsule.verify_with(&verifying_key)? — verifica integridade + assinatura
verify()está deprecated — useverify_with(pk)para checagem completa ouverify_cid()apenas para integridade.
header_without_sig || payload.vector_id || CID) quando cifrar.cargo-audit e cargo-deny em PRs/merge.MIT • MSRV 1.75+ • pronto para evoluir para alloc/no_std no v0.1.1.