Pourquoi utilisons-nous Base64?

276

Wikipédia dit

Les schémas de codage Base64 sont couramment utilisés lorsqu'il est nécessaire de coder des données binaires qui doivent être stockées et transférées sur des supports conçus pour traiter des données textuelles. Il s'agit de garantir que les données restent intactes sans modification pendant le transport.

Mais n'est-ce pas que les données sont toujours stockées / transmises en binaire parce que la mémoire que nos machines ont stockent en binaire et cela dépend juste de la façon dont vous les interprétez? Donc, que vous encodiez le modèle de bits 010011010110000101101110comme Manen ASCII ou comme TWFuen Base64, vous allez éventuellement stocker le même modèle de bits.

Si le codage ultime est en termes de zéros et de uns et que chaque machine et support peut les gérer, comment est-ce important si les données sont représentées en ASCII ou en Base64?

Qu'est-ce que cela signifie «des supports conçus pour traiter des données textuelles»? Ils peuvent gérer le binaire => ils peuvent gérer n'importe quoi.


Merci à tous, je pense que je comprends maintenant.

Lorsque nous envoyons des données, nous ne pouvons pas être sûrs que les données seront interprétées dans le même format que nous le souhaitions. Ainsi, nous envoyons des données codées dans un certain format (comme Base64) que les deux parties comprennent. De cette façon, même si l'expéditeur et le destinataire interprètent les mêmes choses différemment, mais parce qu'ils s'accordent sur le format codé, les données ne seront pas interprétées incorrectement.

De l' exemple de Mark Byers

Si je veux envoyer

Hello
world!

Une façon est de l'envoyer en ASCII comme

72 101 108 108 111 10 119 111 114 108 100 33

Mais l'octet 10 pourrait ne pas être interprété correctement comme une nouvelle ligne à l'autre extrémité. Donc, nous utilisons un sous-ensemble de ASCII pour le coder comme ceci

83 71 86 115 98 71 56 115 67 110 100 118 99 109 120 107 73 61 61

qui, au prix de plus de données transférées pour la même quantité d'informations, garantit que le récepteur peut décoder les données de la manière prévue, même s'il se trouve que le récepteur a des interprétations différentes pour le reste du jeu de caractères.

Lazer
la source
6
Contexte historique: les serveurs de messagerie étaient auparavant ASCII 7 bits. Beaucoup d'entre eux mettaient le bit haut à 0, donc vous ne deviez envoyer que des valeurs 7 bits. Voir en.wikipedia.org/wiki/Email#Content_encoding
Harold L
53
Nous utilisons base64 car il est plus lisible que Perl
Martin
2
@Martin, vous plaisantez. Perl est difficile à lire, mais base64 est illisible du tout.
Peter Long
1
@Lazer Votre image manque
Mick
2
@Lazer, "Mais l'octet 10 pourrait ne pas être interprété correctement comme une nouvelle ligne à l'autre bout." Pourquoi? les deux parties se sont entendues sur l'ASCII et elles doivent l'interpréter correctement!
ProgramCpp

Réponses:

299

Votre première erreur est de penser que l'encodage ASCII et l'encodage Base64 sont interchangeables. Ils ne sont pas. Ils sont utilisés à des fins différentes.

  • Lorsque vous encodez du texte en ASCII, vous commencez par une chaîne de texte et le convertissez en une séquence d'octets.
  • Lorsque vous encodez des données en Base64, vous commencez par une séquence d'octets et les convertissez en chaîne de texte.

Pour comprendre pourquoi Base64 était nécessaire en premier lieu, nous avons besoin d'un petit historique de l'informatique.


Les ordinateurs communiquent en binaire - 0 et 1 - mais les gens veulent généralement communiquer avec des données de formulaires plus riches telles que du texte ou des images. Afin de transférer ces données entre ordinateurs, elles doivent d'abord être encodées en 0 et 1, envoyées, puis décodées à nouveau. Pour prendre le texte comme exemple - il existe de nombreuses façons différentes d'effectuer cet encodage. Ce serait beaucoup plus simple si nous pouvions tous nous mettre d'accord sur un seul encodage, mais malheureusement ce n'est pas le cas.

