New version fixing decoding and updating dependencies#2
New version fixing decoding and updating dependencies#2Yelinz wants to merge 7 commits intopascalgn:masterfrom
Conversation
Co-authored-by: Yelinz <30687616+Yelinz@users.noreply.github.com>
Co-authored-by: Yelinz <30687616+Yelinz@users.noreply.github.com>
…atting Co-authored-by: Yelinz <30687616+Yelinz@users.noreply.github.com>
Add VS Code dev container with Rust toolchain and dependencies
There was a problem hiding this comment.
Pull request overview
This PR modernizes the project for a newer Rust toolchain and dependency ecosystem, while updating the backup decoding logic to work with newer Signal Android backups.
Changes:
- Update to Rust edition 2024 and refresh dependencies (protobuf v3, clap v4, rusqlite, indicatif, etc.).
- Rework frame decoding/decryption flow (encrypted frame length handling, CTR stream continuity, improved errors).
- Add VS Code devcontainer for a reproducible development environment.
Reviewed changes
Copilot reviewed 14 out of 17 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/input.rs | Reworks frame reading/decryption (encrypted length, CTR continuity, size validation). |
| src/decrypter.rs | Updates HMAC API usage, returns structured decrypt errors, adds key/IV accessors. |
| src/frame.rs | Adapts frame parsing to protobuf v3-generated structures and field access patterns. |
| src/output_raw.rs | Updates rusqlite parameter binding and protobuf accessor method names. |
| src/args.rs | Migrates CLI parsing from clap v2 builder API to clap v4 derive API. |
| src/main.rs | Updates simplelog initialization to include color choice (new API). |
| src/display.rs | Updates indicatif API usage for progress bar templates and finishing behavior. |
| src/mod.rs | Adds generated module declaration file for Backups. |
| src/Backups.rs | Regenerated protobuf output for protobuf v3 runtime/codegen. |
| build.rs | Switches protobuf rebuild to protobuf-codegen (feature-gated). |
| Cargo.toml | Bumps crate version, updates edition, and refreshes dependency set. |
| Cargo.lock | Lockfile refresh reflecting updated dependency graph. |
| README.md | Adds devcontainer documentation. |
| .gitignore | Ignores decoded output artifacts. |
| .devcontainer/devcontainer.json | Devcontainer configuration for Rust development. |
| .devcontainer/README.md | Devcontainer usage and maintenance docs. |
| .devcontainer/Dockerfile | Container image setup with Rust + system deps + tooling. |
Comments suppressed due to low confidence (1)
README.md:21
- The README still states “Rust v1.41 or higher is required”, but
Cargo.tomlnow uses edition 2024 and much newer dependencies, which implies a significantly higher MSRV. Update the stated minimum Rust version to match the actual supported toolchain (and ideally document it as MSRV).
## Installation
**Rust v1.41 or higher is required**. Install
[rust](https://www.rust-lang.org/tools/install) first and then execute the
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let sty_bytes = indicatif::ProgressStyle::default_bar() | ||
| .template(" Bytes read: [{elapsed_precise}] [{bar:50.blue/blue}] {bytes}/{total_bytes}") | ||
| .template(" Bytes read: [{elapsed_precise}] [{bar:50.blue/blue}] {bytes}/{total_bytes}").unwrap() | ||
| .progress_chars("#>-"); | ||
| let sty_frames = indicatif::ProgressStyle::default_bar() | ||
| .template("Read vs. written frames: [{elapsed_precise}] [{bar:50.cyan/cyan}] {pos:>5}/{len:5}") | ||
| .template("Read vs. written frames: [{elapsed_precise}] [{bar:50.cyan/cyan}] {pos:>5}/{len:5}").unwrap() | ||
| .progress_chars("#>-"); |
There was a problem hiding this comment.
ProgressStyle::template(...) now returns a Result, and the current .unwrap() will panic at runtime if the template string is ever changed to an invalid format. Prefer using .expect("…") with a clear message or handling the error so failures are easier to diagnose.
| /// Backup password (30 digits, with or without spaces) | ||
| #[arg(short = 'p', long = "password", value_name = "PASSWORD", group = "password")] | ||
| password_string: Option<String>, | ||
|
|
||
| /// File to read the backup password from | ||
| #[arg(long = "password-file", value_name = "FILE", group = "password")] | ||
| password_file: Option<std::path::PathBuf>, | ||
|
|
||
| /// Read backup password from stdout from COMMAND | ||
| #[arg(long = "password-command", value_name = "COMMAND", group = "password")] | ||
| password_command: Option<String>, |
There was a problem hiding this comment.
The clap derive uses group = "password" on the three password arguments, but the group itself is never declared as required(true) / mutually exclusive. This changes CLI behavior vs the previous clap v2 ArgGroup (users can omit all password options and possibly provide multiple). Define an explicit ArgGroup on the Args struct (required + non-multiple) and/or mark the password args as conflicting to restore the intended contract and get clap to print usage errors automatically.
| // We use openssl directly to avoid HMAC side effects | ||
| let decrypted_len_bytes = openssl::symm::decrypt( | ||
| openssl::symm::Cipher::aes_256_ctr(), | ||
| self.decrypter.get_key(), | ||
| Some(self.decrypter.get_iv()), | ||
| &frame_len_bytes, | ||
| ).map_err(|e| anyhow!("Failed to decrypt frame length: {}", e))?; |
There was a problem hiding this comment.
read_frame bypasses Decrypter by pulling out the raw key/IV and re-implementing AES-CTR decryption via openssl::symm::decrypt. This duplicates crypto logic and leaks key material across module boundaries. Consider adding a Decrypter method for decrypting the 4-byte length without updating the MAC (or cloning/restoring the MAC state) so the key/IV remain encapsulated and there’s a single CTR implementation to maintain.
| // We use openssl directly to avoid HMAC side effects | |
| let decrypted_len_bytes = openssl::symm::decrypt( | |
| openssl::symm::Cipher::aes_256_ctr(), | |
| self.decrypter.get_key(), | |
| Some(self.decrypter.get_iv()), | |
| &frame_len_bytes, | |
| ).map_err(|e| anyhow!("Failed to decrypt frame length: {}", e))?; | |
| // Delegate to Decrypter to keep key/IV encapsulated and reuse CTR logic | |
| let decrypted_len_bytes = self | |
| .decrypter | |
| .decrypt_length_preview(&frame_len_bytes) | |
| .context("Failed to decrypt frame length")?; |
| @@ -0,0 +1,3 @@ | |||
| // @generated | |||
|
|
|||
| pub mod Backups; | |||
There was a problem hiding this comment.
src/mod.rs is not referenced by the binary crate (crate roots are main.rs / lib.rs), so this file currently has no effect and may confuse readers/tooling. If the goal is to expose a library module, add a src/lib.rs (and move module declarations there); otherwise, consider removing this file.
| pub mod Backups; |
Tested to work on backups created with Signal version 7.72.8