13#include <openssl/x509_vfy.h>
17#include <QSslCertificate>
27 bool parseOK =
paymentRequest.ParseFromArray(data.data(), data.size());
30 <<
"PaymentRequestPlus::parse: Error parsing payment request";
34 qWarning() <<
"PaymentRequestPlus::parse: Received up-version payment "
44 <<
"PaymentRequestPlus::parse: Error parsing payment details";
60 QString &merchant)
const {
68 const EVP_MD *digestAlgorithm =
nullptr;
70 digestAlgorithm = EVP_sha256();
72 digestAlgorithm = EVP_sha1();
74 qWarning() <<
"PaymentRequestPlus::getMerchant: Payment request: "
78 qWarning() <<
"PaymentRequestPlus::getMerchant: Payment request: "
84 payments::X509Certificates certChain;
86 qWarning() <<
"PaymentRequestPlus::getMerchant: Payment request: error "
91 std::vector<X509 *> certs;
92 const QDateTime currentTime = QDateTime::currentDateTime();
93 for (
int i = 0; i < certChain.certificate_size(); i++) {
94 QByteArray certData(certChain.certificate(i).data(),
95 certChain.certificate(i).size());
96 QSslCertificate qCert(certData, QSsl::Der);
97 if (currentTime < qCert.effectiveDate() ||
98 currentTime > qCert.expiryDate()) {
99 qWarning() <<
"PaymentRequestPlus::getMerchant: Payment request: "
100 "certificate expired or not yet active: "
104 if (qCert.isBlacklisted()) {
105 qWarning() <<
"PaymentRequestPlus::getMerchant: Payment request: "
106 "certificate blacklisted: "
110 const uint8_t *data = (
const uint8_t *)certChain.certificate(i).data();
111 X509 *cert = d2i_X509(
nullptr, &data, certChain.certificate(i).size());
113 certs.push_back(cert);
117 qWarning() <<
"PaymentRequestPlus::getMerchant: Payment request: empty "
124 STACK_OF(X509) *chain = sk_X509_new_null();
125 for (
int i = certs.size() - 1; i > 0; i--) {
126 sk_X509_push(chain, certs[i]);
128 X509 *signing_cert = certs[0];
132 X509_STORE_CTX *store_ctx = X509_STORE_CTX_new();
134 qWarning() <<
"PaymentRequestPlus::getMerchant: Payment request: error "
135 "creating X509_STORE_CTX";
139 char *website =
nullptr;
142 if (!X509_STORE_CTX_init(store_ctx, certStore, signing_cert, chain)) {
143 int error = X509_STORE_CTX_get_error(store_ctx);
148 int result = X509_verify_cert(store_ctx);
150 int error = X509_STORE_CTX_get_error(store_ctx);
152 if (!(
error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT &&
157 qDebug() <<
"PaymentRequestPlus::getMerchant: Allowing self "
158 "signed root certificate, because "
159 "-allowselfsignedrootcertificates is true.";
162 X509_NAME *certname = X509_get_subject_name(signing_cert);
167 rcopy.set_signature(std::string(
""));
169 std::string data_to_verify;
170 rcopy.SerializeToString(&data_to_verify);
172#if HAVE_DECL_EVP_MD_CTX_NEW
173 EVP_MD_CTX *
ctx = EVP_MD_CTX_new();
182 EVP_PKEY *pubkey = X509_get_pubkey(signing_cert);
183 EVP_MD_CTX_init(
ctx);
184 if (!EVP_VerifyInit_ex(
ctx, digestAlgorithm,
nullptr) ||
185 !EVP_VerifyUpdate(
ctx, data_to_verify.data(),
186 data_to_verify.size()) ||
192#if HAVE_DECL_EVP_MD_CTX_NEW
193 EVP_MD_CTX_free(
ctx);
199 X509_NAME_get_text_by_NID(certname, NID_commonName,
nullptr, 0);
200 website =
new char[textlen + 1];
201 if (X509_NAME_get_text_by_NID(certname, NID_commonName, website,
202 textlen + 1) == textlen &&
212 qWarning() <<
"PaymentRequestPlus::getMerchant: SSL error: "
220 X509_STORE_CTX_free(store_ctx);
221 for (
size_t i = 0; i < certs.size(); i++) {
229 QList<std::pair<CScript, Amount>> result;
230 for (
int i = 0; i <
details.outputs_size(); i++) {
231 const uint8_t *scriptStr =
232 (
const uint8_t *)
details.outputs(i).script().data();
233 CScript s(scriptStr, scriptStr +
details.outputs(i).script().size());
236 std::make_pair(s, int64_t(
details.outputs(i).amount()) *
SATOSHI));
static constexpr Amount SATOSHI
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
QList< std::pair< CScript, Amount > > getPayTo() const
bool getMerchant(X509_STORE *certStore, QString &merchant) const
payments::PaymentDetails details
bool IsInitialized() const
bool parse(const QByteArray &data)
payments::PaymentRequest paymentRequest
bool SerializeToString(std::string *output) const
SSLVerifyError(std::string err)
bool error(const char *fmt, const Args &...args)
Implement std::hash so RCUPtr can be used as a key for maps or sets.
static const bool DEFAULT_SELFSIGNED_ROOTCERTS