Le mode E2E v1 asymétrique de Coffrify Inbox repose sur une paire de clés X25519 générée entièrement dans le navigateur du propriétaire de la drop-box. La clé publique est stockée en clair sur Coffrify pour que les expéditeurs puissent chiffrer leur envoi via un sealed-box libsodium. La clé privée, elle, ne quitte jamais le poste du propriétaire : elle est enveloppée avec PBKDF2-SHA256 (600 000 itérations minimum) et AES-256-GCM avant d'être stockée côté serveur. Coffrify ne voit donc jamais le contenu des fichiers, ni la clé symétrique qui les protège. Ce guide couvre trois opérations : activer l'E2E sur une drop-box, soumettre un dépôt chiffré via l'API publique, et désactiver temporairement le mode E2E sans perdre la capacité de déchiffrer les anciens dépôts.
Endpoints concernés
/api/workspace/inbox/e2eActivation du chiffrement E2E sur la drop-box active : dépose la clé publique X25519 et l'enveloppe de clé privée. Réservé aux rôles `owner` et `admin`./api/workspace/inbox/e2eRécupère l'état E2E de la drop-box active : `enabled`, `public_key`, `private_key_wrapped` et `activated_at`. Utilisé par le navigateur du propriétaire pour déchiffrer les soumissions./api/workspace/inbox/e2eDésactive le mode E2E (passe `e2e_enabled` à `false`) sans supprimer le keypair. Les soumissions antérieures restent déchiffrables hors ligne par le propriétaire./api/public/inbox/submitSoumission publique d'un dépôt. Lorsque la drop-box a `e2e_enabled = true`, ce endpoint exige `encryption_mode: "e2e_v1_asym"` et `encryption_metadata` contenant la clé symétrique enveloppée. Authentifié par captcha (header `x-captcha-token`), pas par token API.Authentification
Les routes /api/workspace/inbox/e2e (GET, POST, DELETE) requièrent une session propriétaire ou administrateur du workspace. Aucun token API n'est accepté sur ces routes : elles utilisent la session de l'utilisateur connecté. Le rôle doit être owner ou admin ; un rôle member reçoit une erreur 403 forbidden. La route de soumission publique /api/public/inbox/submit n'utilise pas de token API mais exige un header x-captcha-token valide avec le scope drop-box. Si vous créez un token API pour des intégrations serveur (format cit_live_…), utilisez plutôt la route /api/v1/inbox/submit avec un scope read_write.
Corps de la requête, Activation E2E (POST /api/workspace/inbox/e2e)
| Champ | Type | Requis | Description |
|---|---|---|---|
| public_key | string (base64url) | Oui | Clé publique X25519 de 32 octets encodée en base64url. Doit décoder exactement en 32 octets. |
| private_key_wrapped | object | Oui | Enveloppe de la clé privée (voir sous-champs ci-dessous). Ne doit jamais contenir de champ private_key, raw_key, plaintext ou passphrase. |
| private_key_wrapped.algorithm | string | Oui | Doit valoir exactement "x25519-sealed-box-v1". |
| private_key_wrapped.kdf | string | Oui | Doit valoir exactement "pbkdf2-sha256". |
| private_key_wrapped.iterations | number | Oui | Nombre d'itérations PBKDF2. Minimum : 600 000 (plancher OWASP 2023). |
| private_key_wrapped.salt | string | Oui | Sel PBKDF2 encodé (base64 ou hex) généré côté client. |
| private_key_wrapped.iv | string | Oui | IV AES-256-GCM encodé (base64 ou hex). |
| private_key_wrapped.ciphertext | string | Oui | Clé privée chiffrée par AES-256-GCM avec la clé dérivée du mot de passe propriétaire. |
Corps de la requête, Soumission E2E (POST /api/public/inbox/submit)
| Champ | Type | Requis | Description |
|---|---|---|---|
| workspace_slug | string | Oui* | Slug du workspace cible. Alternatif : workspace_domain. |
| workspace_domain | string | Oui* | Domaine personnalisé vérifié. Alternatif : workspace_slug. |
| files | array | Oui | Tableau d'objets { name: string, size: number, display_type?: string }. Au moins 1 fichier, max 50 (ou limite de la box). |
| requester_email | string | Oui | Adresse e-mail de l'expéditeur. Max 254 caractères, format valide. |
| requester_name | string | Conditionnel | Nom de l'expéditeur. Requis si la box a require_requester_name = true. |
| message | string | Non | Message accompagnant le dépôt. Tronqué à message_max_chars de la box (défaut 500). |
| encryption_mode | string | Oui (E2E) | Doit valoir "e2e_v1_asym" si la box a e2e_enabled = true. Sinon "server_side" ou omis. |
| encryption_metadata | object | Oui (E2E) | Métadonnées de chiffrement. Doit contenir wrapped_symmetric_key (string, sealed-box libsodium) et files (object avec IV par fichier). |
| custom_field_values | object | Conditionnel | Réponses aux champs personnalisés de la box, clé = UUID du champ. |
Exemples d'appels
Réponses
POST /api/workspace/inbox/e2e (activation réussie) : retourne 200 OK.
GET /api/workspace/inbox/e2e : retourne l'état courant du keypair.
POST /api/public/inbox/submit avec E2E (dépôt créé) : retourne 200 OK avec les URLs presignées pour chaque fichier.
Erreurs
| Code HTTP | Clé d'erreur | Quand | Résolution |
|---|---|---|---|
| 400 | public_key invalide (attendu base64url) | La clé publique n'est pas en base64url ou ne fait pas 32 octets après décodage. | Utilisez la sortie directe de sodium.to_base64(keyPair.publicKey, sodium.base64_variants.URLSAFE_NO_PADDING). |
| 400 | private_key_wrapped invalide | L'objet private_key_wrapped manque un champ obligatoire, l'algorithme n'est pas x25519-sealed-box-v1, ou iterations < 600000. | Vérifiez que tous les sous-champs sont présents et que iterations >= 600000. |
| 400 | private_key_wrapped contient un champ interdit | Le JSON de l'enveloppe contient private_key, raw_key, plaintext ou passphrase. | Ne jamais inclure la clé en clair dans l'enveloppe. Seul le ciphertext est accepté. |
| 400 | DROPBOX_E2E_REQUIRED | La drop-box a e2e_enabled = true mais la soumission envoyait encryption_mode: "server_side" ou omettait le champ. | Passez encryption_mode: "e2e_v1_asym" et fournissez encryption_metadata. |
| 400 | DROPBOX_E2E_METADATA_INVALID | encryption_metadata est absent, ou wrapped_symmetric_key n'est pas une string, ou files est absent. | Vérifiez la structure : { wrapped_symmetric_key: string, files: { "0": { iv: string }, ... } }. |
| 400 | DROPBOX_E2E_NOT_ENABLED | La soumission envoyait encryption_mode: "e2e_v1_asym" mais la box n'a pas E2E activé. | Activez d'abord E2E via POST /api/workspace/inbox/e2e, ou passez server_side si la box ne le requiert pas. |
| 401 | CAPTCHA_REQUIRED | Le header x-captcha-token est absent ou invalide sur la route publique. | Intégrez le composant captcha Coffrify ou obtenez un token via l'API captcha avec scope=drop-box. |
| 401 | unauthorized | Session expirée ou absente sur les routes workspace. | Reconnectez-vous au dashboard Coffrify. |
| 402 | upload_blocked | Le workspace a atteint son quota mensuel de dépôts ou a un paiement en retard (uploads_blocked_until). | Mettez à niveau le plan ou régularisez le paiement depuis le dashboard. |
| 403 | forbidden | L'utilisateur connecté a le rôle member, qui ne peut pas activer/désactiver l'E2E. | Utilisez un compte avec le rôle owner ou admin. |
| 404 | drop_box_not_found | Aucune drop-box active n'existe pour le workspace. | Créez une drop-box depuis l'Inbox Console avant d'activer E2E. |
| 409 | DROPBOX_E2E_ACTIVATION_INCOMPLETE | La box a e2e_enabled = true mais e2e_public_key est null : l'activation est en cours. | Finalisez l'activation E2E depuis l'Inbox Console du propriétaire. |
| 500 | Échec d'activation E2E | Erreur base de données lors de l'update du keypair. | Réessayez. Si le problème persiste, contactez le support Coffrify. |
Voir aussi
- Créer un token API d'Inbox (`cit_live_…`)
- Soumettre un dépôt via token API serveur (`cit_live_…`)
- Configurer des webhooks Inbox (`deposit.created`)
- Champs personnalisés sur une drop-box
- Référence complète de l'API Inbox