Saw Tools

Base64 : tout ce qu'il faut savoir sur l'encodage

Fonctionnement byte par byte, variantes URL-safe et MIME, cas d'usage JWT et Data URI — et surtout pourquoi Base64 n'est pas du chiffrement.

Qu'est-ce que Base64 — et ce que ça n'est pas

Base64 est un schéma d'encodage, pas de chiffrement. Cette distinction est fondamentale et souvent mal comprise, y compris par des développeurs expérimentés. Encoder signifie transformer une représentation en une autre, de façon entièrement réversible et sans secret. Chiffrer signifie rendre des données illisibles sans une clé secrète. Base64 ne protège rien : n'importe qui peut décoder une chaîne Base64 en une fraction de seconde, sans mot de passe, sans clé, sans outil spécialisé.

La définition technique : Base64 est un encodage qui représente des données binaires arbitraires sous forme de texte ASCII en utilisant un alphabet de 64 caractères imprimables. Son objectif historique était de permettre le transport de données binaires (images, pièces jointes, exécutables) sur des canaux qui ne peuvent transmettre que du texte ASCII 7 bits — typiquement les protocoles e-mail des années 1980-1990.

Origine : MIME et la RFC 4648

Base64 est apparu dans le standard MIME (Multipurpose Internet Mail Extensions), formalisé dans la RFC 1521 en 1993, puis dans la RFC 2045. L'objectif était simple : les serveurs de messagerie de l'époque ne transmettaient fiablement que les caractères ASCII imprimables (codes 32 à 126). Une pièce jointe binaire — un fichier Word, une image JPEG — devait donc être convertie en texte avant d'être envoyée par email.

La spécification canonique de Base64 est aujourd'hui la RFC 4648 (2006), qui décrit également ses variantes Base64url, Base32 et Base16. C'est le document de référence que consultent les implémenteurs de bibliothèques cryptographiques, de parseurs JWT et de protocoles web.

Encodage vs chiffrement : le tableau de la confusion

Pour être précis sur la terminologie :

  • Encodage (Base64, URL encoding, UTF-8) : transformation réversible sans secret. N'importe qui peut inverser la transformation. Objectif : compatibilité de transport ou de représentation.
  • Chiffrement (AES-256, RSA, ChaCha20) : transformation réversible uniquement avec la bonne clé secrète. Objectif : confidentialité.
  • Hachage (SHA-256, bcrypt, Argon2) : transformation à sens unique, non réversible. Objectif : vérification d'intégrité ou stockage sécurisé de mots de passe.

Base64 appartient à la première catégorie. Le confondre avec du chiffrement est une erreur de sécurité grave — nous y reviendrons en détail.

Comment ça fonctionne, byte par byte

Le principe de Base64 repose sur une idée simple : regrouper les bits d'entrée en blocs de 6 bits, et représenter chaque bloc de 6 bits par un caractère dans un alphabet de 64 symboles (2⁶ = 64). Voici le mécanisme complet.

L'alphabet de 64 caractères

L'alphabet Base64 standard (RFC 4648 §4) est le suivant :

Index  0–25  : A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
Index 26–51  : a b c d e f g h i j k l m n o p q r s t u v w x y z
Index 52–61  : 0 1 2 3 4 5 6 7 8 9
Index 62     : +
Index 63     : /
Padding      : =

Soit 64 caractères ASCII imprimables qui ne posent pas de problème dans les protocoles textuels de l'époque. Le signe = est utilisé exclusivement comme remplissage (padding) en fin de chaîne.

Les groupes de 3 octets → 4 caractères

L'algorithme traite les données d'entrée par blocs de 3 octets (24 bits). Ces 24 bits sont découpés en 4 groupes de 6 bits, chacun converti en un caractère de l'alphabet. Exemple avec la lettre majuscule "M" (ASCII 77 = 0x4D = binaire 01001101) suivie de "a" (ASCII 97 = 0x61 = 01100001) et "n" (ASCII 110 = 0x6E = 01101110) :

