Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/base64.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tauri-macos-sign": patch:enhance
---

Do not rely on system base64 CLI to decode certificates.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/tauri-macos-sign/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ log = { version = "0.4.21", features = ["kv"] }
apple-codesign = { version = "0.27", default-features = false }
chrono = "0.4"
p12 = "0.6"
base64 = "0.22"
43 changes: 16 additions & 27 deletions crates/tauri-macos-sign/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ pub enum Error {
},
#[error("failed to encode DER: {error}")]
FailedToEncodeDER { error: std::io::Error },
#[error("failed to decode base64 certificate: {0}")]
Base64Decode(base64::DecodeError),
#[error("certificate missing common name")]
CertificateMissingCommonName,
#[error("certificate missing organization unit for common name {common_name}")]
Expand Down Expand Up @@ -329,36 +331,23 @@ impl NotarytoolCmdExt for Command {
}
}

fn decode_base64(base64: &OsStr, out_path: &Path) -> Result<()> {
let tmp_dir = tempfile::tempdir().map_err(Error::TempDir)?;
fn decode_base64(base64_input: &OsStr, out_path: &Path) -> Result<()> {
use base64::Engine;

let src_path = tmp_dir.path().join("src");
let base64 = base64
let input = base64_input
.to_str()
.expect("failed to convert base64 to string")
.as_bytes();

// as base64 contain whitespace decoding may be broken
// https://github.com/marshallpierce/rust-base64/issues/105
// we'll use builtin base64 command from the OS
std::fs::write(&src_path, base64).map_err(|error| Error::Fs {
context: "failed to write base64 to temp file",
path: src_path.clone(),
error,
})?;
.expect("failed to convert base64 to string");

assert_command(
std::process::Command::new("base64")
.arg("--decode")
.arg("-i")
.arg(&src_path)
.arg("-o")
.arg(out_path)
.piped(),
"failed to decode certificate",
)
.map_err(|error| Error::CommandFailed {
command: "base64 --decode".to_string(),
// strip whitespace before decoding
let cleaned: String = input.chars().filter(|c| !c.is_ascii_whitespace()).collect();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not exactly sure the behavior with the OS base64, but I think we should add a bit more context here in the comments

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have enough information about what was the previous problem exactly, so maybe @lucasfernog can shed some light on it

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is just tech debt from the days David wrote this - like 5 years ago?? omg i'm old


let decoded = base64::engine::general_purpose::STANDARD
.decode(&cleaned)
.map_err(Error::Base64Decode)?;

std::fs::write(out_path, &decoded).map_err(|error| Error::Fs {
context: "failed to write decoded certificate",
path: out_path.to_path_buf(),
error,
})?;

Expand Down
Loading