This commit is contained in:
nvrl committed 2026-06-25 09:42:34 +02:00
commit 808a96cdd1
28 files changed
+8410

No files matched your search

+88
View File
@@ -0,0 +1,88 @@
# proton-sdk-rs
A pure-Rust reimplementation of the [Proton Drive SDK](https://github.com/ProtonDriveApps/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`](https://crates.io/crates/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
```rust,no_run
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
```bash
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.