Удалите символ новой строки после вертикальной черты

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

Я хочу выполнить кодирование в Base64 с помощью команды

echo -en "my_message" | openssl sha1 -hmac "secret_key" | base64

Выходная строка команды openssl соответствует ожиданиям, но результат base64 не такой, как вывод с openssl, так как в нем есть символ новой строки. Если я выполняю команду

echo -en "my_message" | openssl sha1 -hmac "secret_key" | xargs echo -n | base64

То конечный вывод правильный.

Мне интересно, есть ли более элегантный способ выполнения этой команды

openssl sha1 -hmac "secret_key" выводит такую строку текста:

SHA1(stdin)= 5238cc013426063a31b5db127f9c939f9218e1f3

Он не только добавляет символ новой строки (если бы его не было, это было бы недопустимым текстом!), но и выводит результат в шестнадцатеричном коде вместо base64, с префиксом SHA1(stdin)= .

Если вам нужен дайджест в формате base64, используйте:

openssl sha1 -binary -hmac "secret_key"

Где он будет выведен в сыром виде, который вы можете передать в xxd -p для шестнадцатеречного кодирования или в base64, чтобы получить кодирование в base64.

Что касается более общего вопроса о удалении символов новой строки:

  • Передача в tr -d '\n' удалит все символы новой строки.
  • Передача в head -c -1 удалит последний байт (независимо от того, является ли он новой строкой или нет).
  • Передача в perl -pe 's/\n\z// if eof' удалит последний байт вывода, если это символ новой строки.

Передача в xargs echo -n является неверной в общем случае, так как

  • Как xargs, так и echo могут искажать данные. xargs определенно не является инструментом для обработки текста.
  • Не все echo поддерживают -n, те, которые не поддерживают опции, обычно обрабатывают экранирование \. xargs printf %s было бы лучше.
  • Это вызовет внешнюю утилиту echo, так что аргументы будут отображаться в выводе ps, что обычно является общедоступной информацией.
cmd_output=$(cmd)
printf %s "$cmd_output"

Удалит все завершающие символы новой строки, но, за исключением zsh, также не сможет обработать нулевые байты, что делает его неприемлемым, например, для сырого двоичного дайджеста (хотя нет смысла удалять завершающие переводы строк (байты 0x0A) из двоичного дайджеста).

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

Чтобы получить корректную кодировку Base64 без ненужных символов новой строки, вы можете воспользоваться параметром -binary при вызове команды OpenSSL, как вы уже упомянули. Это позволит получить бинарный вывод SHA1-хэширования без дополнительных префиксов и символов новой строки.

Вот как может выглядеть ваша команда:

echo -en "my_message" | openssl sha1 -binary -hmac "secret_key" | base64

Когда вы используете -binary, OpenSSL выводит двоичный результат, и последующая команда base64 корректно закодирует его в Base64 без добавления лишних символов.

Если вам необходимо удалить новые строки для других случаев, вы можете использовать несколько подходов:

  1. tr для удаления всех символов новой строки:
your_command | tr -d '\n'
  1. head для удаления последнего символа:
your_command | head -c -1
  1. perl для удаления последнего символа, если он является новой строкой:
your_command | perl -pe 's/\n\z// if eof'

Тем не менее, методы с использованием xargs и echo не рекомендуется использовать в общем случае, так как они могут исказить данные:

  • xargs не предназначен для обработки текста и может вводить нежелательные пробелы или изменять форматирование.
  • echo может вести себя по-разному в зависимости от системы и реализации, что делает его ненадежным для обработки данных.

Для более безопасного подхода вы можете использовать printf, чтобы избежать проблем с echo:

your_command | xargs printf "%s"

Однако, как вы отметили, cmd_output=$(cmd) и printf %s "$cmd_output" — это способ удаления всех завершающих символов новой строки, но, за исключением zsh, это не обрабатывает нулевые байты, поэтому будьте осторожны с использованием этого метода для бинарных данных.

Таким образом, для вашей задачи с кодировкой в Base64 рекомендуется использовать вариант с openssl sha1 -binary, как это указано в первом примере. Это решение является наиболее элегантным и эффективным для вашей ситуации.

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

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