Gavin Andresen
12 years ago
55 changed files with 2631 additions and 437 deletions
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
--- |
||||
name: "protobuf-win32" |
||||
suites: |
||||
- "lucid" |
||||
architectures: |
||||
- "i386" |
||||
packages: |
||||
- "mingw32" |
||||
- "zip" |
||||
- "faketime" |
||||
reference_datetime: "2013-04-15 00:00:00" |
||||
remotes: [] |
||||
files: |
||||
- "protobuf-2.5.0.tar.bz2" |
||||
script: | |
||||
# |
||||
export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 |
||||
export FAKETIME=$REFERENCE_DATETIME |
||||
export TZ=UTC |
||||
# |
||||
tar xjf protobuf-2.5.0.tar.bz2 |
||||
cd protobuf-2.5.0 |
||||
# First: build a native (linux) protoc |
||||
./configure --enable-shared=no --disable-dependency-tracking |
||||
make |
||||
mkdir -p host |
||||
cp src/protoc host |
||||
# Now recompile with the mingw cross-compiler: |
||||
make distclean |
||||
./configure --enable-shared=no --disable-dependency-tracking --with-protoc=$(pwd)/host/protoc --host=i586-mingw32msvc CXXFLAGS=-frandom-seed=11 |
||||
make |
||||
cd .. |
||||
mkdir -p protobuf-win32 |
||||
cp protobuf-2.5.0/host/protoc protobuf-win32/protoc |
||||
cp protobuf-2.5.0/src/.libs/libprotobuf.a protobuf-win32/libprotobuf.a |
||||
cp -r protobuf-2.5.0/src/google protobuf-win32/ |
||||
zip -r $OUTDIR/protobuf-win32-2.5.0-gitian-r1.zip protobuf-win32 |
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
# Based on: http://code.google.com/p/ostinato/source/browse/protobuf.pri |
||||
# |
||||
# Qt qmake integration with Google Protocol Buffers compiler protoc |
||||
# |
||||
# To compile protocol buffers with qt qmake, specify PROTOS variable and |
||||
# include this file |
||||
# |
||||
# Example: |
||||
# PROTOS = a.proto b.proto |
||||
# include(protobuf.pri) |
||||
# |
||||
# Set PROTO_PATH if you need to set the protoc --proto_path search path |
||||
# Set PROTOC to the path to the protoc compiler if it is not in your $PATH |
||||
# |
||||
|
||||
isEmpty(PROTO_DIR):PROTO_DIR = . |
||||
isEmpty(PROTOC):PROTOC = protoc |
||||
|
||||
PROTOPATHS = |
||||
for(p, PROTO_PATH):PROTOPATHS += --proto_path=$${p} |
||||
|
||||
protobuf_decl.name = protobuf header |
||||
protobuf_decl.input = PROTOS |
||||
protobuf_decl.output = $${PROTO_DIR}/${QMAKE_FILE_BASE}.pb.h |
||||
protobuf_decl.commands = $${PROTOC} --cpp_out="$${PROTO_DIR}" $${PROTOPATHS} --proto_path=${QMAKE_FILE_IN_PATH} ${QMAKE_FILE_NAME} |
||||
protobuf_decl.variable_out = GENERATED_FILES |
||||
QMAKE_EXTRA_COMPILERS += protobuf_decl |
||||
|
||||
protobuf_impl.name = protobuf implementation |
||||
protobuf_impl.input = PROTOS |
||||
protobuf_impl.output = $${PROTO_DIR}/${QMAKE_FILE_BASE}.pb.cc |
||||
protobuf_impl.depends = $${PROTO_DIR}/${QMAKE_FILE_BASE}.pb.h |
||||
protobuf_impl.commands = $$escape_expand(\\n) |
||||
protobuf_impl.variable_out = GENERATED_SOURCES |
||||
QMAKE_EXTRA_COMPILERS += protobuf_impl |
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
// |
||||
// Simple Bitcoin Payment Protocol messages |
||||
// |
||||
// Use fields 100+ for extensions; |
||||
// to avoid conflicts, register extensions at: |
||||
// https://en.bitcoin.it/wiki/Payment_Request |
||||
// |
||||
|
||||
package payments; |
||||
option java_package = "org.bitcoin.protocols.payments"; |
||||
option java_outer_classname = "Protos"; |
||||
|
||||
// Generalized form of "send payment to this/these bitcoin addresses" |
||||
message Output { |
||||
optional uint64 amount = 1 [default = 0]; // amount is integer-number-of-satoshis |
||||
required bytes script = 2; // usually one of the standard Script forms |
||||
} |
||||
message PaymentDetails { |
||||
optional string network = 1 [default = "main"]; // "main" or "test" |
||||
repeated Output outputs = 2; // Where payment should be sent |
||||
required uint64 time = 3; // Timestamp; when payment request created |
||||
optional uint64 expires = 4; // Timestamp; when this request should be considered invalid |
||||
optional string memo = 5; // Human-readable description of request for the customer |
||||
optional string payment_url = 6; // URL to send Payment and get PaymentACK |
||||
optional bytes merchant_data = 7; // Arbitrary data to include in the Payment message |
||||
} |
||||
message PaymentRequest { |
||||
optional uint32 payment_details_version = 1 [default = 1]; |
||||
optional string pki_type = 2 [default = "none"]; // none / x509+sha256 / x509+sha1 |
||||
optional bytes pki_data = 3; // depends on pki_type |
||||
required bytes serialized_payment_details = 4; // PaymentDetails |
||||
optional bytes signature = 5; // pki-dependent signature |
||||
} |
||||
message X509Certificates { |
||||
repeated bytes certificate = 1; // DER-encoded X.509 certificate chain |
||||
} |
||||
message Payment { |
||||
optional bytes merchant_data = 1; // From PaymentDetails.merchant_data |
||||
repeated bytes transactions = 2; // Signed transactions that satisfy PaymentDetails.outputs |
||||
repeated Output refund_to = 3; // Where to send refunds, if a refund is necessary |
||||
optional string memo = 4; // Human-readable message for the merchant |
||||
} |
||||
message PaymentACK { |
||||
required Payment payment = 1; // Payment message that triggered this ACK |
||||
optional string memo = 2; // human-readable message for customer |
||||
} |
@ -0,0 +1,204 @@
@@ -0,0 +1,204 @@
|
||||
//
|
||||
// Wraps dumb protocol buffer paymentRequest
|
||||
// with some extra methods
|
||||
//
|
||||
|
||||
#include <QDateTime> |
||||
#include <QDebug> |
||||
#include <QSslCertificate> |
||||
|
||||
#include <openssl/x509.h> |
||||
#include <openssl/x509_vfy.h> |
||||
|
||||
#include <stdexcept> |
||||
|
||||
#include "paymentrequestplus.h" |
||||
|
||||
class SSLVerifyError : public std::runtime_error |
||||
{ |
||||
public: |
||||
SSLVerifyError(std::string err) : std::runtime_error(err) { } |
||||
}; |
||||
|
||||
bool PaymentRequestPlus::parse(const QByteArray& data) |
||||
{ |
||||
bool parseOK = paymentRequest.ParseFromArray(data.data(), data.size()); |
||||
if (!parseOK) { |
||||
qDebug() << "Error parsing payment request"; |
||||
return false; |
||||
} |
||||
if (paymentRequest.payment_details_version() > 1) { |
||||
qDebug() << "Received up-version payment details, version=" << paymentRequest.payment_details_version(); |
||||
return false; |
||||
} |
||||
|
||||
parseOK = details.ParseFromString(paymentRequest.serialized_payment_details()); |
||||
if (!parseOK) |
||||
{ |
||||
qDebug() << "Error parsing payment details"; |
||||
paymentRequest.Clear(); |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
bool PaymentRequestPlus::SerializeToString(string* output) const |
||||
{ |
||||
return paymentRequest.SerializeToString(output); |
||||
} |
||||
|
||||
bool PaymentRequestPlus::IsInitialized() const |
||||
{ |
||||
return paymentRequest.IsInitialized(); |
||||
} |
||||
|
||||
QString PaymentRequestPlus::getPKIType() const |
||||
{ |
||||
if (!IsInitialized()) return QString("none"); |
||||
return QString::fromStdString(paymentRequest.pki_type()); |
||||
} |
||||
|
||||
bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) const |
||||
{ |
||||
merchant.clear(); |
||||
|
||||
if (!IsInitialized()) |
||||
return false; |
||||
|
||||
// One day we'll support more PKI types, but just
|
||||
// x509 for now:
|
||||
const EVP_MD* digestAlgorithm = NULL; |
||||
if (paymentRequest.pki_type() == "x509+sha256") { |
||||
digestAlgorithm = EVP_sha256(); |
||||
} |
||||
else if (paymentRequest.pki_type() == "x509+sha1") { |
||||
digestAlgorithm = EVP_sha1(); |
||||
} |
||||
else if (paymentRequest.pki_type() == "none") { |
||||
if (fDebug) qDebug() << "PaymentRequest: pki_type == none"; |
||||
return false; |
||||
} |
||||
else { |
||||
qDebug() << "PaymentRequest: unknown pki_type " << paymentRequest.pki_type().c_str(); |
||||
return false; |
||||
} |
||||
|
||||
payments::X509Certificates certChain; |
||||
if (!certChain.ParseFromString(paymentRequest.pki_data())) { |
||||
qDebug() << "PaymentRequest: error parsing pki_data"; |
||||
return false; |
||||
} |
||||
|
||||
std::vector<X509*> certs; |
||||
const QDateTime currentTime = QDateTime::currentDateTime(); |
||||
for (int i = 0; i < certChain.certificate_size(); i++) { |
||||
QByteArray certData(certChain.certificate(i).data(), certChain.certificate(i).size()); |
||||
QSslCertificate qCert(certData, QSsl::Der); |
||||
if (currentTime < qCert.effectiveDate() || currentTime > qCert.expiryDate()) { |
||||
qDebug() << "PaymentRequest: certificate expired or not yet active: " << qCert; |
||||
return false; |
||||
} |
||||
#if QT_VERSION >= 0x050000 |
||||
if (qCert.isBlacklisted()) { |
||||
qDebug() << "PaymentRequest: certificate blacklisted: " << qCert; |
||||
return false; |
||||
} |
||||
#endif |
||||
const unsigned char *data = (const unsigned char *)certChain.certificate(i).data(); |
||||
X509 *cert = d2i_X509(NULL, &data, certChain.certificate(i).size()); |
||||
if (cert) |
||||
certs.push_back(cert); |
||||
} |
||||
if (certs.empty()) { |
||||
qDebug() << "PaymentRequest: empty certificate chain"; |
||||
return false; |
||||
} |
||||
|
||||
// The first cert is the signing cert, the rest are untrusted certs that chain
|
||||
// to a valid root authority. OpenSSL needs them separately.
|
||||
STACK_OF(X509) *chain = sk_X509_new_null(); |
||||
for (int i = certs.size()-1; i > 0; i--) { |
||||
sk_X509_push(chain, certs[i]); |
||||
} |
||||
X509 *signing_cert = certs[0]; |
||||
|
||||
// Now create a "store context", which is a single use object for checking,
|
||||
// load the signing cert into it and verify.
|
||||
X509_STORE_CTX *store_ctx = X509_STORE_CTX_new(); |
||||
if (!store_ctx) { |
||||
qDebug() << "PaymentRequest: error creating X509_STORE_CTX"; |
||||
return false; |
||||
} |
||||
|
||||
char *website = NULL; |
||||
bool fResult = true; |
||||
try |
||||
{ |
||||
if (!X509_STORE_CTX_init(store_ctx, certStore, signing_cert, chain)) |
||||
{ |
||||
int error = X509_STORE_CTX_get_error(store_ctx); |
||||
throw SSLVerifyError(X509_verify_cert_error_string(error)); |
||||
} |
||||
|
||||
// Now do the verification!
|
||||
int result = X509_verify_cert(store_ctx); |
||||
if (result != 1) { |
||||
int error = X509_STORE_CTX_get_error(store_ctx); |
||||
throw SSLVerifyError(X509_verify_cert_error_string(error)); |
||||
} |
||||
X509_NAME *certname = X509_get_subject_name(signing_cert); |
||||
|
||||
// Valid cert; check signature:
|
||||
payments::PaymentRequest rcopy(paymentRequest); // Copy
|
||||
rcopy.set_signature(std::string("")); |
||||
std::string data_to_verify; // Everything but the signature
|
||||
rcopy.SerializeToString(&data_to_verify); |
||||
|
||||
EVP_MD_CTX ctx; |
||||
EVP_PKEY *pubkey = X509_get_pubkey(signing_cert); |
||||
EVP_MD_CTX_init(&ctx); |
||||
if (!EVP_VerifyInit_ex(&ctx, digestAlgorithm, NULL) || |
||||
!EVP_VerifyUpdate(&ctx, data_to_verify.data(), data_to_verify.size()) || |
||||
!EVP_VerifyFinal(&ctx, (const unsigned char*)paymentRequest.signature().data(), paymentRequest.signature().size(), pubkey)) { |
||||
|
||||
throw SSLVerifyError("Bad signature, invalid PaymentRequest."); |
||||
} |
||||
|
||||
// OpenSSL API for getting human printable strings from certs is baroque.
|
||||
int textlen = X509_NAME_get_text_by_NID(certname, NID_commonName, NULL, 0); |
||||
website = new char[textlen + 1]; |
||||
if (X509_NAME_get_text_by_NID(certname, NID_commonName, website, textlen + 1) == textlen && textlen > 0) { |
||||
merchant = website; |
||||
} |
||||
else { |
||||
throw SSLVerifyError("Bad certificate, missing common name"); |
||||
} |
||||
// TODO: detect EV certificates and set merchant = business name instead of unfriendly NID_commonName ?
|
||||
} |
||||
catch (SSLVerifyError& err) |
||||
{ |
||||
fResult = false; |
||||
qDebug() << "PaymentRequestPlus::getMerchant SSL err: " << err.what(); |
||||
} |
||||
|
||||
if (website) |
||||
delete[] website; |
||||
X509_STORE_CTX_free(store_ctx); |
||||
for (unsigned int i = 0; i < certs.size(); i++) |
||||
X509_free(certs[i]); |
||||
|
||||
return fResult; |
||||
} |
||||
|
||||
QList<std::pair<CScript,qint64> > PaymentRequestPlus::getPayTo() const |
||||
{ |
||||
QList<std::pair<CScript,qint64> > result; |
||||
for (int i = 0; i < details.outputs_size(); i++) |
||||
{ |
||||
const unsigned char* scriptStr = (const unsigned char*)details.outputs(i).script().data(); |
||||
CScript s(scriptStr, scriptStr+details.outputs(i).script().size()); |
||||
|
||||
result.append(make_pair(s, details.outputs(i).amount())); |
||||
} |
||||
return result; |
||||
} |
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
#ifndef PAYMENTREQUESTPLUS_H |
||||
#define PAYMENTREQUESTPLUS_H |
||||
|
||||
#include <QByteArray> |
||||
#include <QList> |
||||
#include <QString> |
||||
|
||||
#include "base58.h" |
||||
#include "paymentrequest.pb.h" |
||||
|
||||
//
|
||||
// Wraps dumb protocol buffer paymentRequest
|
||||
// with extra methods
|
||||
//
|
||||
|
||||
class PaymentRequestPlus |
||||
{ |
||||
public: |
||||
PaymentRequestPlus() { } |
||||
|
||||
bool parse(const QByteArray& data); |
||||
bool SerializeToString(string* output) const; |
||||
|
||||
bool IsInitialized() const; |
||||
QString getPKIType() const; |
||||
// Returns true if merchant's identity is authenticated, and
|
||||
// returns human-readable merchant identity in merchant
|
||||
bool getMerchant(X509_STORE* certStore, QString& merchant) const; |
||||
|
||||
// Returns list of outputs, amount
|
||||
QList<std::pair<CScript,qint64> > getPayTo() const; |
||||
|
||||
const payments::PaymentDetails& getDetails() const { return details; } |
||||
|
||||
private: |
||||
payments::PaymentRequest paymentRequest; |
||||
payments::PaymentDetails details; |
||||
}; |
||||
|
||||
#endif // PAYMENTREQUESTPLUS_H
|
||||
|
@ -0,0 +1,307 @@
@@ -0,0 +1,307 @@
|
||||
//
|
||||
// Data for paymentservertests.cpp
|
||||
//
|
||||
|
||||
// Base64/DER-encoded fake certificate authority certificate.
|
||||
// Convert pem to base64/der with:
|
||||
// cat file.pem | openssl x509 -inform PEM -outform DER | openssl enc -base64
|
||||
//
|
||||
// Serial Number: 10302349811211485352 (0x8ef94c91b112c0a8)
|
||||
// Issuer: CN=PaymentRequest Test CA
|
||||
// Subject: CN=PaymentRequest Test CA
|
||||
// Not Valid After : Dec 8 16:37:24 2022 GMT
|
||||
//
|
||||
const char* caCert_BASE64 = |
||||
"\
|
||||
MIIB0DCCATmgAwIBAgIJAI75TJGxEsCoMA0GCSqGSIb3DQEBCwUAMCExHzAdBgNV\ |
||||
BAMTFlBheW1lbnRSZXF1ZXN0IFRlc3QgQ0EwHhcNMTIxMjEwMTYzNzI0WhcNMjIx\ |
||||
MjA4MTYzNzI0WjAhMR8wHQYDVQQDExZQYXltZW50UmVxdWVzdCBUZXN0IENBMIGf\ |
||||
MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvua59nX9radoqDYyplcns5qdVDTN1\ |
||||
7tmcGixmMYOYU3UYMU55VSsJs0dWKnMm3COQDY+N63c0XSbRqarBcsLTkaNASuPX\ |
||||
FCv1VWuEKSyy5xe4zeoDU7CVSzlxtQD9wbZW/s3ISjgaXBpwn6eVmntb0JwYxxPc\ |
||||
M1u/hrMD8BDbSQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUA\ |
||||
A4GBADSaRgK5xe47XxycXBhHhr0Wgl4pAsFsufqA9aB9r8KNEHJ0yUvvbD/jaJJM\ |
||||
RtQcf0AJ9olzUMY4syehxbzUJP6aeXhZEYiMvdvcv9D55clq6+WLLlNT3jBgAaVn\ |
||||
p3waRjPD4bUX3nv+ojz5s4puw7Qq5QUZlhGsMzPvwDGCmZkL\ |
||||
"; |
||||
|
||||
//
|
||||
// This payment request validates directly against the
|
||||
// above certificate authority.
|
||||
//
|
||||
const char* paymentrequest1_BASE64 = |
||||
"\
|
||||
Egt4NTA5K3NoYTI1NhrxAwruAzCCAeowggFToAMCAQICAQEwDQYJKoZIhvcNAQEL\ |
||||
BQAwITEfMB0GA1UEAxMWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xMjEyMTAx\ |
||||
NjM3MjRaFw0yMjEyMDgxNjM3MjRaMEMxGTAXBgNVBAMMEHRlc3RtZXJjaGFudC5v\ |
||||
cmcxJjAkBgNVBAoMHVBheW1lbnQgUmVxdWVzdCBUZXN0IE1lcmNoYW50MIGfMA0G\ |
||||
CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHkMy8W1u6HsWlSqdWTmMKf54gICxNfxbY\ |
||||
+rcMtAftr62hCYx2d2QiSRd1pCUzmo12IiSX3WxSHwaTnT3MFD6jRx6+zM6XdGar\ |
||||
I2zpYle11ANzu4gAthN17uRQHV2O5QxVtzNaMdKeJLXT2L9tfEdyL++9ZUqoQmdA\ |
||||
YG9ix330hQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GB\ |
||||
AIkyO99KC68bi9PFRyQQ7nvn5GlQEb3Ca1bRG5+AKN9N5vc8rZ9G2hejtM8wEXni\ |
||||
eGBP+chVMsbTPEHKLrwREn7IvcyCcbAStaklPC3w0B/2idQSHskb6P3X13OR2bTH\ |
||||
a2+6wuhsOZRUrVNr24rM95DKx/eCC6JN1VW+qRPU6fqzIjQSHwiw2wYSGXapFJVg\ |
||||
igPI+6XpExtNLO/i1WFV8ZmoiKwYsuHFiwUqC1VuaXRUZXN0T25lKoABS0j59iMU\ |
||||
Uc9MdIfwsO1BskIET0eJSGNZ7eXb9N62u+qf831PMpEHkmlGpk8rHy92nPcgua/U\ |
||||
Yt8oZMn3QaTZ5A6HjJbc3A73eLylp1a0SwCl+KDMEvDQhqMn1jAVu2v92AH3uB7n\ |
||||
SiWVbw0tX/68iSQEGGfh9n6ee/8Myb3ICdw=\ |
||||
"; |
||||
|
||||
//
|
||||
// Signed, but expired, merchant cert in the request
|
||||
//
|
||||
const char* paymentrequest2_BASE64 = |
||||
"\
|
||||
Egt4NTA5K3NoYTI1NhrsAwrpAzCCAeUwggFOoAMCAQICAQMwDQYJKoZIhvcNAQEL\ |
||||
BQAwITEfMB0GA1UEAxMWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xMzAyMjMy\ |
||||
MTI2NDNaFw0xMzAyMjQyMTI2NDNaMD4xHDAaBgNVBAMME2V4cGlyZWRtZXJjaGFu\ |
||||
dC5vcmcxHjAcBgNVBAoMFUV4cGlyZWQgVGVzdCBNZXJjaGFudDCBnzANBgkqhkiG\ |
||||
9w0BAQEFAAOBjQAwgYkCgYEAx5DMvFtbuh7FpUqnVk5jCn+eICAsTX8W2Pq3DLQH\ |
||||
7a+toQmMdndkIkkXdaQlM5qNdiIkl91sUh8Gk509zBQ+o0cevszOl3RmqyNs6WJX\ |
||||
tdQDc7uIALYTde7kUB1djuUMVbczWjHSniS109i/bXxHci/vvWVKqEJnQGBvYsd9\ |
||||
9IUCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAaU137\ |
||||
j53rvSjlmYZpZ4RWTP7EdD6fl5ZxBeXHytN6DQL33H0eD7OFHt+ofc7E6D7keubl\ |
||||
UfCu+jOvt/MvvPUmtCI9yXZ0dNC4sjyETv+wQpxO0UNZwOM4uegdCzlo6Bi3pD4/\ |
||||
KKLdMkWuUfuPBmoammny74lZaOVr5deKXztTuCI0Eh8IsNsGEhl2qRSVYIoDyPul\ |
||||
6RMbTSzv4tVhVfGZqIisGLLhxYsFKgtVbml0VGVzdFR3byqAAXHuo4nZEPniLpkd\ |
||||
y30TkwBxVgprWJ18a9z/7Py35Qss/JMbOXbnBhJtmJCdIowHRI0aa+zqt3KKKAXi\ |
||||
mm+V4seMgxTcxMS+eDDkiTcB/RtWWSyRcS2ANjFeY0T4SLMwiCL9qWPi03hr8j96\ |
||||
tejrSPOBNSJ3Mi/q5u2Yl4gJZY2b\ |
||||
"; |
||||
|
||||
//
|
||||
// 10-long chain, all intermediates valid
|
||||
//
|
||||
const char* paymentrequest3_BASE64 = |
||||
"\
|
||||
Egt4NTA5K3NoYTI1Nhq8JAr/AzCCAfswggFkoAMCAQICAQEwDQYJKoZIhvcNAQEL\ |
||||
BQAwPzEUMBIGA1UEAwwLdGVzdGNhOC5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVx\ |
||||
dWVzdCBJbnRlcm1lZGlhdGUgODAeFw0xMzAyMjMyMjQyMzFaFw0yMzAyMjEyMjQy\ |
||||
MzFaMDYxGjAYBgNVBAMMEXRlc3RtZXJjaGFudDgub3JnMRgwFgYDVQQKDA9UZXN0\ |
||||
IE1lcmNoYW50IDgwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMMCHA3hiHbS\ |
||||
TKZ5K9jHRwE8NxkGp3IOx56PDB2diNkldG8XweTcRq7bBm7pdiBt4IVggtfs+6hE\ |
||||
hDYIOecyoAnVzPFTdvQ7KQdQ/fD9YLe6lk+o0edOqutPMyrxLFjSluXxEQyk7fdt\ |
||||
URloMMYfp3p1/hFCboA1rAsQ2RW38hR5AgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8w\ |
||||
DQYJKoZIhvcNAQELBQADgYEAPsdFatnc2RJSpvZsw+nCiPVsllycw5ELglq9vfJz\ |
||||
nJJucRxgzmqI2iuas1ugwbXn0BEIRLK7vMF/qBzQR6M/nTxttah+KEu+okjps9vJ\ |
||||
cIyhfTyGPC5xkHaHZ7sG+UHOFhPw0/kXn0x+pbVgBZ5315axqcp1R+DTSj/whMAr\ |
||||
n0AKiAQwggIEMIIBbaADAgECAgECMA0GCSqGSIb3DQEBCwUAMD8xFDASBgNVBAMM\ |
||||
C3Rlc3RjYTcub3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRp\ |
||||
YXRlIDcwHhcNMTMwMjIzMjI0MjMxWhcNMjMwMjIxMjI0MjMxWjA/MRQwEgYDVQQD\ |
||||
DAt0ZXN0Y2E4Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVk\ |
||||
aWF0ZSA4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDexUFfxb1sThvabp7u\ |
||||
dZz59ciThGmmAW0nP4tjrgEACgvWIInr2dZpTHbiQNF34ycsk0le1JD93D7Qb8rd\ |
||||
25OrpaO8XS2Li2zjR9cleixXjSLwV/zv8zJ8yPl/27XL++PDTKBXVpJ8/Syp+9Ty\ |
||||
plV1BqDhqtIHb/QSHEkTQXjeYQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqG\ |
||||
SIb3DQEBCwUAA4GBACMooQVbkbIZ2DaPwHDc4ULwguG3VI2Kzj50UdExmHtzm2S4\ |
||||
MQei+n+HEPjtJAx5OY520+10nfuP+12H2DRLQmWmdvDpeQ/Cv0yavlw4ZRejRFo7\ |
||||
KS83C0wo5rd+qTvvOmAN4UTArWkzYcEUulPdiXnRamb0WQHTeVdIbHVkMormCogE\ |
||||
MIICBDCCAW2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA/MRQwEgYDVQQDDAt0ZXN0\ |
||||
Y2E2Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSA2\ |
||||
MB4XDTEzMDIyMzIyNDIzMVoXDTIzMDIyMTIyNDIzMVowPzEUMBIGA1UEAwwLdGVz\ |
||||
dGNhNy5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUg\ |
||||
NzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtjBRazrkebXAhXsbjimrMIRm\ |
||||
W/f9SwAHwXfc042keNtl0t2z6XE6UPcR2v/KrssXuCZgodeYxz6IM6lWosCM1xot\ |
||||
C3ChKKFBfVO30reuKBRUxXfKAFqxaG0YOAEzdZkkY9AGhqWloeSmgxpIfhInU0EF\ |
||||
JjCwrJ6IkijBatGoAAECAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B\ |
||||
AQsFAAOBgQDBRTi1MolmOA0niHYX0A2lN5QWHkCfX0A7GwyoMA3dvM45m/NYd4WB\ |
||||
X+HwfnfYcI6X9jOgNo5OWmc4GGsld0HlxwMYEKISBS9PbSHPBrb3TBOlw5ztQpXZ\ |
||||
91+bOhLux52Fr03sK7v9qExmBM12M8UR2ltpzAMiUgLLMHyPfiWkvQqIBDCCAgQw\ |
||||
ggFtoAMCAQICAQIwDQYJKoZIhvcNAQELBQAwPzEUMBIGA1UEAwwLdGVzdGNhNS5v\ |
||||
cmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgNTAeFw0x\ |
||||
MzAyMjMyMjQyMzBaFw0yMzAyMjEyMjQyMzBaMD8xFDASBgNVBAMMC3Rlc3RjYTYu\ |
||||
b3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDYwgZ8w\ |
||||
DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANJSH3xivX1t9olIdHsznI1aE9SD7t9i\ |
||||
SZJsIB0otoETHZRVv9M9LvyzBNK98ZV+kTOlST7PJgC0d9BQM9sgYApSRq5oqKDM\ |
||||
9FXbOm/yaReAbU3mkFNFw5roTlJ5ThEy0yOGT/DS0YBRaGIvRPRj2DiqDVdCZZ+w\ |
||||
4jo1IYHkZt4FAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQAD\ |
||||
gYEATm6+J1OmbrothO60xALKonWMBKr6hudb4amkFBqKbA9wMeM3jl+I/yKfz/Uf\ |
||||
xWuJ071IhiNv6Gxx5YwNvhUe1xMhUqHv0gpyK1Z47bD+kYS2se5sWNPNo3Y9qZDG\ |
||||
IXiGQxwHmrzaFk79Uy1xsmvsEz42w6hr25Yaw7HkIgrFveoKiAQwggIEMIIBbaAD\ |
||||
AgECAgECMA0GCSqGSIb3DQEBCwUAMD8xFDASBgNVBAMMC3Rlc3RjYTQub3JnMScw\ |
||||
JQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDQwHhcNMTMwMjIz\ |
||||
MjI0MjMwWhcNMjMwMjIxMjI0MjMwWjA/MRQwEgYDVQQDDAt0ZXN0Y2E1Lm9yZzEn\ |
||||
MCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSA1MIGfMA0GCSqG\ |
||||
SIb3DQEBAQUAA4GNADCBiQKBgQC7vVUFpxHzz2Tr/xij3k58s8d/BPA0R6D5RXTV\ |
||||
vmhAzc1Zuin4zUKRFs/aCj/0yED8Wu/COfNGF4tVlRNMdl9EcFsxa8XGEL4eAZa+\ |
||||
H/rOHH+7/1EINrrVWhZlUecyhilN8jmCZmqEM3ecuD0NAViqyMrgmaiFmsLoQZpE\ |
||||
GepDUQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBAEdJ\ |
||||
Ss8jWiooja3WZzHXeF95QkBJNjIlpDLGcpl4opOYLSuEl9Uxp//LaQQiXuzpj4/I\ |
||||
pkWGQmMy5HOyH1lqDyiMgXpcG8PE0jEQAoEUGZ0QEqB1mZ6BCrYvmUuf/5aSVd8Y\ |
||||
6lKMR3WzFDYU9Zy0nzuHB/3nvp6MeDRQeRMtYvz4CogEMIICBDCCAW2gAwIBAgIB\ |
||||
AjANBgkqhkiG9w0BAQsFADA/MRQwEgYDVQQDDAt0ZXN0Y2EzLm9yZzEnMCUGA1UE\ |
||||
CgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSAzMB4XDTEzMDIyMzIyNDIy\ |
||||
OVoXDTIzMDIyMTIyNDIyOVowPzEUMBIGA1UEAwwLdGVzdGNhNC5vcmcxJzAlBgNV\ |
||||
BAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgNDCBnzANBgkqhkiG9w0B\ |
||||
AQEFAAOBjQAwgYkCgYEAxYYo3w2UXiYg6O8b4QgwN/vgreTkiW122Ep/z2TiDrhV\ |
||||
MhfOOiKdwYESPflfnXnVaQQzCGexYTQqsvqvzHSyna5hL0zPTRJxSKmTVrXRsWtp\ |
||||
dCRhjxCGipS3tlQBDi7vb+7SNRIBK4dBjjGzALNk7gMCpy+yM8f6I043jTlmGb0C\ |
||||
AwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQDU+IQxt3Oh\ |
||||
KqaUYWC23+cB2gekvWqwMBnrCNrX/Dp+kjoJKUoR2Fs3qw53raHES4SIhpGT9l9l\ |
||||
rppNQgFe/JMHeYqOZMZO+6kuU0olJanBJ14tPIc7zlMTQ9OfmZ6v07IpyFbsQDtR\ |
||||
hpe80DpuvSFPfJ4fh0WrQf6kn3KDVpGDnAqIBDCCAgQwggFtoAMCAQICAQIwDQYJ\ |
||||
KoZIhvcNAQELBQAwPzEUMBIGA1UEAwwLdGVzdGNhMi5vcmcxJzAlBgNVBAoMHlBh\ |
||||
eW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgMjAeFw0xMzAyMjMyMjQyMjlaFw0y\ |
||||
MzAyMjEyMjQyMjlaMD8xFDASBgNVBAMMC3Rlc3RjYTMub3JnMScwJQYDVQQKDB5Q\ |
||||
YXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDMwgZ8wDQYJKoZIhvcNAQEBBQAD\ |
||||
gY0AMIGJAoGBANzgVP99Qg98e6NsKEz1v5KqRB7NTBRRsYnBvb/TSWipvMQaCYuE\ |
||||
yk1xG57x++QuASKeR3QHRQJOoAhQaj9JLUhSSv9GQ5PrFLLsOFv7L1tpzXHh2dOB\ |
||||
IW92X2yFRW2s39q+Q21yvN+N8uoKdqXhzRA+dDoXh3cavaVeHX1G+IrlAgMBAAGj\ |
||||
EDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEASTwg84cX+1UhOG9s\ |
||||
ejFV3m34QuI1hPZ+qhqVJlRYUtego8Wng1BburDSwqVAv4ch2wi3c2s4e8J7AXyL\ |
||||
tzSbSQG4RN0oZi0mR8EtTTN+Mix/hBIk79dMZg85+I29uFA6Zj2d9oAhQv2qkHhc\ |
||||
6tcaheNvkQRlCyH68k3iF1Fqf+4KiAQwggIEMIIBbaADAgECAgECMA0GCSqGSIb3\ |
||||
DQEBCwUAMD8xFDASBgNVBAMMC3Rlc3RjYTEub3JnMScwJQYDVQQKDB5QYXltZW50\ |
||||
IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDEwHhcNMTMwMjIzMjI0MjI5WhcNMjMwMjIx\ |
||||
MjI0MjI5WjA/MRQwEgYDVQQDDAt0ZXN0Y2EyLm9yZzEnMCUGA1UECgweUGF5bWVu\ |
||||
dCBSZXF1ZXN0IEludGVybWVkaWF0ZSAyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB\ |
||||
iQKBgQDaV8zhfyQuSf/f+fauMfgs3g/RnWy9yxxUkvQneQQPH3uZzCyk3A6q72ip\ |
||||
TtwNqiibG9455L9A7SaUjGtnpUz0NKT/VWUdqbfCl1PqXjEZbDobbAQ5hxLGOTyL\ |
||||
RQhLIcgeq2/BnmeCqHsC4md04nUp+nBo1HwKyygvK+9sMbCp/wIDAQABoxAwDjAM\ |
||||
BgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBACvYyE+PPmWFkbjyRu9LAt8D\ |
||||
crtyYYLRClKSg6tVvutwukLG2l//kDOohYkJtgTqr6LnCIIIwYdXN+4wxugmw4cn\ |
||||
PIZmP6kovxjhhVM95okilor1zniTAo3RN7JDIfTGNgxLdGu1btt7DOFL4zTbeSJM\ |
||||
b8M1JpPftehH+x/VLyuUCuoDMIIB5jCCAU+gAwIBAgIBBTANBgkqhkiG9w0BAQsF\ |
||||
ADAhMR8wHQYDVQQDExZQYXltZW50UmVxdWVzdCBUZXN0IENBMB4XDTEzMDIyMzIy\ |
||||
NDIyOFoXDTIzMDIyMTIyNDIyOFowPzEUMBIGA1UEAwwLdGVzdGNhMS5vcmcxJzAl\ |
||||
BgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgMTCBnzANBgkqhkiG\ |
||||
9w0BAQEFAAOBjQAwgYkCgYEAo5Vy9H3nA/OOkF5Ap89yfVNSiTay/LYCaB0eALpc\ |
||||
U690U75O9Q3w2M+2AN8wpbbHsJHZMIjEeBRoQfjlYXW1ucQTxWKyT+liu0D25mGX\ |
||||
X27CBXBd4iXTxVII/iX+u3lcjORjoHOBy7QgeIDIIS9y0vYu8eArpjh7m4thrVgI\ |
||||
RtMCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQB9LKcV\ |
||||
JK9sjASNzpQlpUp7nCiw5FSjVY+XMRIKK/kavzlKjZ+InsmmyRVGjDoZi9GrqG9P\ |
||||
VHgLBxi2VtVjmokZoNPqao3OfhqORAubC+JR/JLepM7aDaxDdTHVhSUk4lgNAvi2\ |
||||
6dGY7nZMsnHlPQ2tPp/HvRRiMq1oDjlylc8VTCI2Eh8IsNsGEhl2qRSVYIoDyPul\ |
||||
6RMbTSzv4tVhVfGZqIisGLLhxYsFKg1Vbml0VGVzdFRocmVlKoABn2HTsUQtMNI4\ |
||||
yNvkfkFNka3pRvTUTydJrvyfmEeLzImfM1BWddZjnywku9RToNFZZNgow5QnljmF\ |
||||
chhR/aHOuEMTxmc12K4rNlgYtHCsxLP9zd+6u0cva3TucZ6EzS8PKEib/+r12/52\ |
||||
664NuWA9WtsK7QCFrK2K95PnVCRmWl0=\ |
||||
"; |
||||
|
||||
//
|
||||
// Long chain, with an invalid (expired) cert in the middle
|
||||
//
|
||||
const char* paymentrequest4_BASE64 = |
||||
"\
|
||||
Egt4NTA5K3NoYTI1NhqeJAr/AzCCAfswggFkoAMCAQICAQEwDQYJKoZIhvcNAQEL\ |
||||
BQAwPzEUMBIGA1UEAwwLdGVzdGNhOC5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVx\ |
||||
dWVzdCBJbnRlcm1lZGlhdGUgODAeFw0xMzAyMjMyMjQyMzFaFw0yMzAyMjEyMjQy\ |
||||
MzFaMDYxGjAYBgNVBAMMEXRlc3RtZXJjaGFudDgub3JnMRgwFgYDVQQKDA9UZXN0\ |
||||
IE1lcmNoYW50IDgwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMMCHA3hiHbS\ |
||||
TKZ5K9jHRwE8NxkGp3IOx56PDB2diNkldG8XweTcRq7bBm7pdiBt4IVggtfs+6hE\ |
||||
hDYIOecyoAnVzPFTdvQ7KQdQ/fD9YLe6lk+o0edOqutPMyrxLFjSluXxEQyk7fdt\ |
||||
URloMMYfp3p1/hFCboA1rAsQ2RW38hR5AgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8w\ |
||||
DQYJKoZIhvcNAQELBQADgYEAPsdFatnc2RJSpvZsw+nCiPVsllycw5ELglq9vfJz\ |
||||
nJJucRxgzmqI2iuas1ugwbXn0BEIRLK7vMF/qBzQR6M/nTxttah+KEu+okjps9vJ\ |
||||
cIyhfTyGPC5xkHaHZ7sG+UHOFhPw0/kXn0x+pbVgBZ5315axqcp1R+DTSj/whMAr\ |
||||
n0AKiAQwggIEMIIBbaADAgECAgECMA0GCSqGSIb3DQEBCwUAMD8xFDASBgNVBAMM\ |
||||
C3Rlc3RjYTcub3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRp\ |
||||
YXRlIDcwHhcNMTMwMjIzMjI0MjMxWhcNMjMwMjIxMjI0MjMxWjA/MRQwEgYDVQQD\ |
||||
DAt0ZXN0Y2E4Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVk\ |
||||
aWF0ZSA4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDexUFfxb1sThvabp7u\ |
||||
dZz59ciThGmmAW0nP4tjrgEACgvWIInr2dZpTHbiQNF34ycsk0le1JD93D7Qb8rd\ |
||||
25OrpaO8XS2Li2zjR9cleixXjSLwV/zv8zJ8yPl/27XL++PDTKBXVpJ8/Syp+9Ty\ |
||||
plV1BqDhqtIHb/QSHEkTQXjeYQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqG\ |
||||
SIb3DQEBCwUAA4GBACMooQVbkbIZ2DaPwHDc4ULwguG3VI2Kzj50UdExmHtzm2S4\ |
||||
MQei+n+HEPjtJAx5OY520+10nfuP+12H2DRLQmWmdvDpeQ/Cv0yavlw4ZRejRFo7\ |
||||
KS83C0wo5rd+qTvvOmAN4UTArWkzYcEUulPdiXnRamb0WQHTeVdIbHVkMormCogE\ |
||||
MIICBDCCAW2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA/MRQwEgYDVQQDDAt0ZXN0\ |
||||
Y2E2Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSA2\ |
||||
MB4XDTEzMDIyMzIyNDIzMVoXDTIzMDIyMTIyNDIzMVowPzEUMBIGA1UEAwwLdGVz\ |
||||
dGNhNy5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUg\ |
||||
NzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtjBRazrkebXAhXsbjimrMIRm\ |
||||
W/f9SwAHwXfc042keNtl0t2z6XE6UPcR2v/KrssXuCZgodeYxz6IM6lWosCM1xot\ |
||||
C3ChKKFBfVO30reuKBRUxXfKAFqxaG0YOAEzdZkkY9AGhqWloeSmgxpIfhInU0EF\ |
||||
JjCwrJ6IkijBatGoAAECAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B\ |
||||
AQsFAAOBgQDBRTi1MolmOA0niHYX0A2lN5QWHkCfX0A7GwyoMA3dvM45m/NYd4WB\ |
||||
X+HwfnfYcI6X9jOgNo5OWmc4GGsld0HlxwMYEKISBS9PbSHPBrb3TBOlw5ztQpXZ\ |
||||
91+bOhLux52Fr03sK7v9qExmBM12M8UR2ltpzAMiUgLLMHyPfiWkvQqIBDCCAgQw\ |
||||
ggFtoAMCAQICAQIwDQYJKoZIhvcNAQELBQAwPzEUMBIGA1UEAwwLdGVzdGNhNS5v\ |
||||
cmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgNTAeFw0x\ |
||||
MzAyMjMyMjQyMzBaFw0yMzAyMjEyMjQyMzBaMD8xFDASBgNVBAMMC3Rlc3RjYTYu\ |
||||
b3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDYwgZ8w\ |
||||
DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANJSH3xivX1t9olIdHsznI1aE9SD7t9i\ |
||||
SZJsIB0otoETHZRVv9M9LvyzBNK98ZV+kTOlST7PJgC0d9BQM9sgYApSRq5oqKDM\ |
||||
9FXbOm/yaReAbU3mkFNFw5roTlJ5ThEy0yOGT/DS0YBRaGIvRPRj2DiqDVdCZZ+w\ |
||||
4jo1IYHkZt4FAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQAD\ |
||||
gYEATm6+J1OmbrothO60xALKonWMBKr6hudb4amkFBqKbA9wMeM3jl+I/yKfz/Uf\ |
||||
xWuJ071IhiNv6Gxx5YwNvhUe1xMhUqHv0gpyK1Z47bD+kYS2se5sWNPNo3Y9qZDG\ |
||||
IXiGQxwHmrzaFk79Uy1xsmvsEz42w6hr25Yaw7HkIgrFveoK6gMwggHmMIIBT6AD\ |
||||
AgECAgEGMA0GCSqGSIb3DQEBCwUAMCExHzAdBgNVBAMTFlBheW1lbnRSZXF1ZXN0\ |
||||
IFRlc3QgQ0EwHhcNMTMwMjIzMjI1OTUxWhcNMTMwMjI0MjI1OTUxWjA/MRQwEgYD\ |
||||
VQQDDAt0ZXN0Y2E1Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVy\ |
||||
bWVkaWF0ZSA1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7vVUFpxHzz2Tr\ |
||||
/xij3k58s8d/BPA0R6D5RXTVvmhAzc1Zuin4zUKRFs/aCj/0yED8Wu/COfNGF4tV\ |
||||
lRNMdl9EcFsxa8XGEL4eAZa+H/rOHH+7/1EINrrVWhZlUecyhilN8jmCZmqEM3ec\ |
||||
uD0NAViqyMrgmaiFmsLoQZpEGepDUQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0G\ |
||||
CSqGSIb3DQEBCwUAA4GBAEmcUEnhua/oiXy1fwScLgMqt+jk9mHRpE6SVsIop23Q\ |
||||
CY2JfpG6RxhMMzzzhGklEGN6cxG0HCi6B3HJx6PYrFEfTB0rW4K6m0Tvx3WpS9mN\ |
||||
uoEuJHLy18ausI/sYAPDHCL+SfBVcqorpaIG2sSpZouRBjRHAyqFAYlwlW87uq5n\ |
||||
CogEMIICBDCCAW2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA/MRQwEgYDVQQDDAt0\ |
||||
ZXN0Y2EzLm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0\ |
||||
ZSAzMB4XDTEzMDIyMzIyNDIyOVoXDTIzMDIyMTIyNDIyOVowPzEUMBIGA1UEAwwL\ |
||||
dGVzdGNhNC5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlh\ |
||||
dGUgNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxYYo3w2UXiYg6O8b4Qgw\ |
||||
N/vgreTkiW122Ep/z2TiDrhVMhfOOiKdwYESPflfnXnVaQQzCGexYTQqsvqvzHSy\ |
||||
na5hL0zPTRJxSKmTVrXRsWtpdCRhjxCGipS3tlQBDi7vb+7SNRIBK4dBjjGzALNk\ |
||||
7gMCpy+yM8f6I043jTlmGb0CAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG\ |
||||
9w0BAQsFAAOBgQDU+IQxt3OhKqaUYWC23+cB2gekvWqwMBnrCNrX/Dp+kjoJKUoR\ |
||||
2Fs3qw53raHES4SIhpGT9l9lrppNQgFe/JMHeYqOZMZO+6kuU0olJanBJ14tPIc7\ |
||||
zlMTQ9OfmZ6v07IpyFbsQDtRhpe80DpuvSFPfJ4fh0WrQf6kn3KDVpGDnAqIBDCC\ |
||||
AgQwggFtoAMCAQICAQIwDQYJKoZIhvcNAQELBQAwPzEUMBIGA1UEAwwLdGVzdGNh\ |
||||
Mi5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgMjAe\ |
||||
Fw0xMzAyMjMyMjQyMjlaFw0yMzAyMjEyMjQyMjlaMD8xFDASBgNVBAMMC3Rlc3Rj\ |
||||
YTMub3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDMw\ |
||||
gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANzgVP99Qg98e6NsKEz1v5KqRB7N\ |
||||
TBRRsYnBvb/TSWipvMQaCYuEyk1xG57x++QuASKeR3QHRQJOoAhQaj9JLUhSSv9G\ |
||||
Q5PrFLLsOFv7L1tpzXHh2dOBIW92X2yFRW2s39q+Q21yvN+N8uoKdqXhzRA+dDoX\ |
||||
h3cavaVeHX1G+IrlAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL\ |
||||
BQADgYEASTwg84cX+1UhOG9sejFV3m34QuI1hPZ+qhqVJlRYUtego8Wng1BburDS\ |
||||
wqVAv4ch2wi3c2s4e8J7AXyLtzSbSQG4RN0oZi0mR8EtTTN+Mix/hBIk79dMZg85\ |
||||
+I29uFA6Zj2d9oAhQv2qkHhc6tcaheNvkQRlCyH68k3iF1Fqf+4KiAQwggIEMIIB\ |
||||
baADAgECAgECMA0GCSqGSIb3DQEBCwUAMD8xFDASBgNVBAMMC3Rlc3RjYTEub3Jn\ |
||||
MScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDEwHhcNMTMw\ |
||||
MjIzMjI0MjI5WhcNMjMwMjIxMjI0MjI5WjA/MRQwEgYDVQQDDAt0ZXN0Y2EyLm9y\ |
||||
ZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSAyMIGfMA0G\ |
||||
CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaV8zhfyQuSf/f+fauMfgs3g/RnWy9yxxU\ |
||||
kvQneQQPH3uZzCyk3A6q72ipTtwNqiibG9455L9A7SaUjGtnpUz0NKT/VWUdqbfC\ |
||||
l1PqXjEZbDobbAQ5hxLGOTyLRQhLIcgeq2/BnmeCqHsC4md04nUp+nBo1HwKyygv\ |
||||
K+9sMbCp/wIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GB\ |
||||
ACvYyE+PPmWFkbjyRu9LAt8DcrtyYYLRClKSg6tVvutwukLG2l//kDOohYkJtgTq\ |
||||
r6LnCIIIwYdXN+4wxugmw4cnPIZmP6kovxjhhVM95okilor1zniTAo3RN7JDIfTG\ |
||||
NgxLdGu1btt7DOFL4zTbeSJMb8M1JpPftehH+x/VLyuUCuoDMIIB5jCCAU+gAwIB\ |
||||
AgIBBTANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDExZQYXltZW50UmVxdWVzdCBU\ |
||||
ZXN0IENBMB4XDTEzMDIyMzIyNDIyOFoXDTIzMDIyMTIyNDIyOFowPzEUMBIGA1UE\ |
||||
AwwLdGVzdGNhMS5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1l\ |
||||
ZGlhdGUgMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAo5Vy9H3nA/OOkF5A\ |
||||
p89yfVNSiTay/LYCaB0eALpcU690U75O9Q3w2M+2AN8wpbbHsJHZMIjEeBRoQfjl\ |
||||
YXW1ucQTxWKyT+liu0D25mGXX27CBXBd4iXTxVII/iX+u3lcjORjoHOBy7QgeIDI\ |
||||
IS9y0vYu8eArpjh7m4thrVgIRtMCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkq\ |
||||
hkiG9w0BAQsFAAOBgQB9LKcVJK9sjASNzpQlpUp7nCiw5FSjVY+XMRIKK/kavzlK\ |
||||
jZ+InsmmyRVGjDoZi9GrqG9PVHgLBxi2VtVjmokZoNPqao3OfhqORAubC+JR/JLe\ |
||||
pM7aDaxDdTHVhSUk4lgNAvi26dGY7nZMsnHlPQ2tPp/HvRRiMq1oDjlylc8VTCI1\ |
||||
Eh8IsNsGEhl2qRSVYIoDyPul6RMbTSzv4tVhVfGZqIisGLLhxYsFKgxVbml0VGVz\ |
||||
dEZvdXIqgAEBE1PP93Tkpif35F+dYmXn9kLA/1djcPjCs2o2rwRMM4Uk356O5dgu\ |
||||
HXQjsfdR58qZQS9CS5DAtRUf0R8+43/wijO/hb49VNaNXmY+/cPHMkahP2aV3tZi\ |
||||
FAyZblLik9A7ZvF+UsjeFQiHB5wzWQvbqk5wQ4yabHIXoYv/E0q+eQ==\ |
||||
"; |
||||
|
||||
const char* paymentrequest5_BASE64 = |
||||
"\
|
||||
Egt4NTA5K3NoYTI1NhrxAwruAzCCAeowggFToAMCAQICAQEwDQYJKoZIhvcNAQEL\ |
||||
BQAwITEfMB0GA1UEAxMWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xMzA0MTkx\ |
||||
NzIwMDZaFw0yMzA0MTcxNzIwMDZaMEMxGTAXBgNVBAMMEHRlc3RtZXJjaGFudC5v\ |
||||
cmcxJjAkBgNVBAoMHVBheW1lbnQgUmVxdWVzdCBUZXN0IE1lcmNoYW50MIGfMA0G\ |
||||
CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhV6Yn47aEEmbl50YLvXoqGEJA51I/40wr\ |
||||
Z6VQGdXYaRqYktagrWDlgYY9h0JQ1bQhm8HgW7ju0R4NaDTXUqxg4HjprF0z3Mfm\ |
||||
/6mmebkLOOptfkVD7ceAteNI7cyuqWGIAZA7D9mV97mXoCAtTlBUycvkmoiClCCS\ |
||||
h0EpF/UTaQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GB\ |
||||
AGIRwW7I0QvLga+RnJoJSZNZQbtu4rQW3xmoz8WfZMBYXX3QBYg5ftycbdK+/IbP\ |
||||
qozfjGW2AS6DNArvpveSPDTK9+GJBNo1paiNtVqwXkC3Ddscv5AIms1eZGiIOQNC\ |
||||
mUvdLkpoXo48WAer3EGsZ3B15GyNEELc0q9W5yUebba1IjUSHwiw2wYSGXapFJVg\ |
||||
igPI+6XpExtNLO/i1WFV8ZmoiKwYuPvFiwUqDFVuaXRUZXN0Rml2ZSqAAXdsMgdG\ |
||||
ssymvca1S/1KeM3n8Ydi2fi1JUzAAr59xPvNJRUeqCLP9upHn5z7br3P12Oz9A20\ |
||||
5/4wL4ClPRPVnOHgij0bEg+y0tGESqmF1rfOfXDszlo2U92wCxS07kq79YAZJ1Zo\ |
||||
XYh860/Q4wvc7lfiTe+dXBzPKAKhMy91yETY\ |
||||
"; |
@ -0,0 +1,109 @@
@@ -0,0 +1,109 @@
|
||||
#include <QCoreApplication> |
||||
#include <QDebug> |
||||
#include <QTemporaryFile> |
||||
#include <QVariant> |
||||
|
||||
#include <openssl/x509.h> |
||||
#include <openssl/x509_vfy.h> |
||||
|
||||
#include "optionsmodel.h" |
||||
#include "paymentservertests.h" |
||||
#include "paymentrequestdata.h" |
||||
#include "util.h" |
||||
|
||||
|
||||
|
||||
X509 *parse_b64der_cert(const char* cert_data) |
||||
{ |
||||
std::vector<unsigned char> data = DecodeBase64(cert_data); |
||||
assert(data.size() > 0); |
||||
const unsigned char* dptr = &data[0]; |
||||
X509 *cert = d2i_X509(NULL, &dptr, data.size()); |
||||
assert(cert); |
||||
return cert; |
||||
} |
||||
|
||||
|
||||
//
|
||||
// Test payment request handling
|
||||
//
|
||||
|
||||
static SendCoinsRecipient handleRequest(PaymentServer* server, std::vector<unsigned char>& data) |
||||
{ |
||||
RecipientCatcher sigCatcher; |
||||
QObject::connect(server, SIGNAL(receivedPaymentRequest(SendCoinsRecipient)), |
||||
&sigCatcher, SLOT(getRecipient(SendCoinsRecipient))); |
||||
|
||||
// Write data to a temp file:
|
||||
QTemporaryFile f; |
||||
f.open(); |
||||
f.write((const char*)&data[0], data.size()); |
||||
f.close(); |
||||
|
||||
// Create a FileOpenEvent and send it directly to the server's event filter:
|
||||
QFileOpenEvent event(f.fileName()); |
||||
server->eventFilter(NULL, &event); |
||||
|
||||
QObject::disconnect(server, SIGNAL(receivedPaymentRequest(SendCoinsRecipient)), |
||||
&sigCatcher, SLOT(getRecipient(SendCoinsRecipient))); |
||||
|
||||
// Return results from sigCatcher
|
||||
return sigCatcher.recipient; |
||||
} |
||||
|
||||
void PaymentServerTests::paymentServerTests() |
||||
{ |
||||
OptionsModel optionsModel; |
||||
PaymentServer* server = new PaymentServer(NULL, false); |
||||
X509_STORE* caStore = X509_STORE_new(); |
||||
X509_STORE_add_cert(caStore, parse_b64der_cert(caCert_BASE64)); |
||||
PaymentServer::LoadRootCAs(caStore); |
||||
server->initNetManager(optionsModel); |
||||
server->uiReady(); |
||||
|
||||
// Now feed PaymentRequests to server, and observe signals it produces:
|
||||
std::vector<unsigned char> data = DecodeBase64(paymentrequest1_BASE64); |
||||
SendCoinsRecipient r = handleRequest(server, data); |
||||
QString merchant; |
||||
r.paymentRequest.getMerchant(caStore, merchant); |
||||
QCOMPARE(merchant, QString("testmerchant.org")); |
||||
|
||||
// Version of the above, with an expired certificate:
|
||||
data = DecodeBase64(paymentrequest2_BASE64); |
||||
r = handleRequest(server, data); |
||||
r.paymentRequest.getMerchant(caStore, merchant); |
||||
QCOMPARE(merchant, QString("")); |
||||
|
||||
// Long certificate chain:
|
||||
data = DecodeBase64(paymentrequest3_BASE64); |
||||
r = handleRequest(server, data); |
||||
r.paymentRequest.getMerchant(caStore, merchant); |
||||
QCOMPARE(merchant, QString("testmerchant8.org")); |
||||
|
||||
// Long certificate chain, with an expired certificate in the middle:
|
||||
data = DecodeBase64(paymentrequest4_BASE64); |
||||
r = handleRequest(server, data); |
||||
r.paymentRequest.getMerchant(caStore, merchant); |
||||
QCOMPARE(merchant, QString("")); |
||||
|
||||
// Validly signed, but by a CA not in our root CA list:
|
||||
data = DecodeBase64(paymentrequest5_BASE64); |
||||
r = handleRequest(server, data); |
||||
r.paymentRequest.getMerchant(caStore, merchant); |
||||
QCOMPARE(merchant, QString("")); |
||||
|
||||
// Try again with no root CA's, verifiedMerchant should be empty:
|
||||
caStore = X509_STORE_new(); |
||||
PaymentServer::LoadRootCAs(caStore); |
||||
data = DecodeBase64(paymentrequest1_BASE64); |
||||
r = handleRequest(server, data); |
||||
r.paymentRequest.getMerchant(caStore, merchant); |
||||
QCOMPARE(merchant, QString("")); |
||||
|
||||
delete server; |
||||
} |
||||
|
||||
void RecipientCatcher::getRecipient(SendCoinsRecipient r) |
||||
{ |
||||
recipient = r; |
||||
} |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
#ifndef PAYMENTSERVERTESTS_H |
||||
#define PAYMENTSERVERTESTS_H |
||||
|
||||
#include <QTest> |
||||
#include <QObject> |
||||
|
||||
#include "../paymentserver.h" |
||||
|
||||
class PaymentServerTests : public QObject |
||||
{ |
||||
Q_OBJECT |
||||
|
||||
private slots: |
||||
void paymentServerTests(); |
||||
}; |
||||
|
||||
// Dummy class to receive paymentserver signals.
|
||||
// If SendCoinsRecipient was a proper QObject, then we could use
|
||||
// QSignalSpy... but it's not.
|
||||
class RecipientCatcher : public QObject |
||||
{ |
||||
Q_OBJECT |
||||
public slots: |
||||
void getRecipient(SendCoinsRecipient r); |
||||
public: |
||||
SendCoinsRecipient recipient; |
||||
}; |
||||
|
||||
#endif // PAYMENTSERVERTESTS_H
|
Loading…
Reference in new issue