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:
resumefrom 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.