Как извлечь значение подписи из сертификата в PHP

у меня есть сертификат:

-----BEGIN CERTIFICATE-----
MIIEvzCCBGSgAwIBAgITeAAARlJXpwVPUYDkbAABAABGUjAKBggqhkjOPQQDAjBi
MRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxEzARBgoJkiaJk/IsZAEZFgNnb3YxFzAV
BgoJkiaJk/IsZAEZFgdleHRnYXp0MRswGQYDVQQDExJQRVpFSU5WT0lDRVNDQTQt
Q0EwHhcNMjQwNzAyMDMxMTE2WhcNMjYwNzAyMDMyMTE2WjBJMQswCQYDVQQGEwJT
QTESMBAGA1UEChMJZnJlZSB0ZXh0MRIwEAYDVQQLEwlmcmVlIHRleHQxEjAQBgNV
BAMTCWZyZWUgdGV4dDBWMBAGByqGSM49AgEGBSuBBAAKA0IABP/Lh6KN1Y5Z6CzW
+3hLkwGLUyorKQoCCQZzrbtvHNLocvv7OFDUHZZiOnwzhavZLkOEPjH8ojIH1kb1
A4LsTEejggMTMIIDDzB+BgNVHREEdzB1pHMwcTEgMB4GA1UEBAwXMS1TaGFFa3wy
LVNoYUVrfDMtU2hhRWsxHzAdBgoJkiaJk/IsZAEBDA8zMTExOTAyOTM3MDAwMDMx
DTALBgNVBAwMBDExMDAxDjAMBgNVBBoMBWphemFuMQ0wCwYDVQQPDARUZWNoMB0G
A1UdDgQWBBQJ9H6ej6E1lbOuT+RG6WI9yHrdATAfBgNVHSMEGDAWgBTHwOa3qd0S
yk89bWiCliFF8wF1pDCB5QYDVR0fBIHdMIHaMIHXoIHUoIHRhoHObGRhcDovLy9D
Tj1QRVpFSU5WT0lDRVNDQTQtQ0EoMSksQ049UFJaRUlOVk9JQ0VQS0k0LENOPUNE
UCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25m
aWd1cmF0aW9uLERDPWV4dHphdGNhLERDPWdvdixEQz1sb2NhbD9jZXJ0aWZpY2F0
ZVJldm9jYXRpb25MaXN0P2Jhc2U/b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9u
UG9pbnQwgc4GCCsGAQUFBwEBBIHBMIG+MIG7BggrBgEFBQcwAoaBrmxkYXA6Ly8v
Q049UEVaRUlOVk9JQ0VTQ0E0LUNBLENOPUFJQSxDTj1QdWJsaWMlMjBLZXklMjBT
ZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9uLERDPWV4dHphdGNh
LERDPWdvdixEQz1sb2NhbD9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xhc3M9
Y2VydGlmaWNhdGlvbkF1dGhvcml0eTAOBgNVHQ8BAf8EBAMCB4AwPAYJKwYBBAGC
NxUHBC8wLQYlKwYBBAGCNxUIgYaoHYTQ+xKG7Z0kh877GdPAVWaBnNgtg+XFXQIB
ZAIBEDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwMwJwYJKwYBBAGCNxUK
BBowGDAKBggrBgEFBQcDAjAKBggrBgEFBQcDAzAKBggqhkjOPQQDAgNJADBGAiEA
2sVgVJidhX8lnKshVB4JL7YBY+F1p48JI7NPpO4xJDQCIQCWf97LYNEK7358msfA
RK1iTp3om8fnJ33A59SurRjENA==
-----END CERTIFICATE-----

и я хочу получить значение подписи, указанное в этом сертификате.

Я попробовал много решений, и это наиболее близко к необходимому результату.


$cert = openssl_x509_read($certificate);

openssl_x509_export($cert, $out, FALSE);

echo $out;

