Вопрос или проблема
Я подключился через 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, чтобы передать и декодировать нужные данные.
Используйте следующий подход:
-
Подготовка данных: На вашем локальном компьютере закодируйте нужные данные и копируйте их в буфер обмена. Можно использовать команду:
cat filename | base64 | xclip -selection clipboard
-
Декодирование на сервере: Вставьте закодированный текст в файл на сервере. Используйте редактор VIM или nano для создания файла с закодированными данными:
cat > encoded.txt
-
Декодирование с помощью AWK: Используйте приведенный выше скрипт для преобразования данных. Вам может понадобиться предварительно создать файл с содержимым
base64decode.awk
, используя доступные на сервере редакторы. -
Выполните команду декодирования: Запустите AWK скрипт через ash для транспиляции ваших данных:
awk -f base64decode.awk encoded.txt > decoded_output
Этим методом вы декодируете Base64 без нужды установки дополнительных пакетов, соблюдая все ограничения вашей текущей среды. Это позволит сохранить данные даже в критичной ситуации, когда нет возможности расширить доступ к серверу или использовать другие стандартные инструменты GNU/Linux.
Заключение
Применение AWK для декодирования Base64 в вашей ситуации является практическим решением, учитывающим все ограничения BusyBox. Это наглядно демонстрирует, как можно использовать теоретические основы кодирования и декодирования на практике в условиях ограниченной среды. Важно, чтобы ваш скрипт и данные были правильно отлажены перед началом критичной операции, такой как создание резервных копий или передача больших объемов данных через нестабильный SSH.