← Tous les articles

Base64 n'est pas du chiffrement : une idée fausse fréquente chez les développeurs

Les chaînes encodées en Base64 ont l'air brouillées, mais n'importe qui peut les décoder en un appel de fonction. Apprenez ce qu'est vraiment Base64, pourquoi on le confond avec du chiffrement et quoi utiliser quand vous devez vraiment protéger des données.

« Je vais l’encoder en Base64 pour que personne ne puisse le lire. » Cette phrase apparaît dans les revues de code, les messages Slack et les réponses Stack Overflow plus souvent qu’elle ne devrait. Base64, ce n’est pas du chiffrement. Ce n’est pas de l’obfuscation. Ce n’est pas de la sécurité d’aucune sorte. Décoder demande un appel de fonction et aucune connaissance d’une clé ou d’un secret. Cet article explique ce qu’est réellement Base64, pourquoi la confusion persiste, et ce qu’il faut utiliser à la place quand on a vraiment besoin de protéger des données.

Ce qu’est réellement Base64

Base64 est un schéma d’encodage —— un mappage réversible entre des données binaires et un ensemble de 64 caractères ASCII imprimables (A–Z, a–z, 0–9, +, /, avec = comme padding).

Chaque 3 octets d’entrée deviennent 4 caractères Base64. L’algorithme est entièrement déterministe et ne nécessite aucune clé :

// Encodage
btoa("hello")          // → "aGVsbG8="
btoa("secret password") // → "c2VjcmV0IHBhc3N3b3Jk"

// Décodage —— un appel, pas de clé
atob("c2VjcmV0IHBhc3N3b3Jk") // → "secret password"

C’est tout. Quiconque a accès à la chaîne encodée peut la décoder instantanément, dans n’importe quel langage, n’importe quel environnement, sans information supplémentaire.

Pourquoi la confusion existe

Les chaînes encodées en Base64 ressemblent à des données chiffrées. Elles regorgent de majuscules, minuscules, chiffres et caractères spéciaux mélangés, et n’ont aucune ressemblance visible avec l’entrée originale. Ce bruit visuel suffit à tromper un observateur non technique —— et, étonnamment souvent, un observateur technique aussi.

Le motif est aussi renforcé par proximité. Base64 apparaît constamment dans des contextes de sécurité :

  • Les certificats HTTPS sont encodés en Base64 (format PEM)
  • Les tokens JWT utilisent l’encodage Base64url pour leur header et leur payload
  • L’authentification HTTP Basic envoie les identifiants en Base64
  • Les clés SSH sont stockées en Base64
  • Les données chiffrées sont souvent encodées en Base64 pour le transport

Voir Base64 dans tous ces contextes adjacents à la sécurité pousse les développeurs à confondre encodage et sécurité. L’encodage n’est que l’emballage ; la sécurité vient des opérations cryptographiques en dessous.

Encodage vs chiffrement : la différence centrale

La distinction est simple et absolue :

Encodage (Base64)Chiffrement (AES, RSA…)
ButReprésenter des données binaires comme du texteDissimuler des données aux parties non autorisées
Clé requise ?NonOui
Réversible par tous ?Oui —— un appel de fonctionSeulement avec la bonne clé
Ajoute de la confidentialité ?NonOui (si utilisé correctement)
Taille de sortie~33 % plus grande que l’entréeVarie selon l’algorithme

Le chiffrement transforme les données avec une clé, de sorte que sans la clé, retrouver l’original soit computationnellement infaisable. L’encodage Base64 n’a pas cette propriété.

Erreurs de sécurité en conditions réelles

Stocker des secrets « encodés » dans le code source

// ❌ Ce n’est pas secret —— n’importe qui peut le décoder
const API_KEY = atob("c2stbGl2ZS1hYmMxMjM0NTY3ODk=");

// Quiconque lit ce code exécute :
atob("c2stbGl2ZS1hYmMxMjM0NTY3ODk=") // → "sk-live-abc123456789"

Les outils automatisés de scan de secrets (GitHub Secret Scanning, GitGuardian, truffleHog) décodent les chaînes Base64 dans le cadre de leur détection. Si vous comptez sur Base64 pour les arrêter, ça ne marchera pas.

Authentification HTTP Basic

// L’en-tête Authorization ressemble à :
Authorization: Basic dXNlcjpwYXNzd29yZA==

// Ce Base64 se décode trivialement :
atob("dXNlcjpwYXNzd29yZA==") // → "user:password"

L’authentification HTTP Basic n’est sûre que sur HTTPS —— la couche TLS fournit le vrai chiffrement. Le Base64 dans l’en-tête sert uniquement à encoder la paire username:password en une seule valeur textuelle, pas à la dissimuler. Sur HTTP en clair, quiconque intercepte le trafic peut lire les identifiants instantanément.

Traiter les « tokens » JWT comme des secrets

// Un JWT ressemble à trois sections Base64url reliées par des points :
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjQyfQ.abc123

// La section centrale (payload) se décode en :
atob("eyJ1c2VySWQiOjQyfQ") // → '{"userId":42}'

Les payloads JWT ne sont pas chiffrés —— ils sont encodés en Base64url et signés. Quiconque reçoit le token peut lire le payload. La signature empêche la manipulation mais n’apporte pas la confidentialité. Ne mettez jamais de données sensibles (mots de passe, numéros de carte, informations personnelles) dans un payload JWT à moins d’utiliser JWE (JSON Web Encryption), qui est un standard différent et bien moins courant.

Obfusquer des données dans les URLs

