Назад | Перейти на главную страницу

Как разбить файл PEM

Примечание : На самом деле это не вопрос, потому что я уже нашел ответ, но поскольку мне было нелегко найти его здесь, я опубликую его, чтобы он мог принести пользу другим.

Вопрос: Как прочитать объединенный файл 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 команда.
  • Команда awk выдаст индивидуальный PEM, соответствующий строке CN (общее имя).

источник1 , источник2

Также стоит отметить, что Файлы 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 ).