Как декодировать Base64, используя только ash в BusyBox?

Вопрос или проблема

Я подключился через SSH к серверу, и это последняя и единственная сессия, которая работает; если я выйду, я потеряю доступ к серверу навсегда.

Мне нужно передать файл (примерно 8 МБ), и я хотел бы сделать это, закодировав его в Base64 и вставив в терминал. Даже если существует лучшее решение, я всё равно хочу знать, как это сделать.

Как декодировать Base64, используя только ash? Команда base64 недоступна. Существует ли однострочный алгоритм для этого? Я использую среду BusyBox.

Используя код Awk, найденный здесь, вы можете легко декодировать его с помощью такой команды:

awk -f base64decode.awk [file1 [file2 [...]]] > output

Полная версия кода base64decode.awk приведена ниже:

# base64decode.awk
#
# Введение
# ========
# Декодирование строк, закодированных в Base64.
#
# Использование
# =============
# Обычно вы запускаете скрипт так:
#
#     $ awk -f base64decode.awk [file1 [file2 [...]]] > output

# Скрипт реализует декодирование Base64 на основе RFC 3548:
#
# https://tools.ietf.org/html/rfc3548

# создайте нашу таблицу поиска
BEGIN {
    # загрузить символы на основе алфавита
    for (i=0; i<26; i++) {
        BASE64[sprintf("%c", i+65)] = i
        BASE64[sprintf("%c", i+97)] = i+26
    }
    # загрузить наши цифры
    for (i=0; i<10; i++) {
        BASE64[sprintf("%c", i+48)] = i+52
    }
    # и наконец наши два дополнительных символа
    BASE64["+"] = 62
    BASE64["/"] = 63
    # также добавьте символ заполнения
    BASE64["="] = -1
}

# Основная функция для декодирования данных Base64.
#
# Аргументы:
# * encoded - строка Base64
# * result - массив для возврата двоичных данных
#
# Выходим при ошибке. Для других случаев использования это должно быть изменено на возврат кода ошибки.
function base64decode(encoded, result) {
    n = 1
    while (length(encoded) >= 4) {
        g0 = BASE64[substr(encoded, 1, 1)]
        g1 = BASE64[substr(encoded, 2, 1)]
        g2 = BASE64[substr(encoded, 3, 1)]
        g3 = BASE64[substr(encoded, 4, 1)]
        if (g0 == "") {
            printf("Неопознанный символ %c в строке, закодированной в Base 64\n",
            g0) >> "/dev/stderr"
            exit 1
        }
        if (g1 == "") {
            printf("Неопознанный символ %c в строке, закодированной в Base 64\n",
            g1) >> "/dev/stderr"
            exit 1
        }
        if (g2 == "") {
            printf("Неопознанный символ %c в строке, закодированной в Base 64\n",
            g2) >> "/dev/stderr"
            exit 1
        }
        if (g3 == "") {
            printf("Неопознанный символ %c в строке, закодированной в Base 64\n",
            g3) >> "/dev/stderr"
            exit 1
        }

        # в AWK нет побитового сдвига, но мы можем достичь тех же
        # результатов с помощью умножения, деления и арифметики по модулю
        result[n++] = (g0 * 4) + int(g1 / 16)
        if (g2 != -1) {
            result[n++] = ((g1 * 16) % 256) + int(g2 / 4)
            if (g3 != -1) {
                result[n++] = ((g2 * 64) % 256) + g3
            }
        }

        encoded = substr(encoded, 5)
    }
    if (length(encoded) != 0) {
        printf("Лишние символы в конце строки, закодированной в Base 64: \"%s\"\n",
        encoded) >> "/dev/stderr"
        exit 1
    }
}

# наша основная обработка текста
{
    # Декодировать полученные данные.
    base64decode($0, result)

    # Вывести декодированную строку.
    #
    # Мы не можем вывести символ NUL, используя BusyBox AWK. См.:
    # https://stackoverflow.com/a/32302711
    #
    # Поэтому мы собираем результат в восьмеричную строку и используем
    # команду оболочки "printf" для создания реального вывода.
    # 
    # Это также помогает в случае gawk, который путается с
    # не-ASCII выводом, если используется локализация, за исключением
    # случаев, когда установлено LC_ALL=C или "--characters-as-bytes".
    printf_str = ""
    for (i=1; i in result; i++) {
        printf_str = printf_str sprintf("\\%03o", result[i])
        if (length(printf_str) >= 1024) {
            system("printf '" printf_str "'")
            printf_str = ""
        }
        delete result[i]
    }
    system("printf '" printf_str "'")
}

