Aller au contenu
← Tous les articles

Comment tapeshelf chiffre les vidéos, et pourquoi il ne stocke aucune clé

Une vidéo privée sur tapeshelf est réservée à son propriétaire et aux personnes qu’il a choisies. Voici comment l’application s’y tient, et où s’arrête la protection.

De l’import à la lecture

Votre navigateur envoie le fichier directement dans un bucket privé d’un stockage compatible S3, par morceaux de 16 Mo qui reprennent là où ils en étaient si la connexion coupe. Le fichier ne passe jamais par nos serveurs d’API.

Un processus d’arrière-plan, le worker, vérifie le fichier avec ffprobe, puis en retire les métadonnées (lieu et date de tournage, appareil, auteur, commentaires) en le réécrivant sans le réencoder. C’est ce fichier nettoyé que l’on télécharge. Les vidéos importées avant le 18 octobre 2026 gardent leurs métadonnées.

Une vidéo H.264 jusqu’en 1080p qui passe encore quelques vérifications est simplement réempaquetée, ce qui prend quelques secondes. Tout le reste est converti en H.264 jusqu’en 1080p. ffmpeg découpe ensuite le résultat en segments HLS de six secondes, que Safari lit nativement et que les autres navigateurs lisent avec hls.js.

Chiffrer les segments

ffmpeg sait chiffrer du HLS tout seul, mais il veut la clé dans un fichier sur le disque. Nous ne voulions de clé sur aucun disque, alors c’est le worker qui chiffre lui-même les segments :

  • chaque segment est chiffré en AES-128 en mode CBC, la méthode que définit le standard HLS ;
  • la clé fait 16 octets, elle est propre à chaque vidéo et n’existe que dans la mémoire du worker pendant qu’il travaille ;
  • le vecteur d’initialisation est le numéro de séquence du segment, ce que suppose un lecteur HLS quand la playlist n’en indique pas.

Seuls les segments chiffrés et leur playlist partent dans le bucket privé. Les fichiers temporaires du worker sont supprimés à la fin de la tâche.

Des clés jamais stockées

Ensuite, la clé n’est conservée nulle part. Au lieu de générer une clé aléatoire puis de devoir la garder en lieu sûr, tapeshelf la recalcule chaque fois qu’il en a besoin :

clé de la vidéo = HKDF-SHA256(clé maîtresse, "video:" + id de la vidéo + version) → 16 octets

Chaque montage fait monter la version de la vidéo, ce qui lui donne une nouvelle clé.

La clé maîtresse est un unique secret dans la configuration du serveur. Elle n’est ni dans la base de données, ni dans les buckets, ni dans les sauvegardes. Une copie de la base ne contient aucune clé de vidéo et le bucket ne contient que des segments chiffrés : un attaquant aurait aussi besoin de la configuration du serveur.

Si vous perdez la clé maîtresse, plus aucune vidéo ne pourra être lue, et aucune sauvegarde de la base n’y changera rien. C’est surtout important si vous faites tourner tapeshelf sur votre propre serveur.

Trois requêtes quand vous lancez la lecture

  1. Lecture. L’API vérifie que vous avez le droit de regarder : vous êtes l’auteur, la vidéo est sur votre étagère, ou elle est publique. Elle renvoie alors l’adresse d’une playlist avec un jeton signé, valable une heure, qui nomme la vidéo et vous (ou personne, si vous n’êtes pas connecté).
  2. Playlist. L’API vérifie de nouveau le jeton et vos droits, puis réécrit la playlist à la volée. Chaque segment devient un lien signé vers le stockage, et la ligne de la clé renvoie vers l’API.
  3. Clé. Le jeton doit avoir été émis pour cette vidéo. Pour une vidéo privée, votre session connectée doit aussi appartenir à la personne nommée dans le jeton. Alors seulement l’API calcule la clé et envoie ses 16 octets.

