diff --git a/Cargo.lock b/Cargo.lock
index cd5167ae6e511b08385ad35ced2cdc4fc70e47ca..028b93702fe5ac45effcea620fdafde8de5b7e61 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1746,6 +1746,7 @@ dependencies = [
  "hex",
  "log",
  "md-5",
+ "nethsm-backup",
  "nethsm-sdk-rs",
  "nethsm-tests",
  "p224",
diff --git a/Cargo.toml b/Cargo.toml
index 5b47045f679288ccc79bb7a6939f58d17038e4a2..1551e230a8ce9cb07d22459656d249ba608a6d8e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,6 +14,7 @@ chrono = "0.4.38"
 clap = { version = "4.5.19", features = ["derive", "env"] }
 ed25519-dalek = "2.1.1"
 nethsm = { path = "nethsm", version = "0.7.1" }
+nethsm-backup = { path = "nethsm-backup" }
 nethsm-config = { path = "nethsm-config", version = "0.2.1" }
 rand = "0.8.5"
 rsa = "0.9.6"
diff --git a/nethsm/Cargo.toml b/nethsm/Cargo.toml
index b0b88a2f259e556d2985b9505042dc0854b87c66..9c08fb345754073343d53fe04487b61d60d39eea 100644
--- a/nethsm/Cargo.toml
+++ b/nethsm/Cargo.toml
@@ -20,6 +20,7 @@ email_address = "0.2.9"
 hex = { version = "0.4.3", features = ["serde"] }
 log = "0.4.22"
 md-5 = "0.10.6"
+nethsm-backup.workspace = true
 nethsm-sdk-rs = "1.1.1"
 p224 = { version = "0.13.2", features = ["pem", "pkcs8"] }
 p256 = { version = "0.13.2", features = ["pem", "pkcs8"] }
diff --git a/nethsm/src/lib.rs b/nethsm/src/lib.rs
index 6bb7e4502ac3de45d5d79d77ed5821e9881bbab0..7869e3064a4066f7604c0a26472430fe49cee289 100644
--- a/nethsm/src/lib.rs
+++ b/nethsm/src/lib.rs
@@ -88,6 +88,7 @@
 use std::cell::RefCell;
 use std::collections::HashMap;
 use std::fmt::Display;
+use std::io::Read;
 use std::net::Ipv4Addr;
 use std::str::FromStr;
 use std::sync::Arc;
@@ -371,6 +372,71 @@ impl FromStr for Url {
     }
 }
 
+/// Validates a [backup].
+///
+/// Parses a previously created backup file. If `passphrase` is
+/// [`Some`], additionally decrypts the backup and verifies the
+/// encrypted backup version number.
+///
+/// # Errors
+///
+/// Returns an [`nethsm_backup::Error`] if validating a [backup] fails:
+/// * the magic number is missing in the file
+/// * the version number is unknown
+/// * the provided passphrase is incorrect
+///
+/// # Examples
+///
+/// ```no_run
+/// use nethsm::{validate_backup, ConnectionSecurity, Credentials, NetHsm, Passphrase};
+///
+/// # fn main() -> testresult::TestResult {
+/// // create a connection with a user in the Backup role
+/// let nethsm = NetHsm::new(
+///     "https://example.org/api/v1".try_into()?,
+///     ConnectionSecurity::Unsafe,
+///     Some(Credentials::new(
+///         "backup1".parse()?,
+///         Some(Passphrase::new("passphrase".to_string())),
+///     )),
+///     None,
+///     None,
+/// )?;
+///
+/// // create a backup and write it to file
+/// std::fs::write("nethsm.bkp", nethsm.backup()?)?;
+///
+/// // check for consistency only
+/// validate_backup(&mut std::fs::File::open("nethsm.bkp")?, None)?;
+///
+/// // check for correct passphrase by decrypting and validating the encrypted backup version
+/// validate_backup(
+///     &mut std::fs::File::open("nethsm.bkp")?,
+///     Passphrase::new("a sample password".into()),
+/// )?;
+/// # Ok(())
+/// # }
+/// ```
+/// [backup]: https://docs.nitrokey.com/nethsm/administration#backup
+pub fn validate_backup(
+    reader: &mut impl Read,
+    passphrase: impl Into<Option<Passphrase>>,
+) -> Result<(), nethsm_backup::Error> {
+    let passphrase = passphrase.into();
+    let backup = nethsm_backup::Backup::parse(reader)?;
+    if let Some(passphrase) = passphrase {
+        let decryptor = backup.decrypt(passphrase.expose_borrowed().as_bytes())?;
+        let version = decryptor.version()?;
+        if version.len() != 1 || version[0] != 0 {
+            return Err(nethsm_backup::Error::BadVersion {
+                highest_supported_version: 0,
+                backup_version: version,
+            });
+        }
+    }
+    Ok(())
+}
+
 /// A network connection to a NetHSM.
 ///
 /// Defines a network configuration for the connection and a list of user [`Credentials`] that can