M          a          n
01001101   01100001   01101110
└──────────────────────────────┘ 24 bits groupés
 010011  010110  000101  101110
   19      22       5      46
    T       W       F       u
→ "TWFu"

C'est le résultat canonique : btoa("Man") en JavaScript retourne "TWFu". On peut le vérifier immédiatement dans notre outil d'encodage Base64.

Encodons "Bonjour" octet par octet

Prenons le mot "Bonjour" en ASCII (7 octets) :

B=66  o=111  n=110  j=106  o=111  u=117  r=114

Groupe 1 : B(66)   o(111)  n(110)
  Binaire : 01000010 01101111 01101110
  6-bits  : 010000 100110 111101 101110
  Index   : 16     38     61     46
  Chars   :  Q      m      9      u   → "Qm9u"

Groupe 2 : j(106)  o(111)  u(117)
  Binaire : 01101010 01101111 01110101
  6-bits  : 011010 100110 111101 110101
  Index   : 26     38     61     53
  Chars   :  a      m      9      1   → "am91"

Groupe 3 : r(114)  [1 octet seulement → padding]
  Binaire : 01110010
  Complété: 01110010 00000000
  6-bits  : 011100 100000 [padding] [padding]
  Index   : 28     32
  Chars   :  c      g      =      =  → "cg=="

Résultat final : "Qm9uam91cg=="

Vérification : atob("Qm9uam91cg==") dans n'importe quelle console JavaScript retourne "Bonjour".

Le padding avec =

Lorsque le nombre d'octets en entrée n'est pas un multiple de 3, le dernier bloc est incomplet. Base64 ajoute des zéros pour compléter, et marque les positions inutilisées avec le caractère = :

  • Entrée de 1 octet restant (ex : 1 octet) → 2 caractères Base64 + ==
  • Entrée de 2 octets restants → 3 caractères Base64 + =
  • Entrée multiple de 3 → aucun padding

Le padding permet au décodeur de savoir exactement combien d'octets étaient dans le dernier bloc. Certaines variantes (notamment Base64url) omettent le padding — le décodeur doit alors inférer la longueur à partir de la longueur totale de la chaîne modulo 4.

Variantes : standard, URL-safe, MIME

La RFC 4648 définit plusieurs alphabets selon les contextes. La logique est toujours la même (groupes de 6 bits), seuls les caractères pour les index 62 et 63 changent.

Base64 standard (RFC 4648 §4)

Index 62 = +, index 63 = /. C'est la variante historique, celle que vous trouvez dans les certificats PEM, les pièces jointes MIME, et la fonction btoa() des navigateurs. Le problème de + et / : ces deux caractères ont une signification spéciale dans les URLs. Le + représente un espace dans l'encodage de formulaires (application/x-www-form-urlencoded), et le / est un séparateur de chemin. Placer du Base64 standard dans une URL sans ré-encodage URL-encode est une source de bugs courants.

Base64url (RFC 4648 §5)

Index 62 = -, index 63 = _. Ces deux caractères sont sûrs dans les URLs et les noms de fichiers. Le padding = est généralement omis (il peut être confondu avec un séparateur de paramètre dans certains contextes). C'est la variante utilisée par :

  • JWT (JSON Web Tokens, RFC 7519) — les trois segments header, payload et signature sont encodés en Base64url
  • OAuth 2.0 et PKCE (Proof Key for Code Exchange)
  • WebAuthn / FIDO2 — les identifiants de credential
  • Les paramètres d'URL contenant des données binaires (tokens, nonces)

MIME Base64 (RFC 2045)

Utilise le même alphabet que le Base64 standard, mais ajoute une contrainte de formatage : retour à la ligne tous les 76 caractères (CRLF). Cette limite de ligne existait pour la compatibilité avec les anciens MUA (Mail User Agents) qui traitaient les lignes de façon séquentielle. Vous la retrouvez dans :

  • Les pièces jointes d'emails encodées en Content-Transfer-Encoding: base64
  • Les fichiers .pem (certificats X.509, clés RSA) qui utilisent 64 colonnes par convention
  • Les fichiers MIME multiparts

