Skip to content

drive: add block upload verifier token and revision verification endpoint#2

Open
lmwashere wants to merge 2 commits intorclone:masterfrom
lmwashere:master
Open

drive: add block upload verifier token and revision verification endpoint#2
lmwashere wants to merge 2 commits intorclone:masterfrom
lmwashere:master

Conversation

@lmwashere
Copy link
Copy Markdown

Proton's storage backend now requires a Verifier.Token per block when
requesting block upload URLs (POST /drive/blocks). Without it, the storage
server rejects uploads with HTTP 422 / Code=200501 "Operation failed:
Please retry".

This commit adds:

  • RevisionVerification type and BlockUploadVerifier type in block_types.go
  • Verifier field (omitempty) on BlockUploadInfo
  • GetRevisionVerification() method calling the v2 API endpoint:
    GET /drive/v2/volumes/{volumeID}/links/{linkID}/revisions/{revisionID}/verification

The VerificationCode returned by that endpoint is XOR'd with the leading
bytes of each block's ciphertext in Proton-API-Bridge to produce the
per-block token (matching the algorithm in the official Proton Drive JS SDK
in ProtonDriveApps/sdk).

Note: the JS SDK also decrypts each block as a client-side integrity check
before computing the XOR. That step is not implemented here; the server-side
manifest signature still provides end-to-end integrity verification.

Reproducer: rclone copy <file> proton: --verbose
Expected: upload succeeds
Actual: 422 POST fra-storage.proton.me/storage/blocks: Operation failed: Please retry (Code=200501, Status=422)


This fix was identified and generated with Claude Code (AI assistant) by a
non-programmer user. It has not been independently reviewed by a Go or
cryptography expert. Expert review before merging is strongly recommended.

…oint

Proton's storage backend now requires a Verifier.Token per block when
requesting block upload URLs (POST /drive/blocks). Without it, the storage
server rejects uploads with HTTP 422 / Code=200501 "Operation failed:
Please retry".

This commit adds:

- RevisionVerification type and BlockUploadVerifier type in block_types.go
- Verifier field (omitempty) on BlockUploadInfo
- GetRevisionVerification() method calling the v2 API endpoint:
  GET /drive/v2/volumes/{volumeID}/links/{linkID}/revisions/{revisionID}/verification

The VerificationCode returned by that endpoint is XOR'd with the leading
bytes of each block's ciphertext in Proton-API-Bridge to produce the
per-block token (matching the algorithm in the official Proton Drive JS SDK).

Note: the JS SDK also decrypts each block as a client-side integrity check
before computing the XOR. That step is not implemented here; the server-side
manifest signature still provides end-to-end integrity verification.

This fix was identified and generated with Claude Code (AI assistant) by a
non-programmer user. It has not been independently reviewed by a Go or
cryptography expert. Expert review before merging is strongly recommended.

Fixes uploads failing with: 422 POST fra-storage.proton.me/storage/blocks:
Operation failed: Please retry (Code=200501, Status=422)
@mcanevet
Copy link
Copy Markdown

mcanevet commented Mar 13, 2026

Test Results with This Fix

Integration tests run on rclone backend using this PR:

✅ Passing Tests

  • FsEncoding (18 tests) - all PASS
  • FsPutFiles (most) - PASS
  • FsPutZeroLength - PASS
  • FsPutError - PASS
  • FsUploadUnknownSize - PASS
  • FsRootCollapse - PASS
  • ObjectOpen, ObjectOpenSeek, ObjectOpenRange - PASS
  • ObjectUpdate - PASS
  • ObjectRemove - PASS
  • And many more...

❌ Still Failing

  • FsMove - Code 2000 error ("maybe outdated app")
  • FsDirMove - Code 2000 error

Summary

This PR fixes the 422 block upload errors ✅, but move/rename operations still fail with Code 2000. A separate fix for session key reuse during move is needed.


Test command: RCLONE_CONFIG_TESTPROTONDRIVE_REPLACE_EXISTING_DRAFT=true go test -run TestIntegration -timeout 30m -v

@hardyhwood
Copy link
Copy Markdown

Thanks for running those integration tests, @mcanevet — really helpful data!

Glad to hear the 422 block upload errors are resolved ✅. The FsMove / FsDirMove Code 2000 failures are a known separate issue related to session key reuse during move operations — outside the scope of this PR. I agree a dedicated fix would be the right approach there.

Hopefully the maintainers can take a look now that there's community-verified test coverage on this.

Three fixes for Proton Drive operations:

1. MoveLinkReq: add required NameSignatureEmail field and fix SignatureEmail
   JSON tag. Without NameSignatureEmail the API returns Code=2000 ("value
   cannot be empty"). NodePassphraseSignature and SignatureEmail are now
   omitempty as they are only required for anonymously-created nodes.
   Ref: https://github.com/ProtonDriveApps/windows-drive/blob/main/src/ProtonDrive.Client/MoveLinkParameters.cs

2. UploadBlock: accept []byte instead of io.Reader so resty can replay the
   request body on retry. Previously, on a network drop resty retried with
   an exhausted reader, producing an empty body and Code=2003 from storage.

3. Retry 502 Bad Gateway: storage servers return 502 transiently; add it to
   the retry condition alongside 429/503 so individual block failures recover
   without restarting the entire file transfer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants