Files
proton-sdk-rs/README.md
T
2026-06-25 09:42:34 +02:00

3.0 KiB

proton-sdk-rs

A pure-Rust reimplementation of the Proton Drive SDK. No dependency on the official NativeAOT core — it talks to the Proton Drive API and does the OpenPGP crypto directly.

Unofficial, third-party project. Not affiliated with or endorsed by Proton. If you build on it, follow the operational requirements in the upstream SDK README (honest x-pm-appversion, event-based sync, no Proton branding, etc.).

Status

Milestone 1 — session + read operations. Implemented:

  • Core: typed IDs, API response envelope, config, reqwest HTTP client with x-pm-uid / x-pm-appversion / bearer auth and transparent 401 token refresh.
  • Session: resume from existing tokens, end.
  • Account: user keys, address keys, and Proton's bcrypt key-passphrase derivation (the mailbox password is required even for read — see below).
  • Drive read: get_my_files_folder, get_node, enumerate_folder_children, with share and node (link) decryption and recursive parent-key resolution.

Not yet implemented: SRP password login (begin), uploads/downloads, sharing, events, trash, photos, signature-verification enforcement, persistent caching.

Workspace

Crate Purpose
crates/proton-sdk Core account/session/crypto (Proton.Sdk analogue)
crates/proton-drive-sdk High-level Drive client (Proton.Drive.Sdk analogue)

OpenPGP is provided by the pgp crate (rPGP).

The mailbox-password requirement

Proton's key model is layered, so read-only decryption still needs the user's mailbox (data) password, not just session tokens:

mailbox password + key salt --bcrypt--> key passphrase
  -> unlock user keys -> decrypt address-key token -> unlock address key
  -> decrypt share/node passphrase -> unlock node key -> decrypt names

ProtonApiSession::resume takes the tokens; ProtonDriveClient::new takes the mailbox password.

Usage

use proton_sdk::config::ProtonClientConfiguration;
use proton_sdk::session::{PasswordMode, ProtonApiSession, ResumeParameters};
use proton_drive_sdk::ProtonDriveClient;

# async fn run() -> proton_sdk::error::Result<()> {
let config = ProtonClientConfiguration::new("external-drive-myapp@0.1.0-alpha");
let session = ProtonApiSession::resume(config, ResumeParameters {
    session_id: "uid".into(),
    username: "user@proton.me".into(),
    user_id: "user-id".into(),
    access_token: "access".into(),
    refresh_token: "refresh".into(),
    scopes: vec![],
    is_waiting_for_second_factor_code: false,
    password_mode: PasswordMode::Single,
})?;

let drive = ProtonDriveClient::new(&session, b"mailbox-password".to_vec());
let root = drive.get_my_files_folder().await?;
for child in drive.enumerate_folder_children(&root.uid).await? {
    println!("{} ({:?})", child.name, child.kind);
}
# Ok(())
# }

Build & test

cargo build
cargo test

License

MIT, matching upstream. The MIT license covers this source only; use of Proton's hosted services remains subject to Proton's terms.