fix(upgrade): U-01 — enforce pre-hashed minisign verification
This commit is contained in:
+4
-2
@@ -64,14 +64,16 @@ impl Default for UpgradeOptions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Überprüft eine Minisign-Signatur für gegebene Binärdaten mit dem angegebenen Minisign Public Key (S-02).
|
/// Ü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<()> {
|
pub fn verify_minisign_signature(data: &[u8], sig_str: &str, pubkey_str: &str) -> Result<()> {
|
||||||
let pubkey = minisign_verify::PublicKey::from_base64(pubkey_str)
|
let pubkey = minisign_verify::PublicKey::from_base64(pubkey_str)
|
||||||
.map_err(|e| anyhow::anyhow!("Ungültiger öffentlicher Minisign-Schlüssel: {e}"))?;
|
.map_err(|e| anyhow::anyhow!("Ungültiger öffentlicher Minisign-Schlüssel: {e}"))?;
|
||||||
let signature = minisign_verify::Signature::decode(sig_str)
|
let signature = minisign_verify::Signature::decode(sig_str)
|
||||||
.map_err(|e| anyhow::anyhow!("Ungültiges Minisign-Signaturformat: {e}"))?;
|
.map_err(|e| anyhow::anyhow!("Ungültiges Minisign-Signaturformat: {e}"))?;
|
||||||
pubkey
|
pubkey
|
||||||
.verify(data, &signature, true)
|
.verify(data, &signature, false)
|
||||||
.map_err(|e| anyhow::anyhow!("Minisign-Signaturprüfung FEHLGESCHLAGEN: {e}. Das Release-Manifest ist nicht vertrauenswürdig!"))?;
|
.map_err(|e| anyhow::anyhow!("Minisign-Signaturprüfung FEHLGESCHLAGEN: {e}. Das Release-Manifest ist nicht vertrauenswürdig!"))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,3 +75,36 @@ fn test_upgrade_blocks_unofficial_url_without_insecure_flag() {
|
|||||||
"Fehler muss Sicherheitsverstoß anzeigen: {err_msg}"
|
"Fehler muss Sicherheitsverstoß anzeigen: {err_msg}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_u01_reject_legacy_unhashed_signature() {
|
||||||
|
let payload = b"Hello Sanctum Release 0.7.0 Security Testing\n";
|
||||||
|
let sig_text = "\
|
||||||
|
untrusted comment: signature from minisign secret key\n\
|
||||||
|
RUSsVphPgr8155LCucDq8RzDmWMzWElzhBmHrS5p+qJlOCGU4AQpn2F28MVPFrnoGPYEHx7/6TlKg2b45DlYuBQ0+ASeLIzMLwc=\n\
|
||||||
|
trusted comment: timestamp:1789750897\tfile:test_payload.txt\thashed\n\
|
||||||
|
0l7KsNJkDTo2uOKL8UAiaJOWuhwhGTVZ5fn0JFMdxXE9riYixQO9YnBpSVqz8iCDhWrz8hJBnmUrIWnaRaXVCA==\n";
|
||||||
|
|
||||||
|
// Gültige pre-hashed Signatur muss weiterhin erfolgreich geprüft werden
|
||||||
|
assert!(verify_minisign_signature(payload, sig_text, SANCTUM_RELEASE_PUBKEY).is_ok());
|
||||||
|
|
||||||
|
// Modifiziere die Signatur, um eine Legacy-Signatur (Ed statt ED) zu simulieren
|
||||||
|
// In Base64 entspricht 'ED' (0x45, 0x44) dem Präfix 'RU'
|
||||||
|
// 'Ed' (0x45, 0x64) entspricht in Base64 dem Präfix 'RW'
|
||||||
|
let lines: Vec<&str> = sig_text.lines().collect();
|
||||||
|
let mut sig_line = lines[1].to_string();
|
||||||
|
assert!(sig_line.starts_with("RU"));
|
||||||
|
sig_line.replace_range(0..2, "RW");
|
||||||
|
|
||||||
|
let legacy_sig_text = format!(
|
||||||
|
"{}\n{}\n{}\n{}\n",
|
||||||
|
lines[0], sig_line, lines[2], lines[3]
|
||||||
|
);
|
||||||
|
|
||||||
|
let res = verify_minisign_signature(payload, &legacy_sig_text, SANCTUM_RELEASE_PUBKEY);
|
||||||
|
assert!(
|
||||||
|
res.is_err(),
|
||||||
|
"U-01: Legacy-Signaturen (ohne Pre-Hashing) müssen strikt abgewiesen werden"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user