From 85973bcc44f60fe3bbc952557ebf578dd4c475d2 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Wed, 11 Sep 2019 03:37:44 -0400 Subject: [PATCH] When BIP70 is disabled, get PaymentRequest merchant using string search The merchant name is stored in the X.509 certificate embedded in a PaymentRequest. Use some string searching to locate it so that it can be shown to the user in the transaction details when BIP70 support was not configured. --- src/qt/transactiondesc.cpp | 58 +++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index ebe79253683..648fdb76739 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -49,6 +49,36 @@ QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const i } } +#ifndef ENABLE_BIP70 +// Takes an encoded PaymentRequest as a string and tries to find the Common Name of the X.509 certificate +// used to sign the PaymentRequest. +bool GetPaymentRequestMerchant(const std::string& pr, QString& merchant) +{ + // Search for the supported pki type strings + if (pr.find(std::string({0x12, 0x0b}) + "x509+sha256") != std::string::npos || pr.find(std::string({0x12, 0x09}) + "x509+sha1") != std::string::npos) { + // We want the common name of the Subject of the cert. This should be the second occurrence + // of the bytes 0x0603550403. The first occurrence of those is the common name of the issuer. + // After those bytes will be either 0x13 or 0x0C, then length, then either the ascii or utf8 + // string with the common name which is the merchant name + size_t cn_pos = pr.find({0x06, 0x03, 0x55, 0x04, 0x03}); + if (cn_pos != std::string::npos) { + cn_pos = pr.find({0x06, 0x03, 0x55, 0x04, 0x03}, cn_pos + 5); + if (cn_pos != std::string::npos) { + cn_pos += 5; + if (pr[cn_pos] == 0x13 || pr[cn_pos] == 0x0c) { + cn_pos++; // Consume the type + int str_len = pr[cn_pos]; + cn_pos++; // Consume the string length + merchant = QString::fromUtf8(pr.data() + cn_pos, str_len); + return true; + } + } + } + } + return false; +} +#endif + QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord *rec, int unit) { int numBlocks; @@ -255,26 +285,34 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall strHTML += "" + tr("Output index") + ": " + QString::number(rec->getOutputIndex()) + "
"; // Message from normal bitcoin:URI (bitcoin:123...?message=example) - for (const std::pair& r : orderForm) + for (const std::pair& r : orderForm) { if (r.first == "Message") strHTML += "
" + tr("Message") + ":
" + GUIUtil::HtmlEscape(r.second, true) + "
"; -#ifdef ENABLE_BIP70 - // - // PaymentRequest info: - // - for (const std::pair& r : orderForm) - { + // + // PaymentRequest info: + // if (r.first == "PaymentRequest") { + QString merchant; +#ifdef ENABLE_BIP70 PaymentRequestPlus req; req.parse(QByteArray::fromRawData(r.second.data(), r.second.size())); - QString merchant; - if (req.getMerchant(PaymentServer::getCertStore(), merchant)) + if (!req.getMerchant(PaymentServer::getCertStore(), merchant)) { + merchant.clear(); + } +#else + if (!GetPaymentRequestMerchant(r.second, merchant)) { + merchant.clear(); + } else { + merchant += tr(" (Certificate was not verified)"); + } +#endif + if (!merchant.isNull()) { strHTML += "" + tr("Merchant") + ": " + GUIUtil::HtmlEscape(merchant) + "
"; + } } } -#endif if (wtx.is_coinbase) {