Вопрос или проблема
У меня есть файл SSL CRT в формате PEM. Есть ли способ извлечь общее имя (CN) из сертификата с помощью командной строки?
Если у вас установлен openssl
, вы можете выполнить:
openssl x509 -noout -subject -in server.pem
certtool -i < whatever.pem | egrep "^\s+Subject:"
Обратите внимание, что файл передается на стандартный ввод через <
, а не используется как аргумент. Без egrep
это выведет весь сертификат, но CN будет в поле Subject:
вверху (остерегайтесь, также существует значение CN в поле Issuer:
).
X.509 Информация о сертификате:
Версия: 3
Серийный номер (шестнадцатеричный): 01
Выдаватель: [...] CN=unixandlinux.ex <- Не это.
Действительность: ...
Субъект: CN=goldilocks
certtool
является частью gnutls, если он не установлен, просто найдите его. GnuTLS, на мой взгляд, немного удобнее, чем OpenSSL.
Используя openssl и awk
- openssl
-subject
извлекает только субъект,-multiline
разбивает его на строки
- awk
-F' = '
– разделить поля по<space>=<space>
/commonName/
для только тех строк, которые соответствуютcommonName
{print $2}
– вывести второе поле
❯ openssl x509 -noout -subject -in cert.crt -nameopt multiline
subject=
countryName = AU
stateOrProvinceName = NSW
localityName = Sydney
organizationName = Some Acme Company Pty Ltd
organizationalUnitName = Engineering
commonName = CommonName 123
emailAddress = [email protected]
❯ openssl x509 -noout -subject -in cert.crt -nameopt multiline | awk -F' = ' '/commonName/ {print $2}'
CommonName 123
Я нашел приведенный выше ответ и посчитал его очень полезным, но также заметил, что синтаксис команды certtool
(на Ubuntu Linux, сегодня) заметно отличается от описанного goldilocks, так же как и вывод. Поэтому я решил обновить этот отличный ответ тем, что могло бы быть «версия на сегодня».
Опция "i"
(сейчас?) означает «импорт», согласно man certtool
, так что команду, похоже, нужно заменить на "d"
, «вывод». Таким образом, эта команда:
certtool d myfoo.crt
(В моем случае расширение файла просто оказывается .crt
, а не .pem
… это не имеет значения.)
… выдает вывод, который, в соответствующей части, выглядит как:
Общее имя : Foobar
Несомненно, goldilocks был прав: вывод certtool
гораздо проще для работы, чем openssl
в этом случае.
Старый вопрос, но я нашел, что некоторые сертификаты имеют значения, которые отображаются openssl на той же строке, что и commonName, разделенные знаком +.
Я думаю, что это зависит от того, как формируется общее имя субъекта — похоже, возможно сделать значение CN последовательностью из нескольких подзначений.
Примером этого является emailAddress, который может выглядеть как commonName=Joe Bloggs + [email protected]
, даже при использовании -nameopt multiline.
Чтобы обойти это, моим альтернативным подходом является использование openssl asn1parse
:
openssl asn1parse -in '/pathto/thecert.crt' |\
awk -v FS=':' -v OFS='' '
BEGIN {e=0}
e==2 {$1="";$2="";$3="";print;exit}
/:commonName$/ {e++}
'
Я закончил использованием:
openssl x509 -inform DER -noout -subject -nameopt oneline,-esc_msb -in test.pem | sed 's/.*CN = //' | sed 's/, OU =.*$//' | sed 's/\"//g'
Обратите внимание на -nameopt oneline,-esc_msb
, что позволяет получить правильный вывод, когда CN (общее имя) содержит специальные символы, например акценты.
sed 's/.*CN = //'
удаляет первую часть до CN =
sed 's/, OU =.*$//'
удаляет последнюю часть от , OU =
sed 's/\"//g'
удаляет кавычки, если они есть; заметил, что иногда CN идет с кавычками, а иногда нет.
Я уверен, что есть более приятные и короткие способы сделать это, но этот способ сработал для меня.
Я использовал:
openssl x509 -noout -subject -in mycert.crt | awk -F= '{print $NF}'
и добавил | sed -e 's/^[ \t]*//'
, если вы не можете мириться с пробелами
Что касается извлечения самого CN из DN субъекта/выдавателя, я не смог получить регулярное выражение, которое обрабатывало бы:
- CN, содержащие подстановочные знаки
- и CN, содержащие встроенные пробелы
Поэтому этот сценарий bash:
- разделяет строку выдающего на
,
на массив - перебирает массив, чтобы найти атрибут DN, начинающийся с
CN
- удаляет
CN=
с начала атрибута
Скрипт bash:
issuer_dn=$(openssl x509 -in cert.pem -text -noout | grep "Issuer:" | sed -e 's/Issuer\: //')
IFS=','; attributes=(${issuer_dn}); unset IFS;
for attribute in "${attributes[@]}"; do
# обрезать начальные пробелы
attribute=$(echo "${attribute}" | sed -e 's/^\s*//')
# удалить 'CN=' с начала атрибута
[[ "${attribute}" == CN* ]] && cn="${attribute#*CN=}" && break
done
issuer_dn: C=NA, ST=NP, L=Wellers, O=Team, OU=Testing, CN=foo.example.com
cn: foo.example.com
issuer_dn: C=NA, ST=NP, L=Wellers, O=Team, CN=foo*.example.com, OU=Testing
cn: foo*.example.com
issuer_dn: C=NA, ST=NP, L=Wellers, O=Team, CN=Joe Bloggs, OU=Testing
cn: Joe Bloggs
Я использую эту команду для извлечения CN из сертификата :
openssl x509 -noout -subject -nameopt multiline -in certificateName.pem | grep commonName | cut -d= -f2 | sed 's/^ *//g'
Первая часть считывает сертификат и извлекает субъект (-subject) и форматирует результат на разных строках (-nameopt multiline).
Вторая часть выбирает только ту строку, которая содержит “commonName”
Третья часть обрезает и берет только после знака равенства (” commonName = my.cn.com”)
А последняя удаляет пробелы в начале (проблема форматирования).
Ответ или решение
Чтобы извлечь общее имя (CN) из SSL-сертификата в формате PEM с помощью командной строки, можно воспользоваться утилитой openssl
, которая широко используется для работы с сертификатами. Ниже представлены несколько методов для выполнения этой задачи.
Метод 1: Использование OpenSSL
- Установите OpenSSL, если он еще не установлен. В большинстве дистрибутивов Linux он уже включен.
- Введите следующую команду для извлечения информации о субъекте сертификата:
openssl x509 -noout -subject -in ваш_сертификат.pem
Эта команда выведет информацию о субъекте сертификата. Обратите внимание, что вы получите результат в несколько строк. Чтобы извлечь только общее имя (CN), вы можете использовать awk
:
openssl x509 -noout -subject -in ваш_сертификат.pem | awk -F'=' '/CN/ {print $2}'
Метод 2: Использование certtool
Если у вас установлен пакет GnuTLS, вы можете использовать certtool
, который более удобен в данном случае:
certtool -i < ваш_сертификат.pem | grep "Subject:"
Это демонстрирует всю информацию о субъекте, и для поиска CN можно использовать grep
или awk
.
Также вы можете использовать более новую версию команды, если командный синтаксис изменился:
certtool d ваш_сертификат.pem
Метод 3: Использование командной строки для более сложных случаев
В некоторых случаях CN может содержать пробелы или специальные символы. Для этого можно воспользоваться следующим скриптом на Bash:
issuer_dn=$(openssl x509 -in ваш_сертификат.pem -text -noout | grep "Subject:" | sed -e 's/Subject: //')
IFS=','; attributes=(${issuer_dn}); unset IFS;
for attribute in "${attributes[@]}"; do
attribute=$(echo "${attribute}" | sed -e 's/^\s*//')
[[ "${attribute}" == CN* ]] && cn="${attribute#*CN=}" && break
done
echo $cn
Этот скрипт разбивает строку субъекта, ищет атрибут, начинающийся с CN, и извлекает его значение.
Заключение
Существует множество способов извлечь общее имя (CN) из SSL-сертификата в формате PEM. Методы с использованием openssl
и certtool
являются наиболее распространенными. В зависимости от вашего конкретного случая, вы можете выбрать любой из предложенных методов, чтобы успешно получить необходимую информацию из сертификата.