это решение дает мне всю информацию о сертификате, а также подпись с ним, но в виде строки:


Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            78:00:00:46:52:57:a7:05:4f:51:80:e4:6c:00:01:00:00:46:52
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: DC=local, DC=gov, DC=extgazt, CN=PEZEINVOICESCA4-CA
        Validity
            Not Before: Jul  2 03:11:16 2024 GMT
            Not After : Jul  2 03:21:16 2026 GMT
        Subject: C=SA, O=free text, OU=free text, CN=free text
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:ff:cb:87:a2:8d:d5:8e:59:e8:2c:d6:fb:78:4b:
                    93:01:8b:53:2a:2b:29:0a:02:09:06:73:ad:bb:6f:
                    1c:d2:e8:72:fb:fb:38:50:d4:1d:96:62:3a:7c:33:
                    85:ab:d9:2e:43:84:3e:31:fc:a2:32:07:d6:46:f5:
                    03:82:ec:4c:47
                ASN1 OID: secp256k1
        X509v3 extensions:
            X509v3 Subject Alternative Name: 
                DirName:/SN=1-ShaEk|2-ShaEk|3-ShaEk/UID=311190293700003/title=1100/registeredAddress=jazan/businessCategory=Tech
            X509v3 Subject Key Identifier: 
                09:F4:7E:9E:8F:A1:35:95:B3:AE:4F:E4:46:E9:62:3D:C8:7A:DD:01
            X509v3 Authority Key Identifier: 
                keyid:C7:C0:E6:B7:A9:DD:12:CA:4F:3D:6D:68:82:96:21:45:F3:01:75:A4

            X509v3 CRL Distribution Points: 

                Full Name:
                  URI:ldap:///CN=PEZEINVOICESCA4-CA(1),CN=PRZEINVOICEPKI4,CN=CDP,CN=Public%20Key%20Services,CN=Services,CN=Configuration,DC=extzatca,DC=gov,DC=local?certificateRevocationList?base?objectClass=cRLDistributionPoint

            Authority Information Access: 
                CA Issuers - URI:ldap:///CN=PEZEINVOICESCA4-CA,CN=AIA,CN=Public%20Key%20Services,CN=Services,CN=Configuration,DC=extzatca,DC=gov,DC=local?cACertificate?base?objectClass=certificationAuthority

            X509v3 Key Usage: critical
                Digital Signature
            1.3.6.1.4.1.311.21.7: 
                0-.%+.....7.............$......Uf...-...]..d...
            X509v3 Extended Key Usage: 
                TLS Web Client Authentication, Code Signing
            1.3.6.1.4.1.311.21.10: 
                0.0
..+.......0
..+.......
    Signature Algorithm: ecdsa-with-SHA256
         30:46:02:21:00:da:c5:60:54:98:9d:85:7f:25:9c:ab:21:54:
         1e:09:2f:b6:01:63:e1:75:a7:8f:09:23:b3:4f:a4:ee:31:24:
         34:02:21:00:96:7f:de:cb:60:d1:0a:ef:7e:7c:9a:c7:c0:44:
         ad:62:4e:9d:e8:9b:c7:e7:27:7d:c0:e7:d4:ae:ad:18:c4:34

это значение подписи:

проблема теперь в том, что это строка, есть ли способ проще, который дает мне объект или что-то в этом роде?

я тоже пробовал openssl_x509_parse, но подпись не даёт

@brombeer показывает всю информацию о сертификате, не извлекая «только значение подписи».

momo 03.07.2024 10:13

Если вы можете изменить библиотеку: phpseclib позволяет напрямую определять подпись сертификата.

Topaco 03.07.2024 11:21

@Topaco, можешь ли ты дать мне пример документации? пожалуйста

momo 03.07.2024 11:53

@Topaco огромное тебе спасибо, чувак, ты лучший, я использовал это, и это сработало. если хотите, вы можете написать это как ответ, чтобы принять его.

momo 03.07.2024 12:02

Пожалуйста. Я оставил свой комментарий в качестве ответа.

Topaco 03.07.2024 13:07

Вы же не проводите проверку сертификата сами, не так ли? Это гораздо больше, чем просто проверка подписей. Базовая проверка пути описана в RFC 5280, раздел 6, но проверка — это нечто большее, чем просто проверка пути. Задавать вопросы о том, как получить подпись из сертификата X509, — это явный признак того, что вы недостаточно знакомы с PKI на основе X509, чтобы выполнять пользовательскую проверку. Замечательно, если вы пытаетесь научиться это делать, поскольку это очень полезные знания, но ваша первая попытка — это не то, что вы хотите использовать по-настоящему.

