Я должен отлаживать старый PHP-скрипт от разработчика, который покинул компанию. Я понимаю большую часть кода, за исключением следующей функции. Мой вопрос: что …
if ($ seq == 0x03 || $ seq == 0x30)
- Как подписать сертификат X.509 с RS256 в PHP? Не удалось получить действительный отпечаток пальца ... x5t
- Почему разные строки частного ключа в Linux или Windows?
- Нужен ли OpenSSL путь к openssl.conf?
- Установка сервера ns-cert-type для OpenVPN с использованием phpseclib
- Как создать цифровой сертификат и экспортировать в файл .p12 в PHP?
… означает в контексте извлечения подписи из сертификата X.509?
public function extractSignature($certPemString) { $bin = $this->ConvertPemToBinary($certPemString); if(empty($certPemString) || empty($bin)) { return false; } $bin = substr($bin,4); while(strlen($bin) > 1) { $seq = ord($bin[0]); if($seq == 0x03 || $seq == 0x30) { $len = ord($bin[1]); $bytes = 0; if ($len & 0x80) { $bytes = ($len & 0x0f); $len = 0; for ($i = 0; $i < $bytes; $i++) { $len = ($len << 8) | ord($bin[$i + 2]); } } if($seq == 0x03) { return substr($bin,3 + $bytes, $len); } else { $bin = substr($bin,2 + $bytes + $len); } } else { return false; } } return false; }
Сертификат X.509 содержит данные в нескольких разделах (так называемые триплеты Tag-Length-Value). Каждый раздел начинается с байта тега, который указывает формат данных раздела. Здесь вы можете увидеть список этих типов данных.
0x03 – это байт Tag для типа данных BIT STRING , а 0x30 – байт Tag для типа данных SEQUENCE .
Таким образом, этот код предназначен для обработки типов данных BIT STRING и SEQUENCE. Если вы посмотрите на эту часть:
if($seq == 0x03) { return substr($bin,3 + $bytes, $len); } else // $seq == 0x30 { $bin = substr($bin,2 + $bytes + $len); }
вы можете видеть, что функция предназначена для пропуска по последовательностям (0x30), пока не найдет бит-строку (0x03), после чего она вернет значение бит-строки.
Возможно, вам интересно, почему магическое число равно 3 для бит-строки и 2 для последовательности . Это связано с тем, что в бит-строке первый байтовый байт представляет собой специальное дополнительное поле, которое указывает, сколько бит не используется в последнем байте данных. (Например, если вы отправляете 13 бит данных, это займет 2 байта = 16 бит, а поле « неиспользуемые биты » будет равно 3.)
Следующий выпуск: поле Длина. Когда длина значения меньше 128 байт, длина просто указывается с использованием одного байта (самый старший бит будет равен 0). Если длина равна 128 или выше, то первый байт длины имеет бит 7, а остальные 7 бит указывают, сколько последующих байтов содержит длину (в порядке возрастания). Более подробное описание здесь . Разбор поля длины происходит в этом разделе кода:
$len = ord($bin[1]); $bytes = 0; if ($len & 0x80) { // length is greater than 127! $bytes = ($len & 0x0f); $len = 0; for ($i = 0; $i < $bytes; $i++) { $len = ($len << 8) | ord($bin[$i + 2]); } }
После этого $bytes
содержат количество дополнительных байтов, используемых полем длины, а $len
содержит длину поля Value (в байтах).
Вы заметили ошибку в коде? Запомнить,
Если длина равна 128 или выше, то первый байт длины имеет бит 7, а остальные 7 бит указывают, сколько последующих байтов содержит длину.
но код говорит $bytes = ($len & 0x0f)
, который берет только младшие 4 бита байта! Должен быть:
$bytes = ($len & 0x7f);
Конечно, эта ошибка является лишь проблемой для чрезвычайно длинных сообщений: она будет работать нормально до тех пор, пока значение длины будет соответствовать 0x0f = 15 байт, то есть данные должны быть меньше 256 ^ 15 байт. Это около триллиона лет, что должно быть достаточно для всех.
Как говорит Патман, вы просто имеете логическое, если мы просто проверяем, является ли $seq
0x30 или 0x03.
У меня такое чувство, что вы уже знаете это, так что вот так. $seq
– это первый байт сертификата, который, вероятно, является либо версией сертификата, либо магическим номером, чтобы обозначить, что этот файл является сертификатом (также известный как «Я предполагаю это, потому что 10:45 некогда начинать чтение RFC ").
В этом случае мы сравниваем 0x30 и 0x03. Эти числа выражаются в шестнадцатеричном виде (как и каждое число, начинающееся с 0x), которое является базовым 16. Это просто очень удобное сокращение двоичного кода, так как каждая шестнадцатеричная цифра соответствует ровно четырем двоичным битам. Быстрый стол:
0 = 0000 1 = 0001 2 = 0010 3 = 0011 ... ... E = 1110 F = 1111
В равной степени мы могли бы сказать, что if($seq == 3 || $seq == 48)
, но в этом случае шестеро проще читать и понимать.
Я бы рискнул предположить, что это байтовая независимая проверка для идентификатора версии «3» в сертификате x.509. См. RFC 1422 , стр. 7. Остальное вытягивает байт по-байт.
ord () получает значение символа ASCII, который вы передаете. В этом случае он проверяет, является ли символ ASCII либо 0, либо окончанием текста (в соответствии с этой таблицей ASCII ).
0x03 и 0x30 – шестнадцатеричные значения. Посмотрите это, и у вас будет то, что $ seq соответствует