OpenSSL peut-il décoder des données base64 qui ne contiennent pas de sauts de ligne?

9

J'ai deux morceaux de données base64 dans une variable bash. Les sauts de ligne habituels dans les données base64 ont été remplacés par des espaces et la variable est fondamentalement une très longue chaîne d'une ligne.

Je peux décoder les deux morceaux de données base64 contenus dans la variable mais j'ai rencontré quelques nuances en essayant de le faire. Je voudrais comprendre si je m'approche de cela correctement ou s'il existe un meilleur moyen de décoder les données base64 qui ne contiennent pas de sauts de ligne. Voici ce que j'ai:

Le premier morceau est de 350 caractères et je peux le décoder avec succès comme ceci:

echo ${DATA::350} | openssl base64 -d | wc -c
256

Le deuxième bloc est de 5745 caractères mais la commande ci-dessus ne produit pas les résultats attendus. c'est à dire:

$ echo {DATA:350} | openssl base64 -d | wc -c
432

Cependant, cela fonctionne si je remets les sauts de ligne en arrière:

$ echo ${DATA:350} | tr ' ' "\n" | openssl base64 -d | wc -c
4240

Je m'attends à ce qu'il y ait un problème de longueur de ligne que le premier bloc soit assez petit pour éviter, et il semblerait que ce soit une caractéristique du décodeur base64 utilisé (les deux habituels base64et openssl base64se comportent différemment).

Le base64décodeur (au lieu de openssl base64) s'arrête au premier caractère invalide (le blanc) et décode donc juste la première "ligne" (48 octets de données de sortie) tandis qu'OpenSSL produit 432 caractères (9 "lignes"). La base64commande a une option pour ignorer les ordures , donc cela fonctionne:

$ echo ${DATA:350} | base64 -d -i | wc -c
4240

Le décodeur OpenSSL ne semble pas avoir une telle option.

En outre, la suppression de l'espace blanc fonctionne entièrement pour base64mais pas openssl base64:

$ echo ${DATA:350} | tr -d ' ' | openssl base64 -d | wc -c
400

$ echo ${DATA:350} | tr -d ' ' | base64 -d | wc -c
4240

Donc, à la fin, j'ai remplacé les sauts de ligne et j'ai utilisé le décodeur OpenSSL parce que j'avais quand même besoin de continuer à traiter les données décodées:

$ openssl enc -d -a -in <(echo ${DATA:350} | /usr/bin/tr ' ' "\n") -aes-256-cbc -pass file:<(echo $skey) | ...

Mais je voudrais comprendre Est-ce qu'OpenSSL peut décoder les données base64 qui ne contiennent pas de sauts de ligne?

étoilé
la source
FWIW bash peut modifier ou supprimer les caractères lui-même, sans tr, en utilisant ${var//old[/new}- mais pas en même temps que la sous-chaîne.
dave_thompson_085

Réponses:

17

Si vous n'avez pas besoin d' espaces, vous opensslallez gérer cela avec l' -Aoption:

Donc:

$ ls -l sp2.bmp
-rw-r--r-- 1 sweh sweh 3000054 Apr 21 20:13 sp2.bmp
$ x=$(openssl base64 -A < sp2.bmp)                
$ echo "$x" | wc
      1       1 4000073
$ echo "$x" | openssl base64 -d -A > res
$ ls -l res
-rw-r--r-- 1 sweh sweh 3000054 Jul 30 10:00 res
$ cmp res sp2.bmp 
$ 

Nous pouvons voir que les données base64 sont toutes sur une seule ligne et peuvent être décodées.

man encexplique l' -Aoption.

Si vous devez conserver les espaces, vous devrez les supprimer (soit en les convertissant, '\n'soit en les supprimant et en les utilisant -A).

Stephen Harris
la source
L' -Aoption a été l'une des premières choses que j'ai essayées, mais je l'ai fait avant d'essayer de supprimer les espaces, puis j'ai "continué" quand cela n'a pas fonctionné! La page de manuel ne mentionne pas que les espaces sont un problème. Quoi qu'il en soit, je viens de l'essayer à nouveau avec les espaces supprimés et cela fonctionne. C'est toujours méchant mais au moins c'est juste un tr -d ' '. C'est dommage qu'il ne puisse pas le traiter et ignorer les espaces blancs (comme le base64peut).
Starfry
2
La RFC 4648 indique que les espaces à proprement parler (section 3.3) et les sauts de ligne (section 3.1) sont interdits en base64. La section 3.3 indique également que les implémentations DOIVENT rejeter les données dans ce cas. C'est donc openssl base64 -Aplus près d'être une interprétation stricte, que vous attendez d'un outil de chiffrement de sécurité. Je suppose que les coreutils base64sont plus indulgents.
Stephen Harris
2
OpenSSL a implémenté base64 dans les années 1990 (avant 4648 ou même 3548) principalement pour lire et écrire des fichiers 'PEM' (vraiment PEM) et S / MIME, tous deux nécessitant des sauts de ligne. -Aest fondamentalement "nous avons les EVP_{En,De}codeBlockfacteurs, autant laisser les gens les utiliser".
dave_thompson_085