Gavin Andresen
12 years ago
55 changed files with 2631 additions and 437 deletions
@ -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 @@ |
|||||||
|
# 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 @@ |
|||||||
|
// |
||||||
|
// 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 @@ |
|||||||
|
//
|
||||||
|
// 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 @@ |
|||||||
|
#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 @@ |
|||||||
|
//
|
||||||
|
// 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 @@ |
|||||||
|
#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 @@ |
|||||||
|
#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
|
@ -1,16 +1,21 @@ |
|||||||
#include <QTest> |
#include <QTest> |
||||||
#include <QObject> |
#include <QObject> |
||||||
|
|
||||||
#include "uritests.h" |
#include "uritests.h" |
||||||
|
#include "paymentservertests.h" |
||||||
// This is all you need to run all the tests
|
|
||||||
int main(int argc, char *argv[]) |
// This is all you need to run all the tests
|
||||||
{ |
int main(int argc, char *argv[]) |
||||||
bool fInvalid = false; |
{ |
||||||
|
bool fInvalid = false; |
||||||
URITests test1; |
|
||||||
if (QTest::qExec(&test1) != 0) |
URITests test1; |
||||||
fInvalid = true; |
if (QTest::qExec(&test1) != 0) |
||||||
|
fInvalid = true; |
||||||
return fInvalid; |
|
||||||
} |
PaymentServerTests test2; |
||||||
|
if (QTest::qExec(&test2) != 0) |
||||||
|
fInvalid = true; |
||||||
|
|
||||||
|
return fInvalid; |
||||||
|
} |
||||||
|
Loading…
Reference in new issue