Note importante : lors du décodage de Base64 MIME, les retours à la ligne doivent être ignorés. Certaines bibliothèques le font automatiquement ; d'autres non. C'est un piège fréquent.

Cas d'usage légitimes de Base64

Base64 résout des problèmes réels. Voici les cas d'usage principaux, avec leur justification technique.

Data URI : images et ressources inline en HTML/CSS

Le format Data URI (RFC 2397) permet d'embarquer directement des fichiers binaires dans le HTML ou le CSS :

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...">

Ou en CSS :

.icon {
    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0i...");
}

C'est utile pour les petites icônes (évite une requête HTTP supplémentaire), mais contre-productif pour les images volumineuses (les navigateurs ne peuvent pas mettre en cache séparément une ressource inline, et le surcoût de 33 % grossit le HTML lui-même). La règle empirique : Data URI pertinent en dessous de 2-4 Ko.

JWT (JSON Web Tokens)

Un JWT est structuré en trois parties séparées par des points : header.payload.signature. Chaque partie est un objet JSON encodé en Base64url. L'avantage : le token est un texte opaque transportable dans un header HTTP (Authorization: Bearer <token>), un cookie, ou un paramètre d'URL, sans problème de caractères spéciaux.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0
.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Décodez le header : {"alg":"HS256","typ":"JWT"}. Décodez le payload : {"sub":"1234567890","name":"John Doe"}. Ces données ne sont pas secrètes — elles sont simplement encodées. Le secret est dans la signature, qui vérifie que le contenu n'a pas été altéré. N'y mettez jamais un mot de passe ou une donnée que l'utilisateur ne doit pas voir.

Authentification HTTP Basic

Le schéma HTTP Basic Auth (RFC 7617) encode les identifiants en Base64 dans le header Authorization :

Authorization: Basic dXNlcjpwYXNzd29yZA==

Ici, dXNlcjpwYXNzd29yZA== est le Base64 de user:password. Il n'y a aucune sécurité intrinsèque : quiconque intercepte ce header peut décoder les identifiants immédiatement. Basic Auth n'est acceptable que sur HTTPS, jamais en HTTP clair.

Certificats PEM et clés cryptographiques

Les certificats X.509, les clés RSA/ECDSA, les CSR (Certificate Signing Request) sont tous des structures binaires DER (Distinguished Encoding Rules). Le format PEM (Privacy-Enhanced Mail) les enveloppe en Base64 avec des marqueurs lisibles :

-----BEGIN CERTIFICATE-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2a2rwplB...
-----END CERTIFICATE-----

Le nom "PEM" est un héritage historique — les fichiers PEM ne sont plus liés au protocole Privacy-Enhanced Mail, mais la convention de format est restée. OpenSSL, Let's Encrypt et tous les serveurs web modernes utilisent ce format.

API tokens et sérialisation binaire dans JSON

JSON est un format texte : il ne peut pas représenter des données binaires nativement. Pour inclure une image, une signature cryptographique ou un hash binaire dans une réponse JSON, Base64 est la solution standard :

{
    "user_id": "abc123",
    "avatar": "data:image/jpeg;base64,/9j/4AAQSkZJRgAB...",
    "signature": "3q2+7w=="
}

C'est également le cas pour les réponses d'API AWS, Google Cloud, et de nombreuses APIs REST qui retournent des données binaires (images générées, fichiers exportés).

Pièces jointes email MIME

L'encodage MIME d'une pièce jointe ressemble à :

Content-Type: application/pdf; name="facture.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="facture.pdf"

JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZwov
UGFnZXMgMiAwIFIKPj4KZW5kb2JqCjIgMCBvYmoKPDwKL1R5cGUgL1Bh
Z2VzCi9LaWRzIFszIDAgUl0KL0NvdW50IDEKPj4KZW5kb2JqCg==

C'est le même contenu binaire du PDF, représenté en texte pour passer les anciens relais SMTP.

Le piège majeur : pourquoi Base64 n'est pas de la sécurité