À l'origine, de nombreux codages différents ont été créés (par exemple le code Baudot ) qui utilisaient un nombre différent de bits par caractère jusqu'à ce que l'ASCII devienne finalement une norme avec 7 bits par caractère. Cependant, la plupart des ordinateurs stockent des données binaires en octets composés de 8 bits chacun, donc ASCII ne convient pas pour transférer ce type de données. Certains systèmes effaceraient même le bit le plus significatif. De plus, la différence de codage de fin de ligne entre les systèmes signifie que les caractères ASCII 10 et 13 ont également parfois été modifiés.

Pour résoudre ces problèmes, le codage Base64 a été introduit. Cela vous permet de coder des octets aribtraires en octets connus pour être envoyés en toute sécurité sans être corrompus (caractères alphanumériques ASCII et quelques symboles). L'inconvénient est que le codage du message à l'aide de Base64 augmente sa longueur - tous les 3 octets de données sont codés en 4 caractères ASCII.

Pour envoyer du texte fiable , vous pouvez d' abord encoder en octets en utilisant un codage de texte de votre choix (par exemple UTF-8), puis par la suite base64 encode les données binaires résultant en une chaîne de texte qui est sûr à envoyer codé en ASCII. Le destinataire devra inverser ce processus pour récupérer le message d'origine. Cela nécessite bien sûr que le récepteur sache quels codages ont été utilisés, et cette information doit souvent être envoyée séparément.

Historiquement, il a été utilisé pour coder des données binaires dans des messages électroniques où le serveur de messagerie pouvait modifier les fins de ligne. Un exemple plus moderne est l'utilisation de l'encodage Base64 pour incorporer des données d'image directement dans le code source HTML . Ici, il est nécessaire de coder les données pour éviter que des caractères comme «<» et «>» soient interprétés comme des balises.


Voici un exemple de travail:

Je souhaite envoyer un SMS avec deux lignes:

Bonjour
monde!

Si je l'envoie en ASCII (ou UTF-8), cela ressemblera à ceci:

72 101 108 108 111 10 119 111 114 108 100 33

L'octet 10 est corrompu dans certains systèmes afin que nous puissions coder en base 64 ces octets sous forme de chaîne Base64:

SGVsbG8sCndvcmxkIQ ==

Qui, une fois encodé en ASCII, ressemble à ceci:

83 71 86 115 98 71 56 115 67 110 100 118 99 109 120 107 73 61 61

Tous les octets ici sont des octets sûrs connus, il y a donc très peu de chances qu'un système endommage ce message. Je peux l'envoyer à la place de mon message d'origine et laisser le destinataire inverser le processus pour récupérer le message d'origine.

Mark Byers
la source
4
"la plupart des protocoles de communication modernes ne corrompent pas les données" - bien que, par exemple, le courrier électronique puisse le faire, avec un agent de livraison remplaçant la chaîne de caractères "\ nDe" par "\ n> De" lorsqu'il enregistre le message dans une boîte aux lettres. Ou les en-têtes HTTP sont terminés par une nouvelle ligne sans moyen réversible d'échapper aux nouvelles lignes dans les données (la continuation de la ligne confond les espaces blancs), vous ne pouvez donc pas simplement y déverser de l'ASCII arbitraire. base64 est mieux que juste sécurité 7 bits, il est alphanumérique et - = + / sécurité.
Steve Jessop
1
"L'inconvénient est que le codage du message à l'aide de Base64 augmente sa longueur - tous les 3 octets de données sont codés à 4 octets." Comment passe-t-il à 4 octets? Ne sera-t-il toujours pas 3 * 8 = 24 bits seulement?
Lazer
4
@Lazer: non. Regardez votre propre exemple - "Man" est codé en base 64 comme "TWFu". 3 octets -> 4 octets. C'est parce que l'entrée est autorisée à être l'un des 2 ^ 8 = 256 octets possibles, tandis que la sortie n'en utilise que 2 ^ 6 = 64 (et =, pour aider à indiquer la longueur des données). 8 bits par quartet de sortie sont "gaspillés", afin d'empêcher la sortie de contenir des caractères "excitants" même si l'entrée le fait.
Steve Jessop
3
Il peut être utile de reformuler «Lorsque vous encodez des données en Base64, vous commencez avec une séquence d'octets et les convertissez en chaîne de texte» comme «Lorsque vous encodez des données en Base64, vous commencez avec une séquence d'octets et les convertissez en un séquence d'octets constituée uniquement de valeurs ASCII ". Une séquence d'octets composée uniquement de caractères ASCII est ce qui est requis par SMTP, c'est pourquoi Base64 (et imprimable entre guillemets) est utilisé comme encodage de transfert de contenu. Excellent aperçu!
ALEXintlsos
1
Je voterais, mais dispose de 64 voix. Désolé, c'est parfait.
Jessé Catrinck
61

