Получить общее имя (CN) из SSL-сертификата?

Вопрос или проблема

У меня есть файл 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

  1. Установите OpenSSL, если он еще не установлен. В большинстве дистрибутивов Linux он уже включен.
  2. Введите следующую команду для извлечения информации о субъекте сертификата:
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 являются наиболее распространенными. В зависимости от вашего конкретного случая, вы можете выбрать любой из предложенных методов, чтобы успешно получить необходимую информацию из сертификата.

Оцените материал
Добавить комментарий

Капча загружается...