C'est le point le plus important de ce guide, et celui que le web documente le moins clairement. Base64 est complètement transparent : décoder une chaîne Base64 prend une ligne de code dans n'importe quel langage et zéro connaissance préalable. Pourtant, on retrouve régulièrement Base64 utilisé comme mécanisme de protection dans des applications en production.

Exemples concrets de mauvaises pratiques

Cas 1 — Mot de passe en Base64 dans un fichier de configuration :

# config.yml — NE JAMAIS FAIRE ÇA
database:
    host: db.example.com
    password: cGFzc3dvcmQxMjM=   # "password123" encodé en Base64

N'importe quel développeur qui clone le dépôt, n'importe quel attaquant qui accède au fichier de config, peut décoder cela immédiatement. Le fait que ce ne soit pas du texte clair ne procure aucune sécurité — c'est de l'obfuscation, pas du chiffrement.

Cas 2 — "Chiffrement" de données sensibles en Base64 dans une base de données :

-- Dans une table users, colonne "ssn" (numéro de sécurité sociale)
-- Certaines applis stockent : base64_encode("123-45-6789")
-- Résultat : "MTIzLTQ1LTY3ODk="
-- Protection réelle : aucune

Cas 3 — Token d'API "sécurisé" par Base64 :

// Header envoyé par certaines applis mal conçues
X-Api-Key: dXNlcjEyMzpzZWNyZXQ0NTY=
// Décodage immédiat : "user123:secret456"

Cas 4 — Malware et obfuscation : les scripts malveillants utilisent souvent Base64 pour cacher leur code au premier regard, sachant que les outils de détection de signature textuelle ne les détecteront pas directement. Exemple classique :

eval(atob("dmFyIHggPSBkb2N1bWVudC5jb29raWU7..."));

Ce n'est pas sécurisé pour l'attaquant — les sandboxes et antivirus modernes décodent et analysent le Base64. Mais ça trompait les outils de détection basiques des années 2010.

Ce que vous devez utiliser à la place

Si vous avez besoin de confidentialité : utilisez du chiffrement authentifié (AES-256-GCM, ChaCha20-Poly1305). Pour stocker des secrets dans une config : utilisez des variables d'environnement, un gestionnaire de secrets (HashiCorp Vault, AWS Secrets Manager, Doppler), ou à défaut un fichier chiffré avec git-crypt ou sops.

Si vous avez besoin de vérification d'intégrité : utilisez une signature HMAC-SHA256 ou une signature asymétrique (Ed25519, RSA-PSS). C'est exactement ce que fait la troisième partie d'un JWT.

Si vous avez besoin de stocker un mot de passe : utilisez Argon2id, bcrypt ou scrypt — des fonctions de hachage lentes conçues pour rendre les attaques par force brute coûteuses. Consultez notre générateur de mots de passe pour comprendre ce qu'est un mot de passe solide, et combien la solidité dépend de l'algorithme de stockage utilisé côté serveur.

Performance et taille : l'overhead de 33 %

La conséquence directe du ratio 3 octets → 4 caractères est une augmentation de taille de 33 % (précisément : 4/3 − 1 ≈ 0,333). En pratique, avec le padding et les retours à la ligne MIME, le surcoût réel est souvent de 36-37 %.

Impact sur la bande passante et le cache

Pour les Data URI HTML/CSS, ce surcoût a des conséquences directes :

  • Une image de 50 Ko embarquée en Data URI dans le CSS alourdit le CSS d'environ 68 Ko.
  • Ce CSS plus lourd est rechargé à chaque visite si le cache est invalidé.
  • Une image référencée par URL bénéficie d'un cache HTTP indépendant et peut être partagée entre plusieurs pages.