Andrew Henle 04.07.2024 01:06

@AndrewHenle Спасибо за ваш комментарий, проблема в том, что у меня есть проект по работе со счетами, и эти счета должны быть электронными, и они просят включить подпись сертификата в определенное поле счета. это все.

momo 04.07.2024 01:11

@momo Проверка соответствия подписи некоторого сертификата X509 набору байтов ничего не проверяет — сертификаты X509 являются общедоступными. Вы можете получить биты подписи из сертификата X509, который Google использует для своей поисковой системы, и наличие этих битов не доказывает, что вы Google. Что вам нужно сделать, так это попросить создателя счета использовать свой закрытый ключ, чтобы подписать некоторые данные в счете указанным способом. Именно так они доказывают, кто они есть: у них есть закрытый ключ, который нужно было использовать для создания этой подписи.

Andrew Henle 04.07.2024 02:45

(продолжение) Затем вы используете открытый ключ сертификата X509 для проверки подписи. И если вы проверите X509 по доверенной цепочке сертификатов, это подтвердит ваше доверие к X509. Если я дам вам 30:64:02:30:13:19:f0:9f:88:d6:e9:e5:88:82:... байты подписи из stackoverflow.com X509 в вашем электронном счете, это ничего не докажет.

Andrew Henle 04.07.2024 02:49

(продолжение) Вы можете использовать echo | openssl s_client -connect stackoverflow.com:443 -servername stackoverflow.com | openssl x509 -noout -text, чтобы увидеть информацию о сертификате stackoverflow.com X509, включая подпись.

Andrew Henle 04.07.2024 02:51

@AndrewHenle Спасибо, Эндрю, но проблема в том, что я создаю клиентскую службу, а эту спецификацию создало правительство, и они просто сказали: просто поставьте подпись в счете-фактуре, а затем отправьте его нам... если честно, они творили сумасшедшие вещи, но мы ничего не можем сказать.

momo 04.07.2024 03:04
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
11
92
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

phpseclib позволяет напрямую определять подпись сертификата, s. Чтение сертификатов в документации phpseclib.

Сертификат загружается с помощью X509#loadX509(), который возвращает массив с тремя полями сертификата tbsCertificate, signatureAlgorithm и signature (см. RFC 5280). Последний содержит подпись.

Образец кода:

use phpseclib3\File\X509;

