Skip to main content

auths_verifier/
commit_error.rs

1//! Error types for commit signature verification.
2
3use thiserror::Error;
4
5use crate::error::AuthsErrorInfo;
6
7/// Errors from commit signature parsing and verification.
8///
9/// Usage:
10/// ```ignore
11/// match result {
12///     Err(CommitVerificationError::UnsignedCommit) => { /* no signature */ }
13///     Err(CommitVerificationError::SignatureInvalid) => { /* bad sig */ }
14///     Ok(verified) => { /* success */ }
15/// }
16/// ```
17#[derive(Error, Debug)]
18pub enum CommitVerificationError {
19    /// The commit has no signature at all.
20    #[error("commit is unsigned")]
21    UnsignedCommit,
22
23    /// The commit uses a GPG signature, which is not supported.
24    #[error("GPG signatures not supported, use SSH signing")]
25    GpgNotSupported,
26
27    /// The SSHSIG envelope could not be parsed.
28    #[error("SSHSIG parse failed: {0}")]
29    SshSigParseFailed(String),
30
31    /// The SSH key type is not Ed25519.
32    #[error("unsupported SSH key type: {found}")]
33    UnsupportedKeyType {
34        /// The key type string found in the envelope.
35        found: String,
36    },
37
38    /// The SSHSIG namespace does not match the expected value.
39    #[error("namespace mismatch: expected \"{expected}\", found \"{found}\"")]
40    NamespaceMismatch {
41        /// The expected namespace.
42        expected: String,
43        /// The namespace found in the signature.
44        found: String,
45    },
46
47    /// The hash algorithm in the SSHSIG envelope is not supported.
48    #[error("unsupported hash algorithm: {0}")]
49    HashAlgorithmUnsupported(String),
50
51    /// The Ed25519 signature did not verify against the signed data.
52    #[error("signature verification failed")]
53    SignatureInvalid,
54
55    /// The signer's public key is not in the allowed keys list.
56    #[error("signer key not in allowed keys")]
57    UnknownSigner,
58
59    /// The raw commit object could not be parsed.
60    #[error("commit parse failed: {0}")]
61    CommitParseFailed(String),
62}
63
64impl AuthsErrorInfo for CommitVerificationError {
65    fn error_code(&self) -> &'static str {
66        match self {
67            Self::UnsignedCommit => "AUTHS-E2101",
68            Self::GpgNotSupported => "AUTHS-E2102",
69            Self::SshSigParseFailed(_) => "AUTHS-E2103",
70            Self::UnsupportedKeyType { .. } => "AUTHS-E2104",
71            Self::NamespaceMismatch { .. } => "AUTHS-E2105",
72            Self::HashAlgorithmUnsupported(_) => "AUTHS-E2106",
73            Self::SignatureInvalid => "AUTHS-E2107",
74            Self::UnknownSigner => "AUTHS-E2108",
75            Self::CommitParseFailed(_) => "AUTHS-E2109",
76        }
77    }
78
79    fn suggestion(&self) -> Option<&'static str> {
80        match self {
81            Self::UnsignedCommit => Some("Sign commits with: git commit -S"),
82            Self::GpgNotSupported => Some("Configure SSH signing: git config gpg.format ssh"),
83            Self::UnsupportedKeyType { .. } => Some("Use an Ed25519 SSH key for signing"),
84            Self::UnknownSigner => Some("Add the signer's key to the allowed signers list"),
85            Self::SshSigParseFailed(_) => Some(
86                "The SSH signature could not be parsed; verify the commit was signed correctly",
87            ),
88            Self::NamespaceMismatch { .. } => Some(
89                "The signature namespace doesn't match; ensure git config gpg.ssh.defaultKeyCommand is set correctly",
90            ),
91            Self::HashAlgorithmUnsupported(_) => {
92                Some("Use SHA-256 or SHA-512 hash algorithm for signing")
93            }
94            Self::SignatureInvalid => Some(
95                "The commit signature does not match the signed data; the commit may have been modified after signing",
96            ),
97            Self::CommitParseFailed(_) => Some(
98                "The Git commit object is malformed; check repository integrity with `git fsck`",
99            ),
100        }
101    }
102}