Encodage de données binaires en XML

Supposons que vous souhaitiez incorporer quelques images dans un document XML. Les images sont des données binaires, tandis que le document XML est du texte. Mais XML ne peut pas gérer les données binaires intégrées. Alors comment tu fais?

Une option consiste à coder les images en base64, transformant les données binaires en texte que XML peut gérer.

Au lieu de:

<images>
  <image name="Sally">{binary gibberish that breaks XML parsers}</image>
  <image name="Bobby">{binary gibberish that breaks XML parsers}</image>
</images>

tu fais:

<images>
  <image name="Sally" encoding="base64">j23894uaiAJSD3234kljasjkSD...</image>
  <image name="Bobby" encoding="base64">Ja3k23JKasil3452AsdfjlksKsasKD...</image>
</images>

Et l'analyseur XML pourra analyser correctement le document XML et extraire les données d'image.

yfeldblum
la source
C'est peut-être ainsi que fonctionne l'ancien .mhtformat de Microsoft (fichier html + images dans un seul fichier).
Sridhar Sarnobat
38

Pourquoi ne pas regarder la RFC qui définit actuellement Base64 ?

Le codage de base des données est utilisé dans de nombreuses situations pour stocker ou transférer des
données dans des environnements qui, peut-être pour des raisons héritées, sont limités aux données US-ASCII [1]. Le codage de base peut également être utilisé dans de nouvelles applications qui n'ont pas de restrictions héritées, tout simplement parce qu'il permet de manipuler des objets avec des éditeurs de texte.

Dans le passé, différentes applications ont eu des exigences différentes et ont donc parfois implémenté des encodages de base de manières légèrement différentes. Aujourd'hui, les spécifications de protocole utilisent parfois des codages de base en général, et "base64" en particulier, sans description ni référence précise. Les extensions MIME (Multipurpose Internet Mail Extensions) [4] sont souvent utilisées comme référence pour la base64 sans tenir compte des conséquences pour le retour à la ligne ou les caractères non alphabétiques. Le but de cette spécification est d'établir des considérations communes sur l'alphabet et le codage. Nous espérons que cela réduira l'ambiguïté dans d'autres documents, conduisant à une meilleure interopérabilité.

Base64 a été conçu à l'origine pour permettre de joindre des données binaires à des e-mails dans le cadre des extensions de messagerie Internet polyvalentes.

Billy ONeal
la source
26

Les supports conçus pour les données textuelles sont bien entendu éventuellement binaires également, mais les supports textuels utilisent souvent certaines valeurs binaires pour les caractères de contrôle. De plus, les supports textuels peuvent rejeter certaines valeurs binaires comme non textuelles.

Le codage Base64 code les données binaires en tant que valeurs qui ne peuvent être interprétées que comme du texte dans les supports textuels, et est exempt de tout caractère spécial et / ou caractère de contrôle, de sorte que les données seront également préservées sur les supports textuels.