// Motif courant dans les apps héritées
/profile?data=eyJ1c2VySWQiOjQyfQ==

// Collez ça dans n’importe quel décodeur :
atob("eyJ1c2VySWQiOjQyfQ==") // → '{"userId":42}'

Base64 dans les URLs n’ajoute aucune sécurité. Ça casse aussi facilement —— les caractères + et / du Base64 standard ne sont pas URL-safe et doivent être encodés par pourcentage, ce qui explique pourquoi Base64url (+-, /_, pas de padding) existe comme variante distincte.

À quoi sert vraiment Base64

Base64 a des usages légitimes et importants —— juste pas pour la sécurité :

  • Embarquer des données binaires dans des formats texte —— images, polices et fichiers intégrés comme URIs data: en HTML/CSS, ou pièces jointes dans des réponses JSON d’API
  • Pièces jointes d’e-mail —— l’encodage MIME utilise Base64 pour transmettre des fichiers binaires sur des protocoles qui ne gèrent que de l’ASCII 7 bits
  • Sécurité de transport —— certains canaux corrompent les données binaires (octets nuls, caractères de contrôle) ; Base64 garantit que le contenu arrive intact
  • Identifiants opaques —— encoder un ID ou un curseur en Base64 signale aux consommateurs de l’API « n’essayez pas de parser ceci », bien que ça n’apporte aucune sécurité

Quoi utiliser quand vous avez vraiment besoin de sécurité

Si votre objectif est d’empêcher l’accès non autorisé aux données, utilisez un véritable outil cryptographique :

ObjectifQuoi utiliser
Chiffrer des données au reposAES-256-GCM (chiffrement symétrique)
Chiffrer des données en transitTLS 1.3 (HTTPS)
Hacher des mots de passebcrypt, scrypt ou Argon2 —— jamais SHA-256 seul
Signer des tokensHMAC-SHA256 (comme JWT HS256) ou RS256
Stocker des secretsVariables d’environnement, un gestionnaire de secrets (Vault, AWS Secrets Manager)
Chiffrer des tokens de bout en boutJWE (JSON Web Encryption) —— pas un JWT simple

Quand vous avez vraiment besoin d’un token chiffré : JWE et JOSE

Un JWT standard est signé (JWS), pas chiffré —— le payload est lisible. Si vous avez vraiment besoin de confidentialité des claims, utilisez un JWE (JSON Web Encryption, RFC 7516). JWE fait partie de la famille de standards JOSE :

  • Algorithmes JOSE —— chiffrement de contenu (par ex. A256GCM) et gestion des clés (par ex. RSA-OAEP-256, ECDH-ES, A256KW). « alg » choisit comment la clé de chiffrement de contenu est emballée ; « enc » choisit comment le payload lui-même est chiffré.
  • Emballage de clé —— JWE génère une clé de chiffrement de contenu fraîche par message et l’emballe sous la clé du destinataire (asymétrique ou symétrique). La clé emballée voyage dans l’en-tête du token. Ça permet de chiffrer le même texte clair pour différents destinataires sans rechiffrer le corps.
  • Forme compacte JWE —— cinq sections Base64url reliées par des points (header.key.iv.ciphertext.tag), visuellement comme un JWT mais avec quatre morceaux au lieu de trois.

Choisissez une bibliothèque éprouvée (jose, node-jose, python-jose) plutôt que d’implémenter JWE vous-même —— les combinaisons d’algorithmes et formats de clés sont subtiles, et la chute silencieuse vers des algorithmes faibles est un bug JOSE classique.

Un test rapide pour votre propre code

Cherchez dans votre base de code btoa(, atob( et Buffer.from(…, 'base64'). Pour chaque occurrence, demandez-vous :

  • Est-ce que je le fais pour que le texte rentre dans un champ ou survive au transport ? → Bien.
  • Est-ce que je le fais pour dissimuler des données à quelqu’un ? → Remplacez-le par du vrai chiffrement ou un contrôle d’accès.

Questions fréquentes

Base64 est-il du chiffrement ?

Non. Base64 est un encodage réversible sans clé —— n’importe qui peut le décoder en un appel (atob()). Le chiffrement nécessite une clé et rend infaisable la récupération du contenu sans elle.

Est-il sûr de stocker des mots de passe ou des clés d’API en Base64 ?

Non. Le décodage est trivial et les scanners de secrets décodent Base64 automatiquement. Utilisez un gestionnaire de secrets ou des variables d’environnement, et hachez les mots de passe avec bcrypt, scrypt ou Argon2.

N’importe qui peut-il lire le payload d’un JWT ?

Oui. Les payloads JWT sont encodés en Base64url et signés, pas chiffrés —— quiconque a le token peut lire tous les claims. Ne mettez jamais de secrets dans un JWT à moins d’utiliser JWE. Coller des tokens dans des outils en ligne est risqué ; voir pourquoi vous ne devriez pas coller du JSON sensible en ligne.

À quoi sert Base64 alors ?

Représenter des données binaires comme du texte de manière sûre —— URIs data:, pièces jointes d’e-mail (MIME), et transport sur des canaux qui ne gèrent que l’ASCII. C’est un emballage, pas une mesure de sécurité.

Encodez et décodez dans votre navigateur

Besoin d’inspecter une chaîne Base64 maintenant ? Encodage et décodage Base64 sur fixjson.org vous permet d’encoder ou de décoder n’importe quelle chaîne instantanément —— y compris Unicode complet et UTF-8 —— sans rien installer. Utile pour déboguer des payloads JWT, inspecter des réponses d’API ou voir ce qui se cache dans une URI data:.