fix(upgrade): U-02 — validate version in minisign trusted comment against release tag
This commit is contained in:
+48
-3
@@ -67,7 +67,8 @@ impl Default for UpgradeOptions {
|
||||
/// Überprüft eine Minisign-Signatur für gegebene Binärdaten mit dem angegebenen Minisign Public Key (U-01).
|
||||
///
|
||||
/// Erzwingt strikt Pre-Hashing (`allow_legacy = false`), um Malleability- und Längenangriffe auszuschließen.
|
||||
pub fn verify_minisign_signature(data: &[u8], sig_str: &str, pubkey_str: &str) -> Result<()> {
|
||||
/// Gibt bei erfolgreicher Verifikation den kryptografisch authentifizierten `trusted comment` zurück.
|
||||
pub fn verify_minisign_signature(data: &[u8], sig_str: &str, pubkey_str: &str) -> Result<String> {
|
||||
let pubkey = minisign_verify::PublicKey::from_base64(pubkey_str)
|
||||
.map_err(|e| anyhow::anyhow!("Ungültiger öffentlicher Minisign-Schlüssel: {e}"))?;
|
||||
let signature = minisign_verify::Signature::decode(sig_str)
|
||||
@@ -75,6 +76,49 @@ pub fn verify_minisign_signature(data: &[u8], sig_str: &str, pubkey_str: &str) -
|
||||
pubkey
|
||||
.verify(data, &signature, false)
|
||||
.map_err(|e| anyhow::anyhow!("Minisign-Signaturprüfung FEHLGESCHLAGEN: {e}. Das Release-Manifest ist nicht vertrauenswürdig!"))?;
|
||||
Ok(signature.trusted_comment().to_string())
|
||||
}
|
||||
|
||||
/// Extrahiert die Versionsnummer aus dem Trusted Comment einer Minisign-Signatur und
|
||||
/// validiert sie gegen das erwartete Release-Tag (U-02).
|
||||
pub fn validate_trusted_comment_version(
|
||||
trusted_comment: &str,
|
||||
expected_release: &str,
|
||||
) -> Result<()> {
|
||||
let clean_expected = expected_release
|
||||
.trim()
|
||||
.trim_start_matches(|c| c == 'v' || c == 'V');
|
||||
|
||||
if clean_expected.is_empty() {
|
||||
bail!("Erwartetes Release-Tag darf nicht leer sein.");
|
||||
}
|
||||
|
||||
// Durchsuche die Tokens des Trusted Comments (getrennt durch Tabs oder Leerzeichen)
|
||||
let found = trusted_comment.split_whitespace().any(|token| {
|
||||
let val = if let Some(stripped) = token.strip_prefix("version:") {
|
||||
stripped
|
||||
} else if let Some(stripped) = token.strip_prefix("release:") {
|
||||
stripped
|
||||
} else if let Some(stripped) = token.strip_prefix("tag:") {
|
||||
stripped
|
||||
} else {
|
||||
token
|
||||
};
|
||||
|
||||
let clean_val = val.trim_start_matches(|c| c == 'v' || c == 'V');
|
||||
clean_val == clean_expected
|
||||
});
|
||||
|
||||
if !found {
|
||||
bail!(
|
||||
"Signatur-Validierungsfehler (U-02): Der kryptografisch gesicherte Trusted Comment \
|
||||
'{}' stimmt nicht mit der erwarteten Release-Version '{}' überein! \
|
||||
Möglicher Replay-Angriff mit einer älteren signierten Prüfsummendatei.",
|
||||
trusted_comment.trim(),
|
||||
expected_release
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -501,10 +545,11 @@ pub fn run_upgrade(options: &UpgradeOptions) -> Result<()> {
|
||||
" {} Verifiziere Minisign-Signatur gegen eingebetteten Herstellerschlüssel ...",
|
||||
ui::dim("[-]")
|
||||
);
|
||||
verify_minisign_signature(sums_content.as_bytes(), &sig_content, SANCTUM_RELEASE_PUBKEY)
|
||||
let trusted_comment = verify_minisign_signature(sums_content.as_bytes(), &sig_content, SANCTUM_RELEASE_PUBKEY)
|
||||
.context("Minisign-Signaturprüfung für Prüfsummendatei FEHLGESCHLAGEN! Release ist nicht vertrauenswürdig.")?;
|
||||
validate_trusted_comment_version(&trusted_comment, remote_tag)?;
|
||||
println!(
|
||||
" • Signatur: {} (Minisign Ed25519)",
|
||||
" • Signatur: {} (Minisign Ed25519, Version validiert)",
|
||||
ui::green("Gültig")
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user