$certPem = "-----BEGIN CERTIFICATE-----
MIIEvzCCBGSgAwIBAgITeAAARlJXpwVPUYDkbAABAABGUjAKBggqhkjOPQQDAjBi
MRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxEzARBgoJkiaJk/IsZAEZFgNnb3YxFzAV
BgoJkiaJk/IsZAEZFgdleHRnYXp0MRswGQYDVQQDExJQRVpFSU5WT0lDRVNDQTQt
Q0EwHhcNMjQwNzAyMDMxMTE2WhcNMjYwNzAyMDMyMTE2WjBJMQswCQYDVQQGEwJT
QTESMBAGA1UEChMJZnJlZSB0ZXh0MRIwEAYDVQQLEwlmcmVlIHRleHQxEjAQBgNV
BAMTCWZyZWUgdGV4dDBWMBAGByqGSM49AgEGBSuBBAAKA0IABP/Lh6KN1Y5Z6CzW
+3hLkwGLUyorKQoCCQZzrbtvHNLocvv7OFDUHZZiOnwzhavZLkOEPjH8ojIH1kb1
A4LsTEejggMTMIIDDzB+BgNVHREEdzB1pHMwcTEgMB4GA1UEBAwXMS1TaGFFa3wy
LVNoYUVrfDMtU2hhRWsxHzAdBgoJkiaJk/IsZAEBDA8zMTExOTAyOTM3MDAwMDMx
DTALBgNVBAwMBDExMDAxDjAMBgNVBBoMBWphemFuMQ0wCwYDVQQPDARUZWNoMB0G
A1UdDgQWBBQJ9H6ej6E1lbOuT+RG6WI9yHrdATAfBgNVHSMEGDAWgBTHwOa3qd0S
yk89bWiCliFF8wF1pDCB5QYDVR0fBIHdMIHaMIHXoIHUoIHRhoHObGRhcDovLy9D
Tj1QRVpFSU5WT0lDRVNDQTQtQ0EoMSksQ049UFJaRUlOVk9JQ0VQS0k0LENOPUNE
UCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25m
aWd1cmF0aW9uLERDPWV4dHphdGNhLERDPWdvdixEQz1sb2NhbD9jZXJ0aWZpY2F0
ZVJldm9jYXRpb25MaXN0P2Jhc2U/b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9u
UG9pbnQwgc4GCCsGAQUFBwEBBIHBMIG+MIG7BggrBgEFBQcwAoaBrmxkYXA6Ly8v
Q049UEVaRUlOVk9JQ0VTQ0E0LUNBLENOPUFJQSxDTj1QdWJsaWMlMjBLZXklMjBT
ZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9uLERDPWV4dHphdGNh
LERDPWdvdixEQz1sb2NhbD9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xhc3M9
Y2VydGlmaWNhdGlvbkF1dGhvcml0eTAOBgNVHQ8BAf8EBAMCB4AwPAYJKwYBBAGC
NxUHBC8wLQYlKwYBBAGCNxUIgYaoHYTQ+xKG7Z0kh877GdPAVWaBnNgtg+XFXQIB
ZAIBEDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwMwJwYJKwYBBAGCNxUK
BBowGDAKBggrBgEFBQcDAjAKBggrBgEFBQcDAzAKBggqhkjOPQQDAgNJADBGAiEA
2sVgVJidhX8lnKshVB4JL7YBY+F1p48JI7NPpO4xJDQCIQCWf97LYNEK7358msfA
RK1iTp3om8fnJ33A59SurRjENA==
-----END CERTIFICATE-----";

$x509 = new X509();
$cert = $x509->loadX509($certPem);
$signature = $cert["signature"];
print(bin2hex($signature) . PHP_EOL); // 003046022100dac56054989d857f259cab21541e092fb60163e175a78f0923b34fa4ee312434022100967fdecb60d10aef7e7c9ac7c044ad624e9de89bc7e7277dc0e7d4aead18c434

$signature = substr($signature, 1);   // remove leading 0x00
print(bin2hex($signature) . PHP_EOL); // 3046022100dac56054989d857f259cab21541e092fb60163e175a78f0923b34fa4ee312434022100967fdecb60d10aef7e7c9ac7c044ad624e9de89bc7e7277dc0e7d4aead18c434

Для опубликованного сертификата подпись представляет собой подпись ECDSA в формате ASN.1/DER, которую можно проанализировать с помощью анализатора ASN.1, например вот .

Обратите внимание, что по какой-то причине в начале добавляется ведущий 0x00 (возможно, последний байт предыдущей BIT STRING кодировки 0x034900, s. здесь), который следует удалить для правильного формата подписи ASN.1/DER.

спасибо, насчет 0x00, который стоит в первом, я думаю, это пробел, я избавился от него с помощью обрезки вот так: bin2hex(trim($cert["signature"]))

momo 03.07.2024 13:16

@момо, не делай этого. обрезка удалит законные байты из некоторых подписей, сделав их недействительными. Кажется, это работает, потому что 0x00 - это один из байтов, который удаляет обрезка, но он удаляет как в начале, так и в конце, и не останавливается после первого.

Peter 03.07.2024 13:28

@momo — подписи ECDSA в кодировке ASN.1/DER начинаются с 0x30 (SEQUENCE), поэтому ltrim() (но не trim(), комментарий Питера) будет вариантом. Однако другие подписи (например, RSA) вполне могут иметь ведущие значения 0x00, которые являются частью подписи, так что даже ltrim() может удалить слишком много. Поэтому более надежно удалить ведущий байт 0x00.

Topaco 03.07.2024 14:50

@Topaco, спасибо, но как это решить?

momo 04.07.2024 00:42

@momo — Просто используйте substr(..., 1) вместо trim()/ltrim().

Topaco 04.07.2024 06:53

Другие вопросы по теме