декодирование base64 при игнорировании скобок - PullRequest
0 голосов
/ 10 ноября 2018

Я пытаюсь декодировать файл, который в основном закодирован с base64. То, что я хочу сделать, это декодировать следующее, сохраняя при этом [_*_].

example.txt

wq9cXyjjg4QpXy/Crwo=
[_NOTBASE64ED_]
aGkgdGhlcmUK
[_CONSTANT_]
SGVsbG8gV29ybGQhCg==

Иногда это будет в таком виде

aGkgdGhlcmUK[_CONSTANT_]SGVsbG8gV29ybGQhCg==

Желаемый вывод

¯\_(ツ)_/¯
[_NOTBASE64ED_]
hi there
[_CONSTANT_]
Hello World!
hi there[_CONSTANT_]Hello World!

Ошибка вывода

¯\_(ツ)_/¯
4��!:�@�H\�B�8ԓ��[��ܛBbase64: invalid input

Что я пробовал

base64 -di example.txt
base64 -d example.txt
base64 --wrap=0 -d -i example.txt

Я попытался по отдельности base64 [_*_], используя grep -o. Тогда найди и
заменить их через странное расположение массивами, но я не смог
заставить его работать. Base64ing все это, затем расшифровка. Результаты в двойных base64ed строках.

Файл значительно уменьшен! Кодируется с использованием base64 --wrap=0, цикла while и оператора if / else. [_*_] все еще должен быть там после декодирования.

Ответы [ 4 ]

0 голосов
/ 12 ноября 2018

Если Perl является опцией, вы можете сказать что-то вроде:

perl -MMIME::Base64 -lpe '$_ = join("", grep {/^\[/ || chomp($_ = decode_base64($_)), 1} split(/(?=\[)|(?<=\])/))' example.txt

Код, приведенный ниже, эквивалентен приведенному выше, но для пояснения разбит на этапы:

#!/bin/bash

perl -MMIME::Base64 -lpe '
    @ary = split(/(?=\[)|(?<=\])/, $_);
    foreach (@ary) {
        if (! /^\[/) {
            chomp($_ = decode_base64($_));
        }
    }
    $_ = join("", @ary);
' example.txt
  • -MMIME::Base64 загружает модуль кодека base64.
  • -lpe делает Perl похожим на AWK, чтобы зацикливать строки ввода и неявно обрабатывать переводы строки.
  • Регулярное выражение (?=\[)|(?<=\]) соответствует границе между блоком base64 и поддерживающим блоком, окруженным [...].
  • Функция split делит линию на блоки на границе и сохраняет их в массиве.
  • Затем переберите массив и декодируйте запись в кодировке base64, если она найдена.
  • Наконец, объедините блоки подстроки в строку для печати. ​​
0 голосов
/ 10 ноября 2018

Я уверен, что у кого-то есть более умное решение, чем это. Но попробуйте это

#! /bin/bash

MYTMP1=""
function printInlineB64()
{
    local lines=($(echo $1 | sed -e 's/\[/\n[/g' -e 's/\]/]\n/g'))
    OUTPUT=""
    for line in "${lines[@]}"; do
        MYTMP1=$(base64 -d <<< "$line" 2>/dev/null)
        if [ "$?" != "0" ]; then
            OUTPUT="${OUTPUT}${line}"
        else
            OUTPUT="${OUTPUT}${MYTMP1}"
        fi;
    done
    echo "$OUTPUT"
}

MYTMP2=""
function printB64Line()
{
    local line=$1

    # not fully base64 line
    if [[ ! "$line" =~ ^[A-Za-z0-9+/=]+$ ]]; then 
        printInlineB64 "$line"
        return
    fi;

    # likely base64 line
    MYTMP2=$(base64 -d <<< "$line" 2>/dev/null)
    if [ "$?" != "0" ]; then
        echo $line
    else
        echo $MYTMP2
    fi;
}


FILE=$1
if [ -z "$FILE" ]; then
    echo "Please give a file name in argument" 
    exit 1;
fi;

while read line; do
    printB64Line "$line"
done < ${FILE}

и вот вывод

$ cat example.txt && echo "==========================" && ./base64.sh example.txt
wq9cXyjjg4QpXy/Crwo=
[_NOTBASE64ED_]
aGkgdGhlcmUK
[_CONSTANT_]
SGVsbG8gV29ybGQhCg==
==========================
¯\_(ツ)_/¯
[_NOTBASE64ED_]
hi there
[_CONSTANT_]
Hello World!

$ cat example2.txt && echo "==========================" && ./base64.sh example2.txt
aGkgdGhlcmUK[_CONSTANT_]SGVsbG8gV29ybGQhCg==
==========================
hi there[_CONSTANT_]Hello World!
0 голосов
/ 10 ноября 2018

Я бы предложил использовать другие языки, кроме sh, но здесь есть решение, использующее cut. Это будет обрабатывать случай, когда в строке более одного [_constant_].

#!/bin/bash

function decode() {
    local data=""
    local line=$1
    while [[ -n $line ]]; do
          data=$data$(echo $line | cut -d[ -f1 | base64 -d)
          const=$(echo $line | cut -d[ -sf2- | cut -d] -sf1)
          [[ -n $const ]] && data=$data[$const]
          line=$(echo $line | cut -d] -sf2-)
    done
    echo "$data"
}

while read -r line; do
    decode $line
done < example.txt
0 голосов
/ 10 ноября 2018

Вам необходим цикл, который читает каждую строку и проверяет, является ли она base64 или не base64, и обрабатывает ее соответствующим образом.

while read -r line
do
    case "$line" in
        \[*\]) echo "$line" ;;
        *) base64 -d <<< "$line" ;;
    esac
done << example.txt
...