Håvard S
la source
Donc, comme avec Base64, la source et la destination interpréteront les données de la même manière, car elles interpréteront probablement ces 64 caractères de la même manière, même si elles interprètent les caractères de contrôle de différentes manières. Est-ce correct?
Lazer
6
Ces données peuvent même être détruites en transit. Par exemple, de nombreux programmes FTP réécrivent les fins de ligne de 13,10 à 10 ou vice versa si le système d'exploitation du serveur et du client ne correspondent pas et que le transfert est signalé comme mode texte. FTP n'est que le premier exemple qui m'est venu à l'esprit, ce n'est pas un bon parce que FTP prend en charge un mode binaire.
Hendrik Brummermann
@nhnb: Je pense que FTP est un bel exemple car il montre que le mode texte ne convient pas aux choses qui veulent des données binaires.
jamesdlin
Qu'est-ce qu'un média textuel?
Koray Tugay
18

C'est plus que le média valide le codage des chaînes, donc nous voulons nous assurer que les données sont acceptables par une application de gestion (et ne contiennent pas de séquence binaire représentant EOL par exemple)

Imaginez que vous souhaitez envoyer des données binaires dans un e-mail avec encodage UTF-8 - L'e-mail peut ne pas s'afficher correctement si le flux de uns et de zéros crée une séquence qui n'est pas Unicode valide dans l'encodage UTF-8.

Le même type de chose se produit dans les URL lorsque nous voulons encoder des caractères non valides pour une URL dans l'URL elle-même:

http://www.foo.com/hello mon ami -> http://www.foo.com/hello%20my%20friend

C'est parce que nous voulons envoyer un espace sur un système qui pensera que l'espace est malodorant.

Tout ce que nous faisons, c'est de nous assurer qu'il existe un mappage 1 à 1 entre une séquence de bits connue, acceptable et non préjudiciable à une autre séquence littérale de bits, et que l'application de gestion ne distingue pas le codage.

Dans votre exemple, manpeut être ASCII valide en première forme; mais souvent, vous souhaiterez peut-être transmettre des valeurs binaires aléatoires (c'est-à-dire envoyer une image dans un e-mail):

Version MIME: 1.0
Description du contenu: "Encodage Base64 de a.gif"
Type de contenu: image / gif; name = "a.gif"
Content-Transfer-Encoding: Base64
Content-Disposition: pièce jointe; filename = "a.gif"

Ici, nous voyons qu'une image GIF est encodée en base64 comme un morceau d'un e-mail. Le client de messagerie lit les en-têtes et les décode. En raison de l'encodage, nous pouvons être sûrs que le GIF ne contient rien qui puisse être interprété comme un protocole et nous évitons d'insérer des données que SMTP ou POP peuvent trouver importantes.

Aiden Bell
la source
1
C'est génial - cette explication l'a fait cliquer. Il ne s'agit pas d'obscurcir ou de compresser des données, mais simplement d'éviter d'utiliser des séquences spéciales pouvant être interprétées comme un protocole.
Patrick Michaelsen
13

Base64 au lieu d'échapper aux caractères spéciaux

Je vais vous donner un exemple très différent mais réel: j'écris du code javascript à exécuter dans un navigateur. Les balises HTML ont des valeurs d'ID, mais il y a des contraintes sur les caractères valides dans un ID.

Mais je veux que mon ID fasse référence sans perte aux fichiers de mon système de fichiers. En réalité, les fichiers peuvent contenir toutes sortes de caractères étranges et merveilleux, à partir de points d'exclamation, de caractères accentués, de tilde et même d'emoji! Je ne peux pas faire ça:

<div id="/path/to/my_strangely_named_file!@().jpg">
    <img src="http://myserver.com/path/to/my_strangely_named_file!@().jpg">
    Here's a pic I took in Moscow.
</div>

Supposons que je veuille exécuter du code comme celui-ci:

# ERROR
document.getElementById("/path/to/my_strangely_named_file!@().jpg");

Je pense que ce code échouera lors de son exécution.

Avec Base64, je peux me référer à quelque chose de compliqué sans me soucier de la langue qui permet quels caractères spéciaux et qui doivent s'échapper:

document.getElementById("18GerPD8fY4iTbNpC9hHNXNHyrDMampPLA");

Contrairement à l'utilisation d'un MD5 ou d'une autre fonction de hachage, vous pouvez inverser l'encodage pour savoir exactement quelles données étaient réellement utiles.

J'aurais aimé connaître Base64 il y a des années. J'aurais évité d'arracher mes cheveux avec ' encodeURIComponent' etstr.replace(‘\n’,’\\n’)

Transfert de texte SSH:

Si vous essayez de passer des données complexes sur ssh (par exemple un fichier dot afin que vous puissiez obtenir vos personnalisations shell), bonne chance pour le faire sans Base 64. Voici comment vous le feriez avec la base 64 (je sais que vous pouvez utiliser SCP, mais cela prendrait plusieurs commandes - ce qui complique les raccourcis clavier pour la connexion à un serveur):

Sridhar Sarnobat
la source
12

Un exemple de quand je l'ai trouvé pratique était d'essayer d' incorporer des données binaires en XML . Certaines des données binaires étaient mal interprétées par l'analyseur SAX car ces données pouvaient être n'importe quoi, y compris des caractères spéciaux XML. Le codage Base64 des données à l'extrémité émettrice et leur décodage à l'extrémité réceptrice ont résolu ce problème.

Bill le lézard
la source
1
+1 - mais ce n'est en aucun cas spécifique à SAX. Cela arriverait à n'importe quel analyseur XML, c'est-à-dire DOM ou XLINQ.
Billy ONeal
1
@Billy: Oui, absolument. Il se trouve que j'utilisais un analyseur SAX pour cette application.
Bill the Lizard
Différents moteurs, par exemple l'analyseur SAX, peuvent interpréter certaines des valeurs ASCII de différentes manières (différents caractères de contrôle). Donc, l'idée ici est d'utiliser le sous-ensemble d'ASCII qui a la signification commune universellement. Droite?
Lazer
1
@Lazer: C'est vrai. Les données binaires non codées auront des caractères de contrôle juste par hasard lorsque vous essayez de les interpréter en ASCII (ce qui n'était pas le cas dans ce cas).
Bill the Lizard
10

