open-envault 0.3.0

Local-first SOPS-compatible secrets for Git and Rust
Documentation
use serde::Serialize;
use sha2::{Digest, Sha256};

pub fn redact(value: &str) -> String {
    if value.is_empty() {
        "<empty>".into()
    } else {
        "<redacted>".into()
    }
}

#[derive(Debug, Serialize)]
pub struct Finding {
    pub variable: String,
    pub kind: String,
    pub message: String,
}

pub fn json<T: Serialize>(value: &T) -> anyhow::Result<String> {
    Ok(serde_json::to_string_pretty(value)?)
}

pub fn fingerprint(pepper: &str, value: &str) -> String {
    let mut key = [0u8; 64];
    let pepper = pepper.as_bytes();
    if pepper.len() > key.len() {
        key[..32].copy_from_slice(&Sha256::digest(pepper));
    } else {
        key[..pepper.len()].copy_from_slice(pepper);
    }
    let mut inner = Sha256::new();
    for byte in key {
        inner.update([byte ^ 0x36]);
    }
    inner.update(value.as_bytes());
    let inner = inner.finalize();
    let mut outer = Sha256::new();
    for byte in key {
        outer.update([byte ^ 0x5c]);
    }
    outer.update(inner);
    hex::encode(&outer.finalize()[..12])
}

#[derive(Debug, Serialize)]
pub struct CheckEnvelope<T: Serialize> {
    pub ok: bool,
    pub exit: u8,
    pub findings: T,
}

#[derive(Debug, Serialize)]
pub struct DiffEnvelope<T: Serialize> {
    pub ok: bool,
    pub exit: u8,
    pub variables: T,
}