En compression : le Base64 se compresse très bien avec gzip/brotli (il contient peu d'entropie par rapport aux données originales). En pratique, le surcoût après compression tombe souvent à 10-15 %. La plupart des serveurs web modernes compriment automatiquement le HTML/CSS/JS, donc l'impact réel sur le réseau est atténué. Mais le surcoût de parsing et de décodage côté navigateur reste réel.

Quand utiliser vs ne pas utiliser les Data URI

Utilisez les Data URI pour :

  • Les petites icônes SVG inline (moins de 2 Ko)
  • Les sprites CSS très petits
  • Les images critiques au-dessus de la ligne de flottaison dont vous voulez éviter le flash de chargement

Évitez les Data URI pour :

  • Toute image de plus de 5 Ko (le surcoût de taille dépasse le gain de la requête HTTP évitée)
  • Les images répétées sur plusieurs pages (impossible à mettre en cache séparément)
  • Les logos et images de marque (le chargement paresseux avec des URLs normales est plus efficace)

Pièges courants en développement

Base64 paraît simple à l'usage, mais recèle plusieurs pièges qui provoquent des bugs subtils, souvent difficiles à diagnostiquer.

UTF-8 vs Latin-1 : le bug d'encodage de caractères

C'est le piège le plus fréquent. La fonction btoa() des navigateurs n'accepte que des chaînes contenant des caractères Latin-1 (codes 0-255). Encoder une chaîne contenant des caractères Unicode hors de cette plage provoque une exception :

// Fonctionne (ASCII pur)
btoa("Hello World")  // → "SGVsbG8gV29ybGQ="

// Provoque une erreur : InvalidCharacterError
btoa("Héllo")  // É = U+00C9, hors ASCII 7 bits mais dans Latin-1... OK
btoa("こんにちは")  // Caractères japonais : ERREUR

La solution correcte pour encoder du texte Unicode en Base64 dans un navigateur :

// Méthode moderne (navigateurs récents)
function base64EncodeUnicode(str) {
    const bytes = new TextEncoder().encode(str);
    const binString = String.fromCodePoint(...bytes);
    return btoa(binString);
}

// Méthode classique
function base64EncodeUnicode(str) {
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
        (match, p1) => String.fromCharCode('0x' + p1)
    ));
}

En Python, le problème est différent : base64.b64encode() attend des bytes, pas une str. Il faut encoder explicitement la chaîne avant :

import base64

# Incorrect (TypeError en Python 3)
base64.b64encode("Bonjour")

# Correct : encoder la chaîne en UTF-8 d'abord
base64.b64encode("Bonjour".encode("utf-8"))
# → b'Qm9uam91cg=='

# Décoder
base64.b64decode(b"Qm9uam91cg==").decode("utf-8")
# → "Bonjour"

Différences entre langages : tableau de référence

Chaque langage a son API Base64, avec ses particularités :

# Python 3
import base64
encoded = base64.b64encode(b"data")          # Standard
url_safe = base64.urlsafe_b64encode(b"data") # URL-safe (- et _)
decoded = base64.b64decode(encoded)

// JavaScript (Navigateur)
const encoded = btoa("data");          // Standard, Latin-1 uniquement
const decoded = atob(encoded);
// Base64url : pas de fonction native, utiliser une lib ou remplacer + → - et / → _

// Node.js
const buf = Buffer.from("data", "utf8");
const encoded = buf.toString("base64");       // Standard
const urlSafe = buf.toString("base64url");    // URL-safe (Node 16+)
const decoded = Buffer.from(encoded, "base64").toString("utf8");

// PHP
$encoded = base64_encode("data");     // Standard
$decoded = base64_decode($encoded);
// URL-safe : strtr(base64_encode($data), '+/', '-_')

// Go
import "encoding/base64"
encoded := base64.StdEncoding.EncodeToString([]byte("data"))
urlSafe := base64.URLEncoding.EncodeToString([]byte("data"))

// Java
import java.util.Base64;
String encoded = Base64.getEncoder().encodeToString("data".getBytes());
String urlSafe = Base64.getUrlEncoder().encodeToString("data".getBytes());

Base64 vs URL encoding : ne pas confondre

Une confusion fréquente oppose Base64 et l'encodage URL (percent-encoding, RFC 3986). Ce sont deux choses différentes avec des objectifs différents :

  • URL encoding (%XX) : encode les caractères interdits dans les URLs en les remplaçant par leur code hexadécimal précédé d'un %. S'applique à des chaînes de texte. Exemple : "Hello World""Hello%20World".
  • Base64 : encode des données binaires en texte ASCII. S'applique à n'importe quelle suite d'octets. Exemple : un fichier PNG → une chaîne de caractères imprimables.

