Як розділити файл PEM


38

Примітка: Це насправді не питання, тому що я вже знайшов відповідь, але, оскільки я не знайшов її тут легко, я опублікую її, щоб вона могла принести користь іншим.

Питання: Як прочитати зв'язаний файл 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-----/' '{*}'

Це може бути німим питанням, але чому мені потрібно розділити свій файл pem?
Ашвані Агарвал

6
@AshwaniAgarwal Ви хочете розділити файл PEM, коли він містить кілька сертифікатів, і ви хочете вивчити сертифікати окремо за допомогою інструментів, таких як opensslодин сертифікат для аналізу.
Закон29,

Крім того, деякі інструменти або сервери хочуть комбінувати файл з cert і key, а інші хочуть їх окремо.
captncraig

Мені довелося додати "% ----- BEGIN CERTIFICATE -----%" до командного рядка csplit, щоб запобігти порожньому файлу. Здається, відповідає тому, що вказує сторінка man: csplit -f ./tmp/cert- $ file '% ----- ПОЧАТИ СЕРТИФІКАТ -----%' '/ ----- ПОЧАТИ СЕРТИФІКАТ ----- / '' {*} '
Крейг Хікс

2
використовуйте "csplit -z", щоб не залишати порожні файли.
Пол М

Відповіді:


23

Фрагмент awk працює з вилученням різних частин, але вам все одно потрібно знати, який розділ є ключем / cert / ланцюгом. Мені потрібно було витягнути певний розділ і знайшов це у списку розсилки 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

приємний набір команд :) Я буду зберігати його для подальшого використання, але в моєму випадку використання вище, я працюю з файлом, який містить лише cert, що містить 50+ сертифікатів CA ==> ні pkey, ні ланцюг
Cerber

2
Я думаю, що це перевершує awk рішення, нехай openssl зробить аналіз + ви отримаєте конверсію.
Іржавий

Вибачте, але правильна лише команда pkey. Друге і третє не роблять те, що ти рекламуєш - вони роблять щось інше. У деяких випадках результат хороший, в деяких випадках він може породжувати таємничу поведінку у споживачів. Відредагували трохи.
kubanczyk

Будь-яка ідея, як отримати текстово 3-й серт таким чином?
мерехтіння

16

На це раніше відповіли в StackOverflow :

awk '
  split_after == 1 {n++;split_after=0}
  /-----END CERTIFICATE-----/ {split_after=1}
  {print > "cert" n ".pem"}' < $file

Редагувати 29.03.2016 : Дивіться відповідь @slugchewer


Працює лише в Linux, виходить з ладу на FreeBSD.
Майкл-О

3
Натхненний цим, я створив сценарій awk, який розбиває certs та ключі на окремі файли: gist.github.com/jinnko/d6867ce326e8b6e88975
JinnKo

15

splitКоманда доступна на більшості систем, і його виклик, ймовірно , легше запам'ятати.

Якщо у вас є файл, collection.pemякий потрібно розділити на individual-*файли, використовуйте:

split -p "-----BEGIN CERTIFICATE-----" collection.pem individual-

Якщо у вас немає split, ви можете спробувати csplit:

csplit -f individual- collection.pem '/-----BEGIN CERTIFICATE-----/' '{*}'

2
Вибачте, жодна з моїх систем (busybox, fedora, centos) не відображає -pпараметр (ані мандатів, які я читаю ) на split. Можливо, ви використовуєте спеціальний двійковий / пакет
Cerber

1
@Cerber Не могли б спробувати csplit... (див. Редагування вище)
squidpickles

1
добре працює з csplit!
Чербер

У FreeBSD я отримую від csplit: csplit: *}: bad repetition count(але поділ здається на роботу)
Гвінет Llewelyn

4

Якщо ви хочете отримати один сертифікат із пакету 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 є закодованим Base64, ви не знайдете текст типу "тема", "CN", ... з awk
Cerber

1
Так, це працює не для кожного типу PEM. Якщо ви витягуєте P7B до PEM за допомогою openssl, перед кожним сертифікатом буде вказаний рядок теми. Або ви можете змінити будь-який рядок, за допомогою якого сегментуєте файл PEM.
cmcginty

Оновлена ​​відповідь на обробку, коли PEM не містить "тему"
cmcginty

3

Також варто відзначити, що файли PEM - це лише сукупність ключів / сертифікатів всередині BEGIN/ ENDблоків, тому досить просто просто вирізати / вставити, якщо це лише один файл з одним або двома цікавими об'єктами ...


2

Якщо ви обробляєте повноцінні сертифікати ланцюга (тобто ті, що генеруються 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 images), ви можете використовувати маніпуляції з рядком 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


Для менш ощадливих баш, коли ви перегукуєте ці змінні, оточуйте змінну лапками, щоб зберегти рядки, що розбивають так, як ви звикли їх бачити. Я пам’ятаю, коли це було для мене не так очевидно. Фабіо, солодке використання маніпуляцій струнних баш!
мерехтіння

0

Гммм ... майже так само, як я підготував рішення (як це запропонував 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 ).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.