Я хочу проверить подписанный pgp текст в PHP. Следующая документация PHP и ответ на этот вопрос я сделал простой скрипт для проверки библиотеки gnupg. Я отправил подписанную электронную почту между двумя учетными записями электронной почты, используя Thunderbird и Enigmail — получение Thunderbird показывает, что подпись верна.
В PHP, когда я использую обычный текст электронной почты и открытый ключ отправителей, verify()
функция возвращает массив следующим образом:
array(1) {
[0]=>
array(5) {
["fingerprint"]=>
string(40) "468F82339FC55DE5CAFD71BB63DD32AE1308A57F"["validity"]=>
int(0)
["timestamp"]=>
int(1443033896)
["status"]=>
int(0)
["summary"]=>
int(0)
}
}
Когда я изменяю в подписанном сообщении одно слово, результат изменяется на:
array(1) {
[0]=>
array(5) {
["fingerprint"]=>
string(16) "63DD32AE1308A57F"["validity"]=>
int(0)
["timestamp"]=>
int(0)
["status"]=>
int(117440520)
["summary"]=>
int(4)
}
}
И наконец, когда я изменяю много текста или сломал подпись, функция возвращает false
,
Итак, что означают эти значения массива?
validity
всегда 0
?timestamp
значение является временной меткой чего? Время, когда сообщение было подписано?status
значение настолько велико во втором случае? Это просто случайное значение или конкретный код ошибки?summary
что стоит ценность 4
за?Если я просто хочу узнать, правильно ли подписан текст или нет, могу ли я просто сравнить возвращенный fingerprint
с отпечатком открытого ключа и проверьте, равны ли статус и сводка 0
?
Документация PHP GnuPG действительно не хватает информации здесь. Глядя на исходный код и руководство GPGME и источники, вы можете получить соответствующую информацию.
Отказ от ответственности: Ответ содержит некоторые догадки, конечно, чтобы получить разумное представление о том, что происходит, если опираться на него, и не стесняйтесь оставлять отзывы!
Почему срок действия всегда равен 0?
Для проверки validity
подписи, вам нужно назначить доверие (чтобы GnuPG мог вычислить цепочку доверия). срок действия определен в следующих перечислениях GPGME:
/* The available validities for a trust item or key. */
typedef enum
{
GPGME_VALIDITY_UNKNOWN = 0,
GPGME_VALIDITY_UNDEFINED = 1,
GPGME_VALIDITY_NEVER = 2,
GPGME_VALIDITY_MARGINAL = 3,
GPGME_VALIDITY_FULL = 4,
GPGME_VALIDITY_ULTIMATE = 5
}
gpgme_validity_t;
значение временной метки является временной меткой чего? Время, когда сообщение было подписано?
Да, это легко, это метка времени создания подписи. Имейте в виду, что метка времени обычно определяется подписывающей стороной и может быть подделана на произвольные даты.
То же самое с резюме, что означает значение 4?
Чтение документация (gpgme_error_t status
), похоже статус определяется в gpg-error.h
, Это очень длинный список, размещенный в Git-репозитории GnuPG.
Тем не менее, определенный статус в вашем вопросе не имеет смысла для меня.
Почему значение статуса так велико во втором случае? Это просто случайное значение или конкретный код ошибки?
Это резюме на подпись. Опять же, резюме определяется в перечислении GPGME:
/* Flags used for the SUMMARY field in a gpgme_signature_t. */
typedef enum
{
GPGME_SIGSUM_VALID = 0x0001, /* The signature is fully valid. */
GPGME_SIGSUM_GREEN = 0x0002, /* The signature is good. */
GPGME_SIGSUM_RED = 0x0004, /* The signature is bad. */
GPGME_SIGSUM_KEY_REVOKED = 0x0010, /* One key has been revoked. */
GPGME_SIGSUM_KEY_EXPIRED = 0x0020, /* One key has expired. */
GPGME_SIGSUM_SIG_EXPIRED = 0x0040, /* The signature has expired. */
GPGME_SIGSUM_KEY_MISSING = 0x0080, /* Can't verify: key missing. */
GPGME_SIGSUM_CRL_MISSING = 0x0100, /* CRL not available. */
GPGME_SIGSUM_CRL_TOO_OLD = 0x0200, /* Available CRL is too old. */
GPGME_SIGSUM_BAD_POLICY = 0x0400, /* A policy was not met. */
GPGME_SIGSUM_SYS_ERROR = 0x0800 /* A system error occured. */
}
gpgme_sigsum_t;
Таким образом, вы должны прочитать результат как двоичные флаги. Статус 4 указывает на плохую подпись.
Первая подпись была сгенерирована несколько дней назад 2015-09-23T18: 44: 56 + 00: 00 по ключу 468F82339FC55DE5CAFD71BB63DD32AE1308A57F
и является правильной подписью, но ключ может быть проверен (отсутствует путь доверия).
Вторая подпись, похоже, выдается тем же ключом, но не работает.
Если я просто хочу узнать, правильно ли подписан текст или нет, могу ли я просто сравнить возвращенный отпечаток с отпечатком открытого ключа и проверить, равны ли статус и сводка 0?
Насколько я понимаю, что происходит, вы должны проверить, summary
Бит 4 установлен или нет. Если он установлен, у вас плохая подпись. Не сравнивайте его с 4, но используйте битовую манипуляцию для проверки одного бита:
($summary & 0x04) == 0x04
Если вы не используете сеть доверия и validity
Установите флажок для проверки подписи, убедитесь, что сравнили весь отпечаток со списком доверенных ключей.
Других решений пока нет …