Btoa et l'encodage Base 64

Jan 24, 2018 · 406 words · 2 minutes read typescript javascript

btoa et l’encodage base 64

Recement, sur un projet, nous avons eu à transmettre des données encodées en base 64 entre une webapp basé sur Angular 4 et un backend basé sur Spring. Notre webapp est bien evidement basé sur de l’utf8.

Tout se passait bien, jusqu’au jour ou nous avons eu l’idée saugrenue d’utiliser des accents dans les texte transmis…​ Et là, ce fut le drame !!

Le texte "élémentaire" était reçu sous cette forme : "�l�mentaire", ce n’est pas la joie.

Normal au final (d’ou l’interêt de connaitre les API que l’on utilise), car si j’avais lu la doc directement au lieu d’appliquer le premier hello world venu.

La documentation de btoa est pourtant limpide, cela figure même dans le premier encart :

…​une exception InvalidCharacterError est déclenchée si le code point d’un caractère quelconque est en dehors de la plage 0x00 à 0xFF…​
— MDN web docs

Alternative à btoa

La solution était de réimplementer btoa pour une prise en compte des caractères unicode UTF8.

le code est simple :

b64EncodeUnicode(str) {
    const uriEncoding = encodeURIComponent(str) (1)
        .replace(/%([0-9A-F]{2})/g, function(match, p1) { (2)
            return String.fromCharCode( (4)
                parseInt(p1, 16) (3)
            );
        }
    );
    return btoa(uriEncoding); (5)
}
  1. Encodage sous forme d’URI du texte, cela transformera le texte, par exemple "é" donnera %C3%A9

  2. chaque partie de caractère encodé est ensuite formaté afin de supprimer le signe % (paramètre p1), donc %C3 donnera C3.

  3. Le code URI ainsi extrait est transformé en entier, qui sera lui compris entre 0x00 et 0xFF.

  4. La valeur obtenue est transformé en caractère. Ce qui au final, donne pour le mot “élémentaire” le texte pré-encodé “élémentaire”. On voit bien que l’accent prend deux catactères.

  5. La chaine obtenue peut donc être tranquilement encodé en base64 via btao.

Le tour est joué !!

La preuve ?

Afin de formaliser tout cela, j’ai créé un petit poc, que vous trouverez sur mon repo github : ptitbob/solve_btoa_utf8.

Il y a deux projets :

  • ping-server : serveur back basé sur spring(boot) qui ne fait qu’un ping en revoyant une chaine encodée en base64 décodée. - y’a pas plus simple !

    • pour le lancer, placez vous dans le repertoire et executer : mvn spring-boot:run

  • webapp : l’application demo basé sur Angular5 permettant de tester l’encodage via la fonction btoa directement ou via l’alternative

    • Pour lancer la webapp, placez vous dans le repertoire, puis executer ng serve. La webapp sera disponible à cette adresse : http://localhost:4200/ .

have fun