On peut appliquer les deux séquentiellement : pour transporter du Base64 dans une URL, il faut parfois URL-encoder les caractères + et / (ou utiliser directement Base64url qui les évite). Notre générateur de QR code utilise d'ailleurs les deux encodages : les données texte sont URL-encodées pour le contenu du QR, et l'image QR résultante peut être exportée en Data URI Base64.

Valider une chaîne Base64 avant décodage

Toujours valider la chaîne reçue avant de tenter de la décoder, pour éviter les exceptions et les données corrompues. L'expression régulière de validation pour Base64 standard :

// JavaScript
const isValidBase64 = (str) => /^[A-Za-z0-9+/]+={0,2}$/.test(str)
    && str.length % 4 === 0;

// Python
import re
def is_valid_base64(s):
    return bool(re.fullmatch(r'[A-Za-z0-9+/]*={0,2}', s)) and len(s) % 4 == 0

Pour Base64url (sans padding obligatoire) :

// JavaScript
const isValidBase64url = (str) => /^[A-Za-z0-9_-]+$/.test(str);

Note : une chaîne qui passe la regex n'est pas nécessairement un Base64 signifiant — elle est simplement bien formée syntaxiquement. Le décodage peut encore produire des données qui ne représentent pas ce que vous attendez.

Sécurité et bonnes pratiques

Voici les règles à respecter systématiquement lorsque vous travaillez avec Base64.

1. Toujours expliciter le charset

Quand vous encodez du texte (pas des données binaires pures) en Base64, précisez explicitement l'encodage de caractères utilisé — presque toujours UTF-8. Sans cette précision, des développeurs travaillant sur différents systèmes ou langages peuvent obtenir des résultats différents pour le même texte si leur système par défaut est ISO-8859-1, Windows-1252, ou autre.

# Pratique : documenter et fixer l'encodage
data = "Données avec des accents : éàü"
encoded = base64.b64encode(data.encode("utf-8"))
# Toujours décoder avec le même charset
decoded = base64.b64decode(encoded).decode("utf-8")

2. Ne jamais utiliser Base64 pour cacher des secrets

Toute donnée encodée en Base64 doit être considérée comme publique. Si vous ne pouvez pas montrer la donnée en clair, vous ne devez pas non plus la montrer en Base64. Les conséquences pratiques :

  • Ne jamais committer une clé API, un mot de passe ou un secret encodé en Base64 dans un dépôt git — même privé.
  • Ne jamais stocker des données sensibles en Base64 dans un cookie ou localStorage sans chiffrement préalable.
  • Lors d'un audit de sécurité, toujours décoder les valeurs Base64 suspicieuses trouvées dans des configs, des headers ou des tokens.

3. Méfiez-vous des injections via Base64 décodé

Si votre application décode du Base64 reçu de l'utilisateur et utilise le résultat dans une requête SQL, une commande shell, ou un parseur XML/HTML, vous êtes vulnérable aux injections. Le Base64 est une enveloppe de transport, pas un filtre de sécurité. Toujours valider et assainir les données après décodage, jamais avant.

// Mauvais : valider le Base64 ne protège pas contre les injections SQL
const username = atob(req.query.user); // "admin'--" est du Base64 valide
db.query(`SELECT * FROM users WHERE name = '${username}'`); // FAILLE SQL

// Correct : préparer et paramétrer la requête après décodage
const username = atob(req.query.user);
db.query("SELECT * FROM users WHERE name = ?", [username]);

4. Choisir la bonne variante selon le contexte

Règle simple :

  • Dans une URL ou un JWT → Base64url (- et _, sans padding)
  • Dans un email MIME ou un certificat PEM → MIME Base64 (avec retours à la ligne)
  • Partout ailleurs (JSON, stockage, API) → Base64 standard

5. Longueur attendue et vérification

