mirror of
https://github.com/narrrl/proton-sdk-rs.git
synced 2026-11-04 00:47:01 +01:00
updated readme
This commit is contained in:
1 parent
75f707719f
commit
0e335e35ec
1 file changed
+243
-92
@@ -10,18 +10,18 @@
|
|||||||
|
|
||||||
A pure-Rust reimplementation of the [Proton Drive SDK](https://github.com/ProtonDriveApps/sdk).
|
A pure-Rust reimplementation of the [Proton Drive SDK](https://github.com/ProtonDriveApps/sdk).
|
||||||
|
|
||||||
This repository contains two primary crates that replicate the functionality of the official Proton SDKs (available locally in the [sdk/](file:///home/narl/dev/private/proton-sdk-rs/sdk) submodule). Rather than relying on FFI bindings to the official C# NativeAOT core, `proton-sdk-rs` is a **pure-Rust** implementation. It communicates directly with the Proton Drive API over HTTP and performs all OpenPGP cryptographic operations natively using the [`pgp` (rPGP)](https://crates.io/crates/pgp) crate.
|
This repository contains a set of crates that replicate the functionality of the official Proton SDKs. Rather than relying on FFI bindings to the official C# NativeAOT core, `proton-sdk-rs` is a **pure-Rust** implementation. It communicates directly with the Proton Drive API over HTTPS, performs all OpenPGP cryptographic operations natively using the [`pgp` (rPGP)](https://crates.io/crates/pgp) crate, and provides an async, developer-friendly interface.
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> This is an unofficial, third-party project and is not affiliated with or endorsed by Proton.
|
> This is an unofficial, third-party project and is not affiliated with or endorsed by Proton.
|
||||||
> Applications building on top of this SDK must adhere to the operational guidelines of the upstream SDK (such as setting an honest `x-pm-appversion` header, using event-based sync, and avoiding Proton branding). Detailed requirements are documented in the upstream [sdk/README.md](file:///home/narl/dev/private/proton-sdk-rs/sdk/README.md).
|
> Applications building on top of this SDK must adhere to the operational guidelines of the upstream SDK (such as setting an honest `x-pm-appversion` header, using event-based sync, and avoiding Proton branding). Detailed requirements are documented in the upstream `sdk/README.md` (which can be found in the [sdk/](file:///home/narl/dev/private/proton-sdk-rs/sdk) submodule checkout).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Proven in Action
|
## Proven in Action
|
||||||
|
|
||||||
This SDK is the core engine powering the following real-world projects:
|
This SDK is the core engine powering real-world projects:
|
||||||
* **[proton-drive-linux](https://github.com/narrrl/proton-drive-linux)**: A native client and daemon for mounting and syncing Proton Drive on Linux systems, utilizing both crates provided by this repository.
|
* **[proton-drive-linux](https://github.com/narrrl/proton-drive-linux)**: A well-working native client and daemon for mounting (via FUSE) and syncing Proton Drive on Linux systems, utilizing both crates provided by this repository.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -38,38 +38,59 @@ OpenPGP features are powered by rPGP (version `0.20`), and HTTP requests are bui
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Current Feature & Parity Status
|
## System Architecture
|
||||||
|
|
||||||
`proton-sdk-rs` implements **Milestone 2 (Authenticated Read/Write)**. Parity with the official C# SDK (pinned at the upstream commit documented in [UPSTREAM_SYNC.md](file:///home/narl/dev/private/proton-sdk-rs/UPSTREAM_SYNC.md)) is actively maintained.
|
The following diagram illustrates how the crates interact with third-party libraries and the Proton API backend:
|
||||||
|
|
||||||
### Feature Matrix
|
```mermaid
|
||||||
|
graph TD
|
||||||
|
subgraph Client Application
|
||||||
|
PDL["proton-drive-linux (Daemon / Mount)"]
|
||||||
|
end
|
||||||
|
|
||||||
| Module | Feature | Rust Status | Notes / Upstream Parity |
|
subgraph proton-drive-rs ["proton-drive-rs (High-level client)"]
|
||||||
| :--- | :--- | :---: | :--- |
|
PDC["ProtonDriveClient"]
|
||||||
| **Session** | SRP-6a Login | ✅ | Password-based authentication via `begin` / SRP-6a proofs. |
|
PPC["ProtonPhotosClient"]
|
||||||
| | TOTP 2FA | ✅ | Support for applying second-factor TOTP codes. |
|
EEC["Entity Cache & Sync / Events"]
|
||||||
| | Token Refresh | ✅ | Scope refresh and transparent 401 token refresh. |
|
DEV["Devices / Sync Roots"]
|
||||||
| | Resume Session | ✅ | Restore clients instantly via serialized tokens. |
|
SHR["Sharing & Bookmarks"]
|
||||||
| **HTTP Client** | Retries & Jitter | ✅ | Exponential backoff for 408, 429, and 5xx, respecting `Retry-After`. |
|
end
|
||||||
| | Telemetry | ✅ | Pluggable request tracking (`ITelemetry` analogue). |
|
|
||||||
| **Drive / Volume** | Volume Resolution | ✅ | Auto-resolves volume lists; auto-creates the `my-files` root volume on first login. |
|
subgraph proton-sdk ["proton-sdk (Core foundational library)"]
|
||||||
| | Node Listing | ✅ | `get_node`, `enumerate_folder_children`, `enumerate_trash` with key resolution. |
|
PAS["ProtonApiSession (SRP Auth & TOTP)"]
|
||||||
| | File Operations | ✅ | Rename, trash, restore, delete, empty trash. |
|
PHC["ProtonHttpClient (Telemetry & Retry)"]
|
||||||
| | Move Operations | ✅ | Same-volume move. Batch moves are chunked automatically. |
|
CRY["Crypto Module (OpenPGP Keys / Derivation)"]
|
||||||
| | Cross-volume Move | ❌ | Not supported (throwing `NotImplementedException` in the C# public API too). |
|
end
|
||||||
| | Sharing | ❌ | Sharing APIs are omitted (absent in C# public API). |
|
|
||||||
| **Uploads** | Block Uploading | ✅ | Encrypts and uploads chunks (4 MiB default) to block storage. |
|
subgraph Third Party Crates
|
||||||
| | Streaming Upload | ✅ | Streams uploads from any type implementing `std::io::Read`. |
|
RPG["pgp (rPGP v0.20)"]
|
||||||
| | Revision Control | ✅ | Create drafts, upload blocks, and seal new file revisions. |
|
REQ["reqwest (HTTP)"]
|
||||||
| | AEAD Block Support | ✅ | SEIPDv2 / AES-256-GCM AEAD encryption alongside legacy SEIPDv1 (AES-256-CFB). |
|
end
|
||||||
| | Inline Thumbnails | ✅ | Generates and encrypts inline-signed thumbnails. |
|
|
||||||
| **Downloads** | Block Downloading | ✅ | Streams block retrieval, decryption, and signature checks. |
|
subgraph Remote Services
|
||||||
| | Content Integrity | ✅ | Verification of file manifests and block-level SHA-256 digests. |
|
API["Proton API (HTTPS)"]
|
||||||
| | Signature Verification | ✅ | Detached signature verification (non-fatal, reports status). |
|
STR["Proton Block Storage (API/Blob)"]
|
||||||
| **Photos** | Photos Timeline | ✅ | `ProtonPhotosClient` maps photostream, timeline enumeration, and photo downloads. |
|
end
|
||||||
| | Photo Uploads | ✅ | Uploading photos with `PhotoUploadMetadata` (capture time, tags, grouping). |
|
|
||||||
| | Photos Volume Create| ❌ | Volume creation is not yet ported. |
|
PDL --> PDC
|
||||||
| **Caching** | Pluggable Cache | ✅ | Pluggable entity cache (`with_entity_cache`); keys/secrets remain strictly in memory. |
|
PDL --> PPC
|
||||||
|
|
||||||
|
PDC --> PAS
|
||||||
|
PDC --> PHC
|
||||||
|
PDC --> EEC
|
||||||
|
PDC --> DEV
|
||||||
|
PDC --> SHR
|
||||||
|
|
||||||
|
PPC --> PAS
|
||||||
|
PPC --> PHC
|
||||||
|
|
||||||
|
PAS --> CRY
|
||||||
|
PHC --> REQ
|
||||||
|
CRY --> RPG
|
||||||
|
|
||||||
|
REQ --> API
|
||||||
|
REQ --> STR
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -81,30 +102,34 @@ Proton Drive relies on client-side zero-knowledge encryption. The security archi
|
|||||||
|
|
||||||
To perform any read or write operation, you must supply the user's **mailbox (data) password** in addition to the API session tokens. Decryption cascades as follows:
|
To perform any read or write operation, you must supply the user's **mailbox (data) password** in addition to the API session tokens. Decryption cascades as follows:
|
||||||
|
|
||||||
```
|
```mermaid
|
||||||
[Mailbox Password] + [Key Salt]
|
graph TD
|
||||||
│
|
PW["Mailbox Password"]
|
||||||
▼ (bcrypt key-passphrase derivation)
|
SALT["Key Salt"]
|
||||||
[Key Passphrase]
|
KDF["bcrypt Key Derivation"]
|
||||||
│
|
KPW["Key Passphrase"]
|
||||||
▼ (unlocks)
|
UPK["User Private Keys"]
|
||||||
[User Private Keys]
|
AKT["Address Key Token"]
|
||||||
│
|
APK["Address Private Key"]
|
||||||
▼ (decrypts)
|
SPW["Share Passphrase"]
|
||||||
[Address Key Token] ──► [Address Private Key]
|
NPK["Node/Share Private Key"]
|
||||||
│
|
CP["Content Key Packet (PKESK)"]
|
||||||
▼ (decrypts)
|
CK["Content Key (Symmetric AES-256)"]
|
||||||
[Share Passphrase]
|
CT["File Ciphertext Blocks"]
|
||||||
│
|
PT["Decrypted File / Metadata"]
|
||||||
▼ (unlocks)
|
|
||||||
[Share/Node Private Key]
|
PW --> KDF
|
||||||
│
|
SALT --> KDF
|
||||||
├──────────────────────────────┐
|
KDF --> KPW
|
||||||
▼ (decrypts metadata/names) ▼ (decrypts content packet)
|
KPW --> UPK
|
||||||
[Decrypted File Name] [Content Key (Symmetric AES-256)]
|
UPK --> AKT
|
||||||
│
|
AKT --> APK
|
||||||
▼ (decrypts)
|
APK --> SPW
|
||||||
[File Ciphertext Blocks]
|
SPW --> NPK
|
||||||
|
NPK --> CK
|
||||||
|
CP --> CK
|
||||||
|
CK --> PT
|
||||||
|
CT --> PT
|
||||||
```
|
```
|
||||||
|
|
||||||
1. **Passphrase Derivation**: The user's mailbox password is derived into a key passphrase via `bcrypt` using salts fetched from the API. See [derive.rs](file:///home/narl/dev/private/proton-sdk-rs/crates/proton-sdk/src/crypto/derive.rs).
|
1. **Passphrase Derivation**: The user's mailbox password is derived into a key passphrase via `bcrypt` using salts fetched from the API. See [derive.rs](file:///home/narl/dev/private/proton-sdk-rs/crates/proton-sdk/src/crypto/derive.rs).
|
||||||
@@ -112,25 +137,39 @@ To perform any read or write operation, you must supply the user's **mailbox (da
|
|||||||
3. **Share & Node Keys**: Nodes (files and folders) belong to shares. A share's passphrase is decrypted by the address key. The decrypted share passphrase is used to unlock the node's private key (usually X25519/Ed25519 or legacy RSA).
|
3. **Share & Node Keys**: Nodes (files and folders) belong to shares. A share's passphrase is decrypted by the address key. The decrypted share passphrase is used to unlock the node's private key (usually X25519/Ed25519 or legacy RSA).
|
||||||
4. **File Content Keys**: Files contain metadata and data blocks. The file's name and passphrase are encrypted. The symmetric **Content Key** (AES-256) is encapsulated in a PGP Public-Key Encrypted Session-Key (PKESK) packet addressed to the node key. See [content.rs](file:///home/narl/dev/private/proton-sdk-rs/crates/proton-sdk/src/crypto/content.rs).
|
4. **File Content Keys**: Files contain metadata and data blocks. The file's name and passphrase are encrypted. The symmetric **Content Key** (AES-256) is encapsulated in a PGP Public-Key Encrypted Session-Key (PKESK) packet addressed to the node key. See [content.rs](file:///home/narl/dev/private/proton-sdk-rs/crates/proton-sdk/src/crypto/content.rs).
|
||||||
|
|
||||||
### 2. Download Pipeline
|
### 2. Upload Pipeline
|
||||||
|
|
||||||
When streaming a file download via `download_file` or `download_file_to`:
|
|
||||||
|
|
||||||
1. **Resolve and Decrypt Content Key**: The PKESK packet `ContentKeyPacket` is retrieved from the node metadata and decrypted using the unlocked node private key, yielding the [`ContentKey`](file:///home/narl/dev/private/proton-sdk-rs/crates/proton-sdk/src/crypto/content.rs) (the symmetric session key).
|
|
||||||
2. **Retrieve Block List**: The client requests the active revision block list. Each block is represented by an absolute URL (`BareURL`) and requires a one-time `pm-storage-token` header (bearer auth is not sent to block storage hosts).
|
|
||||||
3. **Stream & Decrypt Blocks**:
|
|
||||||
- The block's ciphertext is downloaded.
|
|
||||||
- For **legacy files** (SEIPDv1): The ciphertext is decrypted using the content key in AES-256-CFB mode with MDC verification.
|
|
||||||
- For **AEAD files** (SEIPDv2): The ciphertext is decrypted using the content key in AES-256-GCM mode with 128 KiB chunk sizes.
|
|
||||||
4. **Integrity & Signature Verification**:
|
|
||||||
- The client computes the SHA-256 hash of each ciphertext block and compares it against the digests specified in the file's **Content Manifest**.
|
|
||||||
- The manifest's signature (`ManifestSignature`) is verified. The public keys for verification are resolved dynamically from the author's address (via `core/v4/keys/all`).
|
|
||||||
- Signature verification is non-fatal: a verification failure yields a [`VerificationStatus`](file:///home/narl/dev/private/proton-sdk-rs/crates/proton-sdk/src/crypto/verify.rs) but does not block read access. See [verify.rs](file:///home/narl/dev/private/proton-sdk-rs/crates/proton-sdk/src/crypto/verify.rs).
|
|
||||||
|
|
||||||
### 3. Upload Pipeline
|
|
||||||
|
|
||||||
When uploading a file:
|
When uploading a file:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
autonumber
|
||||||
|
participant App as Client Application
|
||||||
|
participant SDK as proton-drive-rs
|
||||||
|
participant PGP as pgp (rPGP)
|
||||||
|
participant API as Proton API
|
||||||
|
participant Store as Storage Host
|
||||||
|
|
||||||
|
App->>SDK: upload_file(parent_uid, name, reader)
|
||||||
|
SDK->>PGP: Generate X25519/Ed25519 Node Keypair
|
||||||
|
SDK->>PGP: Generate Random AES-256 Session Key (Content Key)
|
||||||
|
SDK->>SDK: Encrypt node passphrase under parent folder key
|
||||||
|
SDK->>SDK: Encrypt and hash (HMAC-SHA256) name
|
||||||
|
SDK->>SDK: Encrypt Content Key under node key
|
||||||
|
SDK->>API: POST /volumes/{vid}/files (Register Draft Revision)
|
||||||
|
API-->>SDK: Draft registered, return Block Storage URLs
|
||||||
|
loop For each 4MB Block
|
||||||
|
SDK->>PGP: Encrypt block data (AES-256-GCM SEIPDv2)
|
||||||
|
SDK->>PGP: Sign block data (detached signature)
|
||||||
|
SDK->>Store: POST block to storage endpoint with pm-storage-token
|
||||||
|
Store-->>SDK: Block uploaded, return block ID & hash
|
||||||
|
end
|
||||||
|
SDK->>SDK: Compile Content Manifest (signed SHA-256 list)
|
||||||
|
SDK->>API: PUT /volumes/{vid}/files/{uid}/revisions/{rev_id} (Seal Revision)
|
||||||
|
API-->>SDK: Revision finalized
|
||||||
|
SDK-->>App: Return created Node info
|
||||||
|
```
|
||||||
|
|
||||||
1. **Generate Node & Content Keys**: The client generates a fresh node keypair (Ed25519/X25519) and a random AES-256 content key.
|
1. **Generate Node & Content Keys**: The client generates a fresh node keypair (Ed25519/X25519) and a random AES-256 content key.
|
||||||
2. **Prepare Draft**:
|
2. **Prepare Draft**:
|
||||||
- The node passphrase is encrypted under the parent folder's key.
|
- The node passphrase is encrypted under the parent folder's key.
|
||||||
@@ -147,6 +186,47 @@ When uploading a file:
|
|||||||
- The manifest is signed using the address key (`ManifestSignature`).
|
- The manifest is signed using the address key (`ManifestSignature`).
|
||||||
- The revision is closed and finalized using a `PUT` request. See [client.rs](file:///home/narl/dev/private/proton-sdk-rs/crates/proton-drive-rs/src/client.rs) for the upload orchestration logic.
|
- The revision is closed and finalized using a `PUT` request. See [client.rs](file:///home/narl/dev/private/proton-sdk-rs/crates/proton-drive-rs/src/client.rs) for the upload orchestration logic.
|
||||||
|
|
||||||
|
### 3. Download Pipeline
|
||||||
|
|
||||||
|
When streaming a file download via `download_file` or `download_file_to`:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
autonumber
|
||||||
|
participant App as Client Application
|
||||||
|
participant SDK as proton-drive-rs
|
||||||
|
participant PGP as pgp (rPGP)
|
||||||
|
participant API as Proton API
|
||||||
|
participant Store as Storage Host
|
||||||
|
|
||||||
|
App->>SDK: download_file(node_uid)
|
||||||
|
SDK->>API: GET /volumes/{vid}/files/{uid}/revisions (Fetch Revision Metadata)
|
||||||
|
API-->>SDK: Content key packet (PKESK), manifest, block URLs
|
||||||
|
SDK->>PGP: Decrypt Content Key using unlocked Node Private Key
|
||||||
|
SDK->>API: GET /keys (Fetch Address Keys for signature verification)
|
||||||
|
API-->>SDK: Public Address Keys
|
||||||
|
loop For each block in manifest
|
||||||
|
SDK->>Store: GET block ciphertext (using pm-storage-token)
|
||||||
|
Store-->>SDK: Ciphertext block
|
||||||
|
SDK->>PGP: Decrypt block (AES-256-GCM / CFB)
|
||||||
|
SDK->>SDK: Calculate SHA-256 of block and verify against manifest
|
||||||
|
SDK-->>App: Stream decrypted bytes
|
||||||
|
end
|
||||||
|
SDK->>PGP: Verify detached Manifest Signature
|
||||||
|
SDK-->>App: Download complete (signature status reported)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. **Resolve and Decrypt Content Key**: The PKESK packet `ContentKeyPacket` is retrieved from the node metadata and decrypted using the unlocked node private key, yielding the `ContentKey` (the symmetric session key).
|
||||||
|
2. **Retrieve Block List**: The client requests the active revision block list. Each block is represented by an absolute URL (`BareURL`) and requires a one-time `pm-storage-token` header (bearer auth is not sent to block storage hosts).
|
||||||
|
3. **Stream & Decrypt Blocks**:
|
||||||
|
- The block's ciphertext is downloaded.
|
||||||
|
- For **legacy files** (SEIPDv1): The ciphertext is decrypted using the content key in AES-256-CFB mode with MDC verification.
|
||||||
|
- For **AEAD files** (SEIPDv2): The ciphertext is decrypted using the content key in AES-256-GCM mode with 128 KiB chunk sizes.
|
||||||
|
4. **Integrity & Signature Verification**:
|
||||||
|
- The client computes the SHA-256 hash of each ciphertext block and compares it against the digests specified in the file's **Content Manifest**.
|
||||||
|
- The manifest's signature (`ManifestSignature`) is verified. The public keys for verification are resolved dynamically from the author's address (via `core/v4/keys/all`).
|
||||||
|
- Signature verification is non-fatal: a verification failure yields a [`VerificationStatus`](file:///home/narl/dev/private/proton-sdk-rs/crates/proton-sdk/src/crypto/verify.rs) but does not block read access. See [verify.rs](file:///home/narl/dev/private/proton-sdk-rs/crates/proton-sdk/src/crypto/verify.rs).
|
||||||
|
|
||||||
### 4. Same-Volume Move Cryptography
|
### 4. Same-Volume Move Cryptography
|
||||||
|
|
||||||
Moving a file or folder within the same volume is an offline cryptographic operation that avoids re-uploading file data.
|
Moving a file or folder within the same volume is an offline cryptographic operation that avoids re-uploading file data.
|
||||||
@@ -155,13 +235,60 @@ Moving a file or folder within the same volume is an offline cryptographic opera
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Current Feature & Parity Status
|
||||||
|
|
||||||
|
`proton-sdk-rs` implements **Milestone 2 (Authenticated Read/Write)** and advanced desktop features. Parity with the official C# SDK (pinned at the upstream commit documented in [UPSTREAM_SYNC.md](file:///home/narl/dev/private/proton-sdk-rs/UPSTREAM_SYNC.md)) is actively maintained.
|
||||||
|
|
||||||
|
### Feature Matrix
|
||||||
|
|
||||||
|
| Module | Feature | Status | Notes / Upstream Parity |
|
||||||
|
| :--- | :--- | :---: | :--- |
|
||||||
|
| **Session** | SRP-6a Login | ✅ | Password-based authentication via `begin` / SRP-6a proofs. |
|
||||||
|
| | TOTP 2FA | ✅ | Support for applying second-factor TOTP codes. |
|
||||||
|
| | Token Refresh | ✅ | Scope refresh and transparent 401 token refresh. |
|
||||||
|
| | Resume Session | ✅ | Restore clients instantly via serialized tokens. |
|
||||||
|
| **HTTP Client** | Retries & Jitter | ✅ | Exponential backoff for 408, 429, and 5xx, respecting `Retry-After`. |
|
||||||
|
| | Telemetry | ✅ | Pluggable request tracking (`ITelemetry` analogue). |
|
||||||
|
| **Drive / Volume** | Volume Resolution | ✅ | Auto-resolves volume lists; auto-creates the `my-files` root volume on first login. |
|
||||||
|
| | Node Listing | ✅ | `get_node`, `enumerate_folder_children`, `enumerate_trash` with key resolution. |
|
||||||
|
| | File Operations | ✅ | Rename, trash, restore, delete, empty trash. |
|
||||||
|
| | Move Operations | ✅ | Same-volume move. Batch moves are chunked automatically. |
|
||||||
|
| | Cross-volume Move | ❌ | Not supported (throwing `NotImplementedException` in the C# public API too). |
|
||||||
|
| **Uploads** | Block Uploading | ✅ | Encrypts and uploads chunks (4 MiB default) to block storage. |
|
||||||
|
| | Streaming Upload | ✅ | Streams uploads from any type implementing `std::io::Read`. |
|
||||||
|
| | Revision Control | ✅ | Create drafts, upload blocks, and seal new file revisions. |
|
||||||
|
| | AEAD Block Support | ✅ | SEIPDv2 / AES-256-GCM AEAD encryption alongside legacy SEIPDv1 (AES-256-CFB). |
|
||||||
|
| | Inline Thumbnails | ✅ | Generates and encrypts inline-signed thumbnails. |
|
||||||
|
| **Downloads** | Block Downloading | ✅ | Streams block retrieval, decryption, and signature checks. |
|
||||||
|
| | Content Integrity | ✅ | Verification of file manifests and block-level SHA-256 digests. |
|
||||||
|
| | Signature Verification | ✅ | Detached signature verification (non-fatal, reports status). |
|
||||||
|
| **Devices** | Device Registration | ✅ | Create and register desktop/sync clients (`create_device`). |
|
||||||
|
| | Device Listing | ✅ | List registered devices and their sync root folders (`enumerate_devices`). |
|
||||||
|
| | Device Operations | ✅ | Rename and delete registered devices. |
|
||||||
|
| **Sharing & Links** | Member Management | ✅ | Invite users (`invite_users`), list members, update roles, and remove members. |
|
||||||
|
| | Public Share Links | ✅ | Create public shareable links (`create_public_link`) with password protection and expiry. |
|
||||||
|
| | External Invites | ✅ | Invite non-Proton users (`invite_external_users`) and track registration status. |
|
||||||
|
| | Bookmarks | ✅ | Save and list public link bookmarks (`create_bookmark`, `list_bookmarks`). |
|
||||||
|
| | Incoming Invites | ✅ | List, accept, or reject invitations shared *with* the current user. |
|
||||||
|
| **Photos** | Photos Timeline | ✅ | `ProtonPhotosClient` maps photostream, timeline enumeration, and photo downloads. |
|
||||||
|
| | Photo Uploads | ✅ | Uploading photos with `PhotoUploadMetadata` (capture time, tags, grouping). |
|
||||||
|
| | Photos Volume Create| ❌ | Volume creation is not yet ported. |
|
||||||
|
| **Caching** | Pluggable Cache | ✅ | Pluggable entity cache (`with_entity_cache`); keys/secrets remain strictly in memory. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Usage Example
|
## Usage Example
|
||||||
|
|
||||||
The following code illustrates performing an SRP login, resolving the `My Files` root, and listing its immediate children.
|
The following code illustrates:
|
||||||
|
1. Resuming a saved session (`ProtonApiSession::resume`).
|
||||||
|
2. Initializing the [`ProtonDriveClient`](file:///home/narl/dev/private/proton-sdk-rs/crates/proton-drive-rs/src/client.rs).
|
||||||
|
3. Querying the `My Files` root and listing immediate folder children.
|
||||||
|
4. Uploading a small file stream.
|
||||||
|
|
||||||
```rust,no_run
|
```rust,no_run
|
||||||
|
use std::io::Cursor;
|
||||||
use proton_sdk::config::ProtonClientConfiguration;
|
use proton_sdk::config::ProtonClientConfiguration;
|
||||||
use proton_sdk::session::ProtonApiSession;
|
use proton_sdk::session::{PasswordMode, ProtonApiSession, ResumeParameters};
|
||||||
use proton_drive_rs::ProtonDriveClient;
|
use proton_drive_rs::ProtonDriveClient;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
@@ -169,39 +296,57 @@ async fn main() -> proton_sdk::error::Result<()> {
|
|||||||
// 1. Configure client with honest identification
|
// 1. Configure client with honest identification
|
||||||
let config = ProtonClientConfiguration::new("external-drive-myapp@0.1.0-alpha");
|
let config = ProtonClientConfiguration::new("external-drive-myapp@0.1.0-alpha");
|
||||||
|
|
||||||
// 2. Perform SRP Login
|
// 2. Resume a previously stored session
|
||||||
let mut session =
|
// (In production, save these credentials securely after SRP login)
|
||||||
ProtonApiSession::begin(config, "username@proton.me", b"mailbox-password").await?;
|
let session = ProtonApiSession::resume(config, ResumeParameters {
|
||||||
|
session_id: "session-uid-from-login".into(),
|
||||||
// Handle TOTP 2FA if required
|
username: "user@proton.me".into(),
|
||||||
if session.is_waiting_for_second_factor() {
|
user_id: "user-id-from-login".into(),
|
||||||
session.apply_second_factor_code("123456").await?;
|
access_token: "current-access-token".into(),
|
||||||
}
|
refresh_token: "current-refresh-token".into(),
|
||||||
|
scopes: vec![],
|
||||||
|
is_waiting_for_second_factor_code: false,
|
||||||
|
password_mode: PasswordMode::Single,
|
||||||
|
})?;
|
||||||
|
|
||||||
// 3. Initialize Drive Client
|
// 3. Initialize Drive Client with user's mailbox password
|
||||||
let drive = ProtonDriveClient::new(&session, b"mailbox-password".to_vec());
|
let mailbox_password = b"my-mailbox-password".to_vec();
|
||||||
|
let drive = ProtonDriveClient::new(&session, mailbox_password);
|
||||||
|
|
||||||
// 4. Resolve My Files root
|
// 4. Resolve the My Files root folder
|
||||||
let root = drive.get_my_files_folder().await?;
|
let root = drive.get_my_files_folder().await?;
|
||||||
|
println!("Root folder resolved. UID: {}", root.uid);
|
||||||
|
|
||||||
// 5. Enumerate children uids and fetch their node data
|
// 5. Enumerate and print immediate children
|
||||||
let child_uids = drive.enumerate_folder_children_node_uids(&root.uid).await?;
|
let child_uids = drive.enumerate_folder_children_node_uids(&root.uid).await?;
|
||||||
let children = drive.enumerate_nodes(&child_uids).await?;
|
let children = drive.enumerate_nodes(&child_uids).await?;
|
||||||
|
|
||||||
for child in children {
|
for child in children {
|
||||||
println!("Node: {} | Type: {:?}", child.name, child.kind);
|
println!("Node: {} | Type: {:?}", child.name, child.kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 6. Upload a new file from a memory stream
|
||||||
|
let file_content = b"Hello, Proton Drive from pure Rust!";
|
||||||
|
let file_size = file_content.len() as u64;
|
||||||
|
let mut reader = Cursor::new(file_content);
|
||||||
|
|
||||||
|
let new_node = drive.upload_file_from(
|
||||||
|
&root.uid,
|
||||||
|
"hello_rust.txt",
|
||||||
|
file_size,
|
||||||
|
&mut reader,
|
||||||
|
).await?;
|
||||||
|
println!("Successfully uploaded: {} (UID: {})", new_node.name, new_node.uid);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If you have pre-saved session tokens, you can skip the login flow and resume the session immediately using `ProtonApiSession::resume`.
|
### Live Smoke Test & SRP Login
|
||||||
|
|
||||||
A live smoke test exists in [live_login.rs](file:///home/narl/dev/private/proton-sdk-rs/crates/proton-drive-rs/examples/live_login.rs) (which reads credentials from a local `.env` and `PROTON_TOTP_SECRET` env var):
|
If you need to perform an SRP password login and TOTP authentication, check out the live smoke test example at [live_login.rs](file:///home/narl/dev/private/proton-sdk-rs/crates/proton-drive-rs/examples/live_login.rs):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
PROTON_TOTP_SECRET=... cargo run -p proton-drive-rs --example live_login
|
PROTON_TOTP_SECRET=your_base32_secret cargo run -p proton-drive-rs --example live_login
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -210,7 +355,7 @@ PROTON_TOTP_SECRET=... cargo run -p proton-drive-rs --example live_login
|
|||||||
|
|
||||||
### Building
|
### Building
|
||||||
|
|
||||||
Ensure you have Rust installed (tested with Rust 1.75+).
|
Ensure you have a modern Rust toolchain installed (edition 2024, tested on Rust 1.96+).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo build
|
cargo build
|
||||||
@@ -242,6 +387,12 @@ PROTON_TOTP_SECRET=your_base32_totp_secret cargo test -p proton-drive-rs --test
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Upstream Synchronization
|
||||||
|
|
||||||
|
We maintain active parity with the official C# SDK codebase. Commit triage and history synchronization records are documented in [UPSTREAM_SYNC.md](file:///home/narl/dev/private/proton-sdk-rs/UPSTREAM_SYNC.md).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is licensed under the MIT License, matching the license of the upstream SDK. See [LICENSE](file:///home/narl/dev/private/proton-sdk-rs/LICENSE) for details. Use of Proton's hosted services remains subject to Proton's terms of service.
|
This project is licensed under the MIT License, matching the license of the upstream SDK. See [LICENSE](file:///home/narl/dev/private/proton-sdk-rs/LICENSE) for details. Use of Proton's hosted services remains subject to Proton's terms of service.
|
||||||
Reference in new issue
Block a user