Un lien temporaire n’a pas de compte à vérifier : sur sa page, le jeton nomme le lien lui-même. Chaque requête vérifie que le lien fonctionne encore et contient toujours la vidéo, et le jeton ne survit jamais au lien. Les vidéos qu’un invité a reçues dans un échange se lisent de la même façon sur la page de l’échange, pendant une semaine.

Les décisions d’accès sont gardées en cache une minute, pour qu’un film de deux heures n’interroge pas la base à chaque requête. Une vidéo supprimée peut donc encore être lancée pendant cette minute. Un lien temporaire expiré ou révoqué, lui, s’arrête aussitôt. Dans les deux cas, un lecteur déjà lancé garde sa clé et ses liens de segments, et peut continuer à lire.

Les liens des segments sont eux aussi signés et expirent, au bout d’une heure ou plus. Le lecteur ne charge la playlist qu’une fois, et des liens trop courts casseraient une simple pause. Quand un lien expire, le lecteur redemande la lecture et reprend au même endroit. Sans la clé, de toute façon, un segment ne sert à rien.

Pourquoi il n’y a pas de fichier à récupérer

Le lecteur ne reçoit jamais de lien vers le fichier vidéo. Il reçoit une playlist liée à un jeton, des morceaux chiffrés et une clé protégée par une vérification. Copiez l’adresse de la playlist d’une vidéo privée dans le navigateur d’un ami : rien ne se lance, car la clé exige votre session.

Le téléchargement est une action à part. Les personnes connectées peuvent télécharger ce qu’elles ont le droit de regarder. Sans compte, on ne peut télécharger que par un lien temporaire que quelqu’un vous a envoyé, ou ce qu’on a reçu en tant qu’invité dans un échange, pendant une semaine. Un lien de téléchargement dure deux minutes.

Les images fonctionnent autrement. Les couvertures, les 16 images extraites de chaque vidéo et l’aperçu image par image qu’on en tire se trouvent dans un bucket public, sous de longs noms aléatoires, et le contenu du bucket ne peut pas être listé. L’aperçu d’une vidéo privée est visible exprès : il montre au visiteur ce qu’il s’apprête à demander.

Ce contre quoi cela protège

  • Les personnes sans accès n’obtiennent ni playlist, ni segment, ni clé.
  • Un lien de segment qui fuite n’est que du bruit chiffré. Un lien de playlist d’une vidéo privée qui fuite ne fonctionne pas sans la session de la personne à qui il a été émis, et il expire de toute façon dans l’heure.
  • Une copie volée de la base de données ne révèle aucune clé.

Ce contre quoi cela ne protège pas

  • Qui peut regarder peut enregistrer. Une personne qui a l’accès peut filmer son écran ou enregistrer le flux avec les bons outils. La clé lui a été donnée en toute légitimité. tapeshelf n’a pas de DRM. Un vrai DRM comme Widevine ou FairPlay dépend de serveurs de licences commerciaux, et il ne peut toujours rien contre un appareil photo braqué sur un écran.
  • Les personnes avec qui vous partagez. Un partage ou un échange donne à l’autre une copie permanente, et cette personne peut télécharger le fichier. Toute personne qui ouvre un lien temporaire que vous avez envoyé le peut aussi, tant qu’il fonctionne. Ce que devient le fichier ensuite ne dépend plus de nous. Partagez avec des gens en qui vous avez confiance.
  • Le serveur lui-même. Ce n’est pas du chiffrement de bout en bout. C’est le serveur qui calcule les clés, donc celui qui l’administre peut lire n’importe quelle vidéo. Sur tapeshelf.com, c’est nous, et nous ouvrons des vidéos privées quand c’est nécessaire pour faire fonctionner et modérer le service. Sur une instance auto-hébergée, c’est son administrateur.

La version courte se trouve sur la page sécurité. Si vous préférez vérifier plutôt que nous croire sur parole, le code est open source, et vous pourrez le faire tourner vous-même.