La longueur d'une chaîne Base64 correctement paddée est toujours un multiple de 4. La formule pour calculer la longueur attendue : ceil(n / 3) * 4 caractères pour n octets en entrée. Si une chaîne Base64 reçue n'a pas une longueur multiple de 4 (et n'est pas en Base64url sans padding), c'est un indicateur de troncature ou de corruption.

Conclusion : Base64, un outil de transport, pas de protection

Base64 est un outil de 1993 qui répond toujours à son besoin initial avec une efficacité remarquable : transporter des données binaires sur des canaux textuels. En 2026, il est omniprésent dans le web moderne — JWT, Data URI, APIs REST, certificats TLS, WebAuthn. Comprendre son fonctionnement interne (groupes de 6 bits, alphabet de 64 symboles, overhead 4/3) permet d'éviter les deux catégories d'erreurs les plus courantes : les bugs d'encodage de caractères (UTF-8 vs Latin-1) et la confusion dangereuse avec du chiffrement.

La règle d'or reste : Base64 = visibilité, pas sécurité. Toute donnée que vous ne pouvez pas montrer en clair ne doit pas être simplement encodée en Base64 — elle doit être chiffrée avec un algorithme approprié, protégée par des contrôles d'accès, ou hachée de façon irréversible.

Vous pouvez tester tous les concepts de ce guide directement dans notre outil d'encodage et décodage Base64 — il gère le Base64 standard, l'URL-safe, et les variantes avec ou sans padding. Pour aller plus loin sur la sécurité des données en transit, consultez également notre générateur de mots de passe et notre générateur de QR code qui met en pratique plusieurs des encodages décrits ici.

Questions fréquentes

Pourquoi mon Base64 fait-il 33 % de plus que l'original ?

Base64 regroupe les octets par paquets de 3 et les représente avec 4 caractères ASCII. Trois octets (24 bits) deviennent 4 caractères (32 bits), soit un overhead de 4/3 ≈ 1,333. Une image de 100 Ko encodée en Base64 pèsera environ 136 Ko. Ce surcoût est inévitable : c'est le prix à payer pour représenter des données binaires dans un alphabet textuel de 64 symboles.

Base64 vs hexadécimal : quand utiliser lequel ?

L'hexadécimal représente chaque octet par 2 caractères (overhead de 100 %), Base64 avec 1,33 caractère en moyenne (overhead 33 %). Base64 est donc plus compact. L'hex est plus lisible pour déboguer des données courtes (hash SHA-256, adresses mémoire) car chaque nibble correspond directement. Pour transporter des données binaires volumineuses (images, certificats, clés), préférez Base64. Pour afficher un hash ou une signature, l'hex est plus pratique.

Pourquoi mon JWT contient-il des points (.) entre les segments Base64 ?

Un JWT (JSON Web Token) est structuré en trois parties séparées par des points : header.payload.signature. Chaque partie est encodée indépendamment en Base64url (variante sans + ni /, avec - et _ à la place, et sans padding =). Les points servent de délimiteurs fixes entre les trois segments. C'est une convention de format définie dans la RFC 7519, pas une particularité de Base64 lui-même.

Mon Base64 contient des espaces ou des retours à la ligne : est-ce normal ?

Oui, dans le contexte MIME (emails, certificats PEM). La RFC 2045 impose un retour à la ligne tous les 76 caractères pour la compatibilité avec les anciens systèmes. Un certificat .pem commence par -----BEGIN CERTIFICATE----- et contient du Base64 sur 64 colonnes. Si vous décodez du Base64 provenant d'un email ou d'un certificat, retirez les espaces et sauts de ligne avant décodage, ou utilisez une bibliothèque qui le gère automatiquement.

Base64 standard vs URL-safe : comment savoir lequel utiliser ?

La règle est simple : si votre Base64 transite dans une URL (paramètre GET, segment de chemin, cookie) ou dans un contexte JSON/JWT, utilisez Base64url (RFC 4648 §5) avec - à la place de + et _ à la place de /. Si vous encodez pour un email MIME, un certificat PEM ou un contexte purement textuel hors URL, utilisez le Base64 standard. Les deux sont identiques sauf pour ces deux caractères et le padding facultatif en Base64url.