La plupart des ordinateurs stockent des données au format binaire 8 bits, mais ce n'est pas obligatoire. Certaines machines et supports de transmission ne peuvent gérer que 7 bits (ou peut-être même moins) à la fois. Un tel support interpréterait le flux en multiples de 7 bits, donc si vous envoyez des données 8 bits, vous ne recevrez pas ce que vous attendez de l'autre côté. La Base-64 n'est qu'un moyen de résoudre ce problème: vous encodez l'entrée dans un format 6 bits, vous l'envoyez sur votre support et la décodez au format 8 bits à la réception.

casablanca
la source
3
Pourquoi est-ce un problème si le flux s'interrompt après 7 bits. A la fin, l'autre machine aura toutes les données reçues sur le flux, elle pourra alors choisir le format 8 bits pour l'afficher? Qu'est-ce qui ne va pas dans mon esprit!
mallaudin
6

En plus des autres réponses (assez longues): même en ignorant les anciens systèmes qui ne prennent en charge que l'ASCII 7 bits, les problèmes de base liés à la fourniture de données binaires en mode texte sont les suivants:

  • Les retours à la ligne sont généralement transformés en mode texte.
  • Il faut faire attention à ne pas traiter un octet NUL comme la fin d'une chaîne de texte, ce qui est trop facile à faire dans n'importe quel programme avec la lignée C.
jamesdlin
la source
Il existe également des caractères de contrôle comme ^ C, ^ D et ^ Z qui sont interprétés comme fin de fichier sur certaines plates-formes.
dan04
5

Qu'est-ce que cela signifie «des supports conçus pour traiter des données textuelles»?

Que ces protocoles ont été conçus pour gérer du texte (souvent, uniquement du texte anglais ) au lieu de données binaires (comme les images .png et .jpg).

Ils peuvent gérer le binaire => ils peuvent gérer n'importe quoi.

Mais l'inverse n'est pas vrai. Un protocole conçu pour représenter du texte peut traiter de manière incorrecte des données binaires qui contiennent:

  • Les octets 0x0A et 0x0D, utilisés pour les fins de ligne, qui diffèrent selon la plateforme.
  • D'autres caractères de contrôle comme 0x00 (terminateur de chaîne NULL = C), 0x03 (FIN DE TEXTE), 0x04 (FIN DE TRANSMISSION) ou 0x1A (fin de fichier DOS) qui peuvent signaler prématurément la fin des données.
  • Octets au-dessus de 0x7F (si le protocole a été conçu pour ASCII).
  • Séquences d'octets non valides UTF-8.

Vous ne pouvez donc pas simplement envoyer des données binaires via un protocole texte. Vous êtes limité aux octets qui représentent les caractères ASCII non contrôlés non spatiaux, dont 94. La raison pour laquelle Base 64 a été choisie est qu'il est plus rapide de travailler avec des puissances de deux, et 64 est le plus grand qui fonctionne. .

Une question cependant. Comment les systèmes ne s'entendent-ils toujours pas sur une technique d'encodage commune comme l'UTF-8 si commun?

Sur le Web, au moins, ils l'ont surtout fait. Une majorité de sites utilisent UTF-8 .

Le problème en Occident est qu'il y a beaucoup de vieux logiciels qui assument ce octet = 1 caractère et ne peuvent pas fonctionner avec UTF-8.

Le problème à l'Est est leur attachement aux encodages comme GB2312 et Shift_JIS.

Et le fait que Microsoft ne semble toujours pas avoir surmonté le mauvais encodage UTF. Si vous souhaitez utiliser l'API Windows ou la bibliothèque d'exécution Microsoft C, vous êtes limité à UTF-16 ou au codage "ANSI" des paramètres régionaux. Cela rend pénible l'utilisation de l'UTF-8 car il faut tout le temps convertir.

dan04
la source
5

Pourquoi / Comment utilisons-nous l'encodage Base64?

Base64 est l'un des schémas de codage binaire en texte ayant une efficacité de 75%. Il est utilisé pour que des données binaires typiques (telles que des images) puissent être envoyées en toute sécurité sur des canaux hérités "non propres 8 bits". Dans les réseaux de messagerie antérieurs (jusqu'au début des années 1990), la plupart des messages électroniques étaient en texte brut dans le jeu de caractères US-ASCII 7 bits. De nombreuses normes de protocole de communication au début ont été conçues pour fonctionner sur des liaisons de communication «7 bits» «et non 8 bits propres». L'efficacité du schéma est le rapport entre le nombre de bits dans l'entrée et le nombre de bits dans la sortie codée. Hexadécimal (Base16) est également l'un des schémas de codage binaire en texte avec une efficacité de 50%.

Étapes d'encodage Base64 (simplifiées):

  1. Les données binaires sont organisées en blocs continus de 24 bits (3 octets) chacun.
  2. Chaque bloc de 24 bits est regroupé en quatre parties de 6 bits chacune.
  3. Chaque groupe de 6 bits est converti en leurs valeurs de caractères Base64 correspondantes, c'est-à-dire que le codage Base64 convertit trois octets en quatre caractères codés. Le rapport entre octets de sortie et octets d'entrée est de 4: 3 (33% de surcharge).
  4. Fait intéressant, les mêmes caractères seront codés différemment selon leur position dans le groupe de trois octets qui est codé pour produire les quatre caractères.
  5. Le destinataire devra inverser ce processus pour récupérer le message d'origine.
Mushtaq Hussain
la source
3

Qu'est-ce que cela signifie «des supports conçus pour traiter des données textuelles»?

À l'époque où l'ASCII régnait, le monde traitant des valeurs non ASCII était un casse-tête. Les gens ont sauté à travers toutes sortes de cerceaux pour les transférer sur le fil sans perdre d'informations.

dirkgently
la source
3
En fait, à l'époque, ASCII n'était même pas utilisé partout. De nombreux protocoles avaient un mode texte et un mode binaire séparés pour le transfert de données, malheureusement le courrier électronique ne l'était pas à l'époque. Le mode texte est nécessaire précisément parce qu'aucun codage de texte unique n'a gouverné le monde, pas ASCII; chaque réseau informatique a son propre encodage préféré, il existe donc des passerelles dont le travail consiste à convertir le texte échangé en encodage local afin qu'une entreprise japonaise puisse envoyer un e-mail à un consultant américain sans mojibake. Cette conversion n'est évidemment pas souhaitable lors de l'envoi de données binaires.
Lie Ryan