]> git.proxmox.com Git - proxmox-backup.git/commitdiff
proxmox_backup_client key: allow to generate paperkey for master key
authorDietmar Maurer <dietmar@proxmox.com>
Tue, 29 Sep 2020 06:19:33 +0000 (08:19 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Tue, 29 Sep 2020 06:29:42 +0000 (08:29 +0200)
debian/control
src/bin/proxmox_backup_client/key.rs

index 20f3f9c95ce9aca282c33f585e11ac8f376eee1a..1785efd4251ab5a643d22444561fdd0b83f0b2f2 100644 (file)
@@ -118,7 +118,7 @@ Description: Proxmox Backup Server daemon with tools and GUI
 
 Package: proxmox-backup-client
 Architecture: any
-Depends: ${misc:Depends}, ${shlibs:Depends}
+Depends: qrencode ${misc:Depends}, ${shlibs:Depends}
 Description: Proxmox Backup Client tools
  This package contains the Proxmox Backup client, which provides a
  simple command line tool to create and restore backups.
index e87f0483c7b31775418258e55732b898a1d0ce7f..5c4db34ec242e367ce0458254ac194233e7068e8 100644 (file)
@@ -293,31 +293,63 @@ fn paper_key(path: Option<String>, subject: Option<String>) -> Result<(), Error>
     };
 
     let data = file_get_contents(&path)?;
-    let key_config: KeyConfig = serde_json::from_slice(&data)?;
-    let key_text = serde_json::to_string_pretty(&key_config)?;
+    let data = std::str::from_utf8(&data)?;
 
     if let Some(subject) = subject {
         println!("Subject: {}\n", subject);
     }
 
-    println!("-----BEGIN PROXMOX BACKUP KEY-----");
-    println!("{}", key_text);
-    println!("-----END PROXMOX BACKUP KEY-----");
+    if data.starts_with("-----BEGIN ENCRYPTED PRIVATE KEY-----\n") {
+        //let rsa = openssl::rsa::Rsa::private_key_from_pem(data.as_bytes())?;
 
-    let mut child = Command::new("qrencode")
-        .args(&["-t", "utf8i", "-lm"])
-        .stdin(Stdio::piped())
-        .stdout(Stdio::piped())
-        .spawn()?;
+        let lines: Vec<String> = data.lines()
+            .map(|s| s.trim_end())
+            .filter(|s| !s.is_empty())
+            .map(String::from)
+            .collect();
 
-    {
-        let stdin = child.stdin.as_mut().expect("Failed to open stdin");
-        stdin.write_all(key_text.as_bytes()).expect("Failed to write to stdin");
+        if !lines[lines.len()-1].starts_with("-----END ENCRYPTED PRIVATE KEY-----") {
+            bail!("unexpected key format");
+        }
+
+        if lines.len() < 20 {
+            bail!("unexpected key format");
+        }
+
+        const BLOCK_SIZE: usize = 5;
+        let blocks = (lines.len() + BLOCK_SIZE -1)/BLOCK_SIZE;
+
+        for i in 0..blocks {
+            let start = i*BLOCK_SIZE;
+            let mut end = start + BLOCK_SIZE;
+            if end > lines.len() {
+                end = lines.len();
+            }
+            let data = &lines[start..end];
+
+            for l in start..end {
+                println!("LINE {:-2}: {}", l, lines[l]);
+            }
+            let data = data.join("\n");
+            let qr_code = generate_qr_code("utf8i", data.as_bytes())?;
+            println!("{}", qr_code);
+            println!("{}", char::from(12u8)); // page break
+
+        }
+        return Ok(());
     }
 
-    let output = child.wait_with_output().expect("Failed to read stdout");
+    let key_config: KeyConfig = serde_json::from_str(&data)?;
+    let key_text = serde_json::to_string_pretty(&key_config)?;
 
-    println!("{}", String::from_utf8_lossy(&output.stdout));
+
+    println!("-----BEGIN PROXMOX BACKUP KEY-----");
+    println!("{}", key_text);
+    println!("-----END PROXMOX BACKUP KEY-----");
+
+    let qr_code = generate_qr_code("utf8i", key_text.as_bytes())?;
+
+    println!("{}", qr_code);
 
     Ok(())
 }
@@ -348,3 +380,27 @@ pub fn cli() -> CliCommandMap {
         .insert("change-passphrase", key_change_passphrase_cmd_def)
         .insert("paper-key", paper_key_cmd_def)
 }
+
+fn generate_qr_code(output_type: &str, data: &[u8]) -> Result<String, Error> {
+
+    let mut child = Command::new("qrencode")
+        .args(&["-t", output_type, "-lm"])
+        .stdin(Stdio::piped())
+        .stdout(Stdio::piped())
+        .spawn()?;
+
+    {
+        let stdin = child.stdin.as_mut()
+            .ok_or_else(|| format_err!("Failed to open stdin"))?;
+        stdin.write_all(data)
+            .map_err(|_| format_err!("Failed to write to stdin"))?;
+    }
+
+    let output = child.wait_with_output()
+        .map_err(|_| format_err!("Failed to read stdout"))?;
+
+    let output = String::from_utf8(output.stdout)
+        .map_err(|_| format_err!("Failed to read stdout (got non-utf8 data)"))?;
+
+    Ok(output)
+}