Skip to main content

mkit_git_bridge/
verify.rs

1//! Shallow signature verification (SPEC-GIT-BRIDGE §10).
2//!
3//! Shallow mode rebuilds the mkit object from a single bridge-emitted
4//! git commit/tag (self-contained: the carried headers include the
5//! mkit tree/parent/target hashes) and checks its Ed25519 signature
6//! under the proper domain via mkit-core's strict verifier. It proves
7//! the carried fields are exactly what the original signer signed; it
8//! does NOT prove the surrounding git graph corresponds to those
9//! BLAKE3 hashes — that is deep verification (full [`crate::reconstruct`]
10//! over the closure, driven by the caller).
11
12use crate::error::BridgeError;
13use crate::gitobj::{GitObject, GitType};
14use crate::reconstruct;
15use mkit_core::object::Object;
16
17/// Outcome of a shallow check.
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum ShallowVerdict {
20    /// Signature verifies under the object's signing domain.
21    Verified,
22    /// All-zero signature: the unsigned convention (SPEC-SIGNING §4a).
23    /// Report as "unsigned", never as tampered.
24    Unsigned,
25    /// A non-zero signature that does not verify.
26    Failed,
27}
28
29/// Shallow-verify a bridge-emitted git commit or tag.
30pub fn shallow_verify(obj: &GitObject) -> Result<ShallowVerdict, BridgeError> {
31    let rec = match obj.gtype {
32        GitType::Commit => reconstruct::reconstruct_commit(&obj.body)?,
33        GitType::Tag => reconstruct::reconstruct_tag(&obj.body)?,
34        GitType::Blob | GitType::Tree => {
35            return Err(BridgeError::NotBridgeObject(
36                "shallow verification applies to commits and tags only".into(),
37            ));
38        }
39    };
40    Ok(match rec.object {
41        Object::Commit(ref c) => {
42            if c.signature == [0u8; 64] {
43                ShallowVerdict::Unsigned
44            } else if mkit_core::sign::verify_commit(c).is_ok() {
45                ShallowVerdict::Verified
46            } else {
47                ShallowVerdict::Failed
48            }
49        }
50        Object::Tag(ref t) => {
51            if t.signature == [0u8; 64] {
52                ShallowVerdict::Unsigned
53            } else if mkit_core::sign::verify_tag(t).is_ok() {
54                ShallowVerdict::Verified
55            } else {
56                ShallowVerdict::Failed
57            }
58        }
59        _ => unreachable!("reconstruct_commit/tag return Commit/Tag"),
60    })
61}