«Openssl dgst -sha1» производит посторонний префикс «(stdin) =» и завершающий перевод строки


31

Если вы запустите эту команду на вашем Unix

echo -n "foo" | openssl dgst -sha1

Вы получите этот вывод:

(stdin)= 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33

(сопровождается переводом строки).

Как я могу заставить openssl не показывать (stdin)=префикс и избежать завершающего перевода строки?


@MarkDavidson Хм, интересно. Вы уверены, что он даже не добавляет новую строку?

Ответы:


22

Сырой двоичный формат не добавляет никаких посторонних выводов.
Выведите как двоичный файл, затем преобразуйте в шестнадцатеричный код:

echo -n "foo" | openssl dgst -sha1 -binary | xxd -p

Даст вам это:

0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33

Этот метод должен быть ориентирован на будущее в случае, если кто-то решит снова изменить формат текстового вывода. Я уверен, что они исправят префикс «SHA1 (stdin) =», чтобы он соответствовал вводу файла.

Я не могу поверить, что они изменили это! Интересно, сколько скриптов было сломано.


4
Он выведет только 20-30 октетов на строку (или 40-60 символов). Для контрольной суммы SHA-256 этого иногда недостаточно. Используйте -c 256опцию, чтобы расширить его до 256 октетов на строку.
Rockallite

16

Я наблюдаю такое поведение под OpenSSL 1.0.0e на Ubuntu 11.10, тогда как OpenSSL 0.9.8k и 0.9.8t выводят только хеш. Командная строка OpenSSL не предназначена для гибкости, это скорее быстрый и грязный способ выполнения криптографических вычислений из командной строки.

Если вы хотите использовать OpenSSL, отфильтруйте вывод:

echo -n "foo" | openssl dgst -sha1 | sed 's/^.* //'

В Linux (с инструментами GNU или BusyBox) вы можете использовать sha1sum, который не требует установки OpenSSL и имеет стабильный формат вывода. Он всегда печатает имя файла, поэтому удалите его.

echo -n "foo" | sha1sum | sed 's/ .*//'

На системах BSD, включая OSX, вы можете использовать sha1.

echo -n "foo" | sha1 -q

Все они выводят контрольную сумму в шестнадцатеричном формате с последующим переводом строки. Текст в системах Unix всегда состоит из последовательности строк, и каждая строка заканчивается символом новой строки. Если вы сохраните вывод команды в переменной оболочки, последний символ новой строки будет удален.

digest=$(echo -n "foo" | openssl dgst -sha1 | sed 's/^.* //')

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

echo -n "foo" | openssl dgst -sha1 | sed 's/^.* //' | tr -d '\n' | unusual_program

это идеальная ситуация => скопировать и вставить карту решения. Благодарность!
оберштет

6

Вот еще одна альтернатива:

echo -n "foo" | openssl sha1 | awk '{print $2}'

1
Я знаю, что вопрос задается с этим конкретным форматом, однако, если кто-то попытается расширить это, чтобы включить имена файлов, он может сломаться, если в имени файла есть пробелы. Просто головы для других людей, которые приземляются здесь.
Кэмерон Ганьон

2

Вот способ сделать это, используя встроенные модули bash вместо pipe, awk, sed, tr, cut и т.д .:

output="$(openssl sha1 <(printf foo))"; echo ${output/* }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.