Примечание : На самом деле это не вопрос, потому что я уже нашел ответ, но поскольку мне было нелегко найти его здесь, я опубликую его, чтобы он мог принести пользу другим.
Вопрос: Как прочитать объединенный файл PEM как тот, который используется директивой apache / mod_ssl SSLCACertificateFile ?
Ответ (оригинал) (источник):
cat $file|awk 'split_after==1{n++;split_after=0} /-----END CERTIFICATE-----/ {split_after=1} {print > "cert" n ".pem"}'
Это может оставить пустой файл, если в конце есть пустая строка, например, с openssl pkcs7 -outform PEM -in my-chain-file -print_certs
. Чтобы этого не произошло, перед печатью проверьте длину строки:
cat $file|awk 'split_after==1{n++;split_after=0}
/-----END CERTIFICATE-----/ {split_after=1}
{if(length($0) > 0) print > "cert" n ".pem"}'
Ответ 29.03.2016 :
Подписан на @slugchewer ответ, csplit
может быть более понятным вариантом с:
csplit -f cert- $file '/-----BEGIN CERTIFICATE-----/' '{*}'
Фрагмент awk работает для извлечения различных частей, но вам все равно нужно знать, какой раздел является ключом / сертификатом / цепочкой. Мне нужно было извлечь определенный раздел, и я нашел его в списке рассылки OpenSSL: http://openssl.6102.n7.nabble.com/Convert-pem-to-crt-and-key-files-tp47681p47697.html
# Extract key
openssl pkey -in foo.pem -out foo-key.pem
# Extract all the certs
openssl crl2pkcs7 -nocrl -certfile foo.pem |
openssl pkcs7 -print_certs -out foo-certs.pem
# Extract the textually first cert as DER
openssl x509 -in foo.pem -outform DER -out first-cert.der
В split
команда доступна в большинстве систем, и ее вызов, вероятно, легче запомнить.
Если у вас есть файл collection.pem
что вы хотите разделить на individual-*
файлы, используйте:
split -p "-----BEGIN CERTIFICATE-----" collection.pem individual-
Если у вас нет split
вы могли бы попробовать csplit
:
csplit -f individual- collection.pem '/-----BEGIN CERTIFICATE-----/' '{*}'
Это было ранее ответил на StackOverflow :
awk '
split_after == 1 {n++;split_after=0}
/-----END CERTIFICATE-----/ {split_after=1}
{print > "cert" n ".pem"}' < $file
Редактировать 29/03/2016 : См. @Slugchewer ответ
Если вы хотите получить один сертификат из пакета PEM с несколькими сертификатами, попробуйте:
$ openssl crl2pkcs7 -nocrl -certfile INPUT.PEM | \
openssl pkcs7 -print_certs | \
awk '/subject.*CN=host.domain.com/,/END CERTIFICATE/'
openssl
команды обработают файл PEM и выплюнут его обратно с предварительно записанными "subject:"
и "issuer:"
строки перед каждым сертификатом. Если ваш PEM уже отформатирован таким образом, все, что вам нужно, это последний awk
команда.Также стоит отметить, что Файлы PEM это просто набор ключей / сертификатов внутри BEGIN
/END
блоки, поэтому довольно легко просто вырезать / вставить, если это всего лишь один файл с одним или двумя интересными объектами ...
Если вы обрабатываете сертификаты полной цепочки (то есть те, которые сгенерированы letsencrypt / certbot и т. Д.), Которые представляют собой конкатенацию сертификата и цепочки центра сертификации, вы можете использовать манипуляции со строкой bash.
Например:
# content of /path/to/fullchain.pem
-----BEGIN CERTIFICATE-----
some long base64 string containing
the certificate
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
another base64 string
containing the first certificate
in the authority chain
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
another base64 string
containing the second certificate
in the authority chain
(there might be more...)
-----END CERTIFICATE-----
Чтобы извлечь сертификат и цепочку центров сертификации в переменные:
# load the certificate into a variable
FULLCHAIN=$(</path/to/fullchain.pem)
CERTIFICATE="${FULLCHAIN%%-----END CERTIFICATE-----*}-----END CERTIFICATE-----"
CHAIN=$(echo -e "${FULLCHAIN#*-----END CERTIFICATE-----}" | sed '/./,$!d')
Пояснение:
Вместо использования awk или openssl (которые являются мощными инструментами, но не всегда доступны, например, в образах Docker Alpine), вы можете использовать манипуляции со строками bash.
"${FULLCHAIN%%-----END CERTIFICATE-----*}-----END CERTIFICATE-----"
: с конца содержимого FULLCHAIN вернуть самое длинное совпадение подстроки, затем объединить -----END CERTIFICATE-----
как его сорвали. В *
соответствует всем символам после -----END CERTIFICATE-----
.
$(echo -e "${FULLCHAIN#*-----END CERTIFICATE-----}" | sed '/./,$!d')
: с начала содержимого FULLCHAIN вернуть самое короткое совпадение подстроки, затем удалить ведущие новые строки. Точно так же *
соответствует всем символам до -----END CERTIFICATE-----
.
Для быстрой справки (пока вы можете узнать больше о манипуляциях со строками в bash Вот):
${VAR#substring}
= самая короткая подстрока от начала содержимого VAR
${VAR%substring}
= самая короткая подстрока с конца содержимого VAR
${VAR##substring}
= самая длинная подстрока от начала содержимого VAR
${VAR%%substring}
= самая длинная подстрока с конца содержимого VAR
Хммм ... почти так же, как я подготовил решение (как предложил y @Cerber), не осознавая, что эта ситуация, похоже, у многих. Мое решение следует почти такой же логике, но использует еще несколько основных команд:
Все мои сертификаты находятся в файле: certin.pem
c=0
while read line
do
if echo $line | grep END; then
echo $line >> certout$c.pem
c=`expr $c + 1`
else
echo $line
echo $line >> certout$c.pem
fi
done < /tmp/certin.pem
Это в основном продолжает запись в файл, пока не встретит «КОНЕЦ», а затем начинает запись в другой файл с приращением. Таким образом у вас будет N выходных файлов (certout0.pem, certout1.pem и так далее ..) файлы в зависимости от того, сколько сертификатов содержится во входном pem-файле ( certin.pem ).