17 #include <openssl/x509_vfy.h> 21 #include <QSslCertificate> 31 bool parseOK = paymentRequest.ParseFromArray(data.data(), data.size());
33 qWarning() <<
"PaymentRequestPlus::parse: Error parsing payment request";
36 if (paymentRequest.payment_details_version() > 1) {
37 qWarning() <<
"PaymentRequestPlus::parse: Received up-version payment details, version=" << paymentRequest.payment_details_version();
41 parseOK = details.ParseFromString(paymentRequest.serialized_payment_details());
44 qWarning() <<
"PaymentRequestPlus::parse: Error parsing payment details";
45 paymentRequest.Clear();
53 return paymentRequest.SerializeToString(output);
58 return paymentRequest.IsInitialized();
70 const EVP_MD* digestAlgorithm =
nullptr;
71 if (paymentRequest.pki_type() ==
"x509+sha256") {
72 digestAlgorithm = EVP_sha256();
74 else if (paymentRequest.pki_type() ==
"x509+sha1") {
75 digestAlgorithm = EVP_sha1();
77 else if (paymentRequest.pki_type() ==
"none") {
78 qWarning() <<
"PaymentRequestPlus::getMerchant: Payment request: pki_type == none";
82 qWarning() <<
"PaymentRequestPlus::getMerchant: Payment request: unknown pki_type " << QString::fromStdString(paymentRequest.pki_type());
86 payments::X509Certificates certChain;
87 if (!certChain.ParseFromString(paymentRequest.pki_data())) {
88 qWarning() <<
"PaymentRequestPlus::getMerchant: Payment request: error parsing pki_data";
92 std::vector<X509*> certs;
93 const QDateTime currentTime = QDateTime::currentDateTime();
94 for (
int i = 0; i < certChain.certificate_size(); i++) {
95 QByteArray certData(certChain.certificate(i).data(), certChain.certificate(i).size());
96 QSslCertificate qCert(certData, QSsl::Der);
97 if (currentTime < qCert.effectiveDate() || currentTime > qCert.expiryDate()) {
98 qWarning() <<
"PaymentRequestPlus::getMerchant: Payment request: certificate expired or not yet active: " << qCert;
101 #if QT_VERSION >= 0x050000 102 if (qCert.isBlacklisted()) {
103 qWarning() <<
"PaymentRequestPlus::getMerchant: Payment request: certificate blacklisted: " << qCert;
107 const unsigned char *data = (
const unsigned char *)certChain.certificate(i).data();
108 X509 *cert = d2i_X509(
nullptr, &data, certChain.certificate(i).size());
110 certs.push_back(cert);
113 qWarning() <<
"PaymentRequestPlus::getMerchant: Payment request: empty certificate chain";
119 STACK_OF(X509) *chain = sk_X509_new_null();
120 for (
int i = certs.size() - 1; i > 0; i--) {
121 sk_X509_push(chain, certs[i]);
123 X509 *signing_cert = certs[0];
127 X509_STORE_CTX *store_ctx = X509_STORE_CTX_new();
129 qWarning() <<
"PaymentRequestPlus::getMerchant: Payment request: error creating X509_STORE_CTX";
133 char *website =
nullptr;
137 if (!X509_STORE_CTX_init(store_ctx, certStore, signing_cert, chain))
139 int error = X509_STORE_CTX_get_error(store_ctx);
144 int result = X509_verify_cert(store_ctx);
146 int error = X509_STORE_CTX_get_error(store_ctx);
149 if (!(error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT &&
gArgs.
GetBoolArg(
"-allowselfsignedrootcertificates", DEFAULT_SELFSIGNED_ROOTCERTS))) {
152 qDebug() <<
"PaymentRequestPlus::getMerchant: Allowing self signed root certificate, because -allowselfsignedrootcertificates is true.";
155 X509_NAME *certname = X509_get_subject_name(signing_cert);
158 payments::PaymentRequest rcopy(paymentRequest);
159 rcopy.set_signature(std::string(
""));
160 std::string data_to_verify;
161 rcopy.SerializeToString(&data_to_verify);
163 #if HAVE_DECL_EVP_MD_CTX_NEW 164 EVP_MD_CTX *ctx = EVP_MD_CTX_new();
165 if (!ctx)
throw SSLVerifyError(
"Error allocating OpenSSL context.");
171 EVP_PKEY *pubkey = X509_get_pubkey(signing_cert);
172 EVP_MD_CTX_init(ctx);
173 if (!EVP_VerifyInit_ex(ctx, digestAlgorithm,
nullptr) ||
174 !EVP_VerifyUpdate(ctx, data_to_verify.data(), data_to_verify.size()) ||
175 !EVP_VerifyFinal(ctx, (
const unsigned char*)paymentRequest.signature().data(), (
unsigned int)paymentRequest.signature().size(), pubkey)) {
178 #if HAVE_DECL_EVP_MD_CTX_NEW 179 EVP_MD_CTX_free(ctx);
183 int textlen = X509_NAME_get_text_by_NID(certname, NID_commonName,
nullptr, 0);
184 website =
new char[textlen + 1];
185 if (X509_NAME_get_text_by_NID(certname, NID_commonName, website, textlen + 1) == textlen && textlen > 0) {
195 qWarning() <<
"PaymentRequestPlus::getMerchant: SSL error: " << err.what();
200 X509_STORE_CTX_free(store_ctx);
201 for (
unsigned int i = 0; i < certs.size(); i++)
209 QList<std::pair<CScript,CAmount> > result;
210 for (
int i = 0; i < details.outputs_size(); i++)
212 const unsigned char* scriptStr = (
const unsigned char*)details.outputs(i).script().data();
213 CScript s(scriptStr, scriptStr+details.outputs(i).script().size());
215 result.append(std::make_pair(s, details.outputs(i).amount()));
SSLVerifyError(std::string err)
bool SerializeToString(std::string *output) const
bool IsInitialized() const
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
bool getMerchant(X509_STORE *certStore, QString &merchant) const
QList< std::pair< CScript, CAmount > > getPayTo() const
bool parse(const QByteArray &data)
Serialized script, used inside transaction inputs and outputs.
bool error(const char *fmt, const Args &... args)