код выше находится под лицензией GNU Affero General Public License v3.0

Ответ или решение

Чтобы рассмотреть, как декодировать Base64 в среде BusyBox, используя только оболочку ash, давайте подробно изучим эту задачу с точки зрения теории, примера и применения.

Теория

Base64 — это простая схема кодирования, применяемая для передачи бинарных данных через текстовые протоколы. Она представляет бинарные данные в виде строковых символов, что позволяет избежать проблем с символами, не предназначенными для текстовых представлений. Процесс кодирования включает разбиение данных на блоки по 3 байта, что дает возможность получить 4 группы по 6 битов, которые затем отображаются в 64 допустимых символа ASCII. Обратный процесс — декодирование — предполагает восстановление оригинальных бинарных данных из этой закодированной строки.

BusyBox — это набор приложений UNIX, предназначенный для работы в ограниченных средах, основных для встраиваемых систем. Именно по этой причине в таких системах могут отсутствовать привычные инструменты, включая base64, так что для решения нашей задачи необходимо использовать другие доступные средства.

Пример

Рассмотрим, как мы можем воспользоваться AWK для выполнения этой задачи, путем создания специально настроенного скрипта. В вашем случае вам удалось найти AWK скрипт, который может выполнять функцию декодирования Base64. кодировка Base64 представлена буквами (A-Z, a-z), цифрами (0-9), а также символами ‘+’ и ‘/’. В коде из примера используется таблица преобразования и простой алгоритм для обработки входных данных с возможностью трактовки каждого символа, и это возможно даже в ограниченных условиях BusyBox.

awk -f base64decode.awk [file1 [file2 [...]]] > output

Этот код читает входные файлы и разбивает закодированную строку на блоги по 4 символа, что позволяет графически восстанавливать бинарные данные. Процесс декодирования включает набор проверок на корректность входных данных, таких как наличие нераспознанных символов и необоснованного количества символов в конце строки, чтобы избежать ошибок преобразования данных.

Применение

Теперь давайте рассмотрим, как можно использовать этот подход в вашей рабочей среде. Поскольку у вас не работают другие сессии, ваша задача — максимально эффективно использовать текущую сессию SSH, чтобы передать и декодировать нужные данные.

Используйте следующий подход:

  1. Подготовка данных: На вашем локальном компьютере закодируйте нужные данные и копируйте их в буфер обмена. Можно использовать команду:

    cat filename | base64 | xclip -selection clipboard
  2. Декодирование на сервере: Вставьте закодированный текст в файл на сервере. Используйте редактор VIM или nano для создания файла с закодированными данными:

    cat > encoded.txt
  3. Декодирование с помощью AWK: Используйте приведенный выше скрипт для преобразования данных. Вам может понадобиться предварительно создать файл с содержимым base64decode.awk, используя доступные на сервере редакторы.

  4. Выполните команду декодирования: Запустите AWK скрипт через ash для транспиляции ваших данных:

    awk -f base64decode.awk encoded.txt > decoded_output

Этим методом вы декодируете Base64 без нужды установки дополнительных пакетов, соблюдая все ограничения вашей текущей среды. Это позволит сохранить данные даже в критичной ситуации, когда нет возможности расширить доступ к серверу или использовать другие стандартные инструменты GNU/Linux.

Заключение

Применение AWK для декодирования Base64 в вашей ситуации является практическим решением, учитывающим все ограничения BusyBox. Это наглядно демонстрирует, как можно использовать теоретические основы кодирования и декодирования на практике в условиях ограниченной среды. Важно, чтобы ваш скрипт и данные были правильно отлажены перед началом критичной операции, такой как создание резервных копий или передача больших объемов данных через нестабильный SSH.

Оцените материал
Добавить комментарий

Капча загружается...