Как разделить файл 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-----/' '{*}'
9 ответов
Ранее на StackOverflow был дан ответ:
awk '
split_after == 1 {n++;split_after=0}
/-----END CERTIFICATE-----/ {split_after=1}
{print > "cert" n ".pem"}' < $file
Изменить 29/03/2016: см. Ответ @slugchewer
Фрагмент 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-----/' '{*}'
Если вы хотите получить один сертификат из пакета PEM с несколькими сертификатами, попробуйте:
$ openssl crl2pkcs7 -nocrl -certfile INPUT.PEM | \
openssl pkcs7 -print_certs | \
awk '/subject.*CN=host.domain.com/,/END CERTIFICATE/'
- Первые два
openssl
Команды обработают PEM-файл и выплюнут его с помощью pre-pen"subject:"
а также"issuer:"
строки перед каждым сертификатом. Если ваш PEM уже отформатирован таким образом, все, что вам нужно, это финалawk
команда. - Команда awk выдаст отдельный PEM, соответствующий строке CN (общее имя).
Если вы обрабатываете сертификаты с полной цепочкой (т. Е. Сгенерированные 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, вернуть самое длинное совпадение подстроки, затем concat -----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
Также стоит отметить, что PEM-файлы - это просто набор ключей / сертификатов внутри BEGIN
/END
блоки, так что довольно просто вырезать / вставить, если это всего лишь один файл с одним или двумя интересными объектами...
Вы можете использоватьawk
следующее:
awk '/-----BEGIN CERTIFICATE-----/ {f=1} /-----END CERTIFICATE-----/ {print; f=0} f' cert_and_key.pem
awk '/-----BEGIN PRIVATE KEY-----/ {f=1} /-----END PRIVATE KEY-----/ {print; f=0} f' cert_and_key.pem
Командаawk '/hello/ {f=1} /world/ {print; f=0} f' some_file
напечатает все строки вsome_file
это между строкhello
иworld
, включительно.
Хммм... почти так же, как я подготовил решение (как предложено 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
Это, в основном, сохраняет запись в файл до тех пор, пока не встретит "END", а затем начнет запись в другой файл в увеличенном виде. Таким образом, у вас будет "N" количество файлов выходных файлов (certout0.pem, certout1.pem и т. Д.) В зависимости от того, сколько сертификатов содержится во входном файле pem (certin.pem).
full.pem
можно легко разделить на и использоватьgrep
иtail
:
grep -B 1000 -m 1 -F -e "-----END CERTIFICATE-----" full.pem > cert.pem
tail -n +2 full.pem | grep -A 1000 -m 1 -F -e "-----BEGIN CERTIFICATE-----" > chain.pem
For: поиск первой строки-----END CERTIFICATE-----
и возьми все раньше-B 1000
затем выведите вcert.pem
.
Для: пропустите первую строку с помощьюtail -n +2
затем найдите первую строку-----BEGIN CERTIFICATE-----
и возьми все после-A 1000
затем выведите вchain.pem
.