Глоссарий / Справочник разработчика
PaymentRequest
- Что такое PaymentRequest?
- PaymentRequest представляет собой внешний конверт BIP70: он оборачивает сериализованный блок PaymentDetails вместе с цепочкой сертификатов и подписью, чтобы плательщик мог проверить, кто именно выставил требование.
Определено в BIP-70.
PaymentRequest был сообщением, которое позволяло кошельку показать название компании вместо строки символов. В нем было пять полей, и два из них имели значение: pki_type, принимавшее одно из значений none, x509+sha256 или x509+sha1, и signature, подпись над сериализованными данными. Для того, кто платит сегодня, урок пережил сам протокол: имя на экране оплаты надежно ровно настолько, насколько надежен тот, кто за него поручился.
Как это работает
Статус: устарело. Bitcoin Core поддерживал обработку PaymentRequest начиная с версии 0.9.0, пока версия 0.20.0 не удалила ее 3 июня 2020 года, и сейчас ни один поддерживаемый кошелек не разбирает это сообщение.
Пять полей, по порядку:
payment_details_version, целое число размером 32 бита со значением по умолчанию 1. Оно никогда не увеличивалось.pki_type, строка со значением по умолчанию "none". Альтернативами были "x509+sha256" и "x509+sha1".pki_data, содержащее структуру X509Certificates, где первым идет конечный сертификат продавца, а за ним любые промежуточные.serialized_payment_details, обязательное, непрозрачная строка байтов, описанная в другом месте этого глоссария.signature, байты, доказывающие, что все это исходит от владельца сертификата.
В процедуре подписания есть небольшая хитрость. Продавец заполняет все поля, оставляет signature пустым, сериализует полное сообщение, вычисляет его хеш, подписывает этот хеш приватным ключом, соответствующим конечному сертификату, и затем записывает подпись в поле, которое только что оставил пустым. Проверяющий снова очищает это поле, повторно сериализует сообщение и проверяет подпись. Просто, самодостаточно и не зависит ни от чего, кроме сертификата.
Проблемой была именно эта зависимость. Чтобы проверить цепочку, кошелек должен был хранить набор корневых сертификатов, который настольное программное обеспечение наследовало от операционной системы, а мобильное часто настраивало неправильно. Даже корректная реализация доказывала лишь то, что некий удостоверяющий центр засвидетельствовал доменное имя, а набор корневых сертификатов содержит сотни центров, и любой из них может выпустить сертификат на любое имя. Самый слабый из предложенных вариантов, x509+sha1, особенно плохо перенес время: практическая коллизия SHA-1 была опубликована 23 февраля 2017 года, через четыре года после того, как был написан BIP70.
Где это встречается
Название PaymentRequest до сих пор используется в двух местах, и только одно из них связано с биткоином.
К первому относятся архивный код и документация, где MIME-тип BIP71 application/bitcoin-paymentrequest помечал ответ, который возвращал сервер продавца. Ко второму относится современная веб-платформа, где PaymentRequest обозначает браузерный API для оплаты картой и сохраненными платежными данными, не имеющий к этому протоколу никакого отношения. Разработчик, использующий это слово сегодня, почти наверняка имеет в виду браузерный API, и путаница между ними является самой распространенной ошибкой при поиске старой документации по биткоину.
Для того, кто покупает биткоин, вывод касается того, как к платежам привязывается личность. Криптобиржи решают это счетами и верификацией личности (KYC), так что платформа знает, кто вы, а вы полагаетесь на репутацию платформы. Самостоятельное хранение решает это тем, что проверять адрес вы должны сами. BIP70 пробовал третий путь, заимствуя систему сертификатов веба, и этот путь закрыт.
PaymentRequest vs PaymentDetails
PaymentRequest является конвертом; PaymentDetails представляет собой письмо внутри него. Чтение конверта говорит, кто подписал и какой сертификат использовал, но не говорит, что именно требуется. Суммы, скрипты, срок действия и примечание находятся во внутреннем сообщении, которое лежит в конверте как неразобранная строка байтов именно для того, чтобы подпись нельзя было аннулировать повторным кодированием. Кошелек должен был проверить первое, прежде чем доверять чему-либо во втором.