Procedure:
```
git clone git@github.com:gavinandresen/paymentrequest.git
cd paymentrequest
ca_in_a_box/create_ca.sh
ca_in_a_box/create_intermediate_cas.sh
openssl x509 -in ca_in_a_box/certs/cacert.pem -inform PEM -outform DER | openssl enc -base64
cd c++
make
mv ../ca_in_a_box .
./paymentrequest-create paytoaddress=1Nf4eZ76SFZdhrHVNLQkLAiS1oPPGaZxSv amount=42 expires=1986627327 | ./paymentrequest-dump
./paymentrequest-create paytoaddress=1Nf4eZ76SFZdhrHVNLQkLAiS1oPPGaZxSv amount=42 expires=1986627327 | base64
./paymentrequest-create paytoaddress=1Nf4eZ76SFZdhrHVNLQkLAiS1oPPGaZxSv amount=42 expires=4826525372 payment_url=testmerchant8.org certificates=./ca_in_a_box/intermediate_8/certs/demomerchant.pem,./ca_in_a_box/intermediate_8/certs/cacert.pem,./ca_in_a_box/intermediate_7/certs/cacert.pem,./ca_in_a_box/intermediate_6/certs/cacert.pem,./ca_in_a_box/intermediate_5/certs/cacert.pem,./ca_in_a_box/intermediate_4/certs/cacert.pem,./ca_in_a_box/intermediate_3/certs/cacert.pem,./ca_in_a_box/intermediate_2/certs/cacert.pem,./ca_in_a_box/intermediate_1/certs/cacert.pem,./ca_in_a_box/certs/cacert.pem privatekey=./ca_in_a_box/intermediate_8/private/demomerchantkey.pem | base64
```
The patch to fix the outdated OpenSSL code is:
```
diff --git a/c++/paymentrequest-create.cpp b/c++/paymentrequest-create.cpp
index 5fdbc8c..69d5b8d 100644
--- a/c++/paymentrequest-create.cpp
+++ b/c++/paymentrequest-create.cpp
@@ -178,16 +178,17 @@ bool decode_base58(const string& btcaddress, unsigned char& version, string& has
unsigned char decoded[25];
size_t nBytes = 0;
- BIGNUM bn58, bn, bnChar;
+ BIGNUM *bn58, *bn, *bnChar;
BN_CTX *ctx;
ctx = BN_CTX_new();
- BN_init(&bn58);
- BN_init(&bn);
- BN_init(&bnChar);
- BN_set_word(&bn58, 58);
- BN_set_word(&bn, 0);
+ bn58 = BN_new();
+ bn = BN_new();
+ bnChar = BN_new();
+
+ BN_set_word(bn58, 58);
+ BN_set_word(bn, 0);
for (unsigned int i = 0; i < btcaddress.length(); i++) {
const char *p1 = strchr(base58_chars, btcaddress[i]);
@@ -195,23 +196,23 @@ bool decode_base58(const string& btcaddress, unsigned char& version, string& has
goto out;
}
- BN_set_word(&bnChar, p1 - base58_chars);
+ BN_set_word(bnChar, p1 - base58_chars);
- assert(BN_mul(&bn, &bn, &bn58, ctx));
- assert(BN_add(&bn, &bn, &bnChar));
+ assert(BN_mul(bn, bn, bn58, ctx));
+ assert(BN_add(bn, bn, bnChar));
}
- nBytes = BN_num_bytes(&bn);
+ nBytes = BN_num_bytes(bn);
if (nBytes == 0 || nBytes > 25)
return false;
std::fill(decoded, decoded+25, (unsigned char)0);
- BN_bn2bin(&bn, &decoded[25-nBytes]);
+ BN_bn2bin(bn, &decoded[25-nBytes]);
out:
- BN_clear_free(&bn58);
- BN_clear_free(&bn);
- BN_clear_free(&bnChar);
+ BN_clear_free(bn58);
+ BN_clear_free(bn);
+ BN_clear_free(bnChar);
BN_CTX_free(ctx);
version = decoded[0];
diff --git a/c++/paymentrequest-dump.cpp b/c++/paymentrequest-dump.cpp
index d20e400..d28d1dd 100644
--- a/c++/paymentrequest-dump.cpp
+++ b/c++/paymentrequest-dump.cpp
@@ -133,12 +133,14 @@ int main(int argc, char **argv) {
request.SerializeToString(&data_to_verify);
request.set_signature(signature);
- EVP_MD_CTX ctx;
+ EVP_MD_CTX *ctx;
+ ctx = EVP_MD_CTX_new();
+
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*)signature.data(), signature.size(), pubkey)) {
+ 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*)signature.data(), signature.size(), pubkey)) {
printf("Bad signature, invalid PaymentRequest.\n");
}
```
Notes:
- the merchant certificate is the first in the chain, then all the intermediate certificate authorities in reverse order, and finally the root certificate authority. The private key is the one for the merchant.
- do not run the `create_ca.sh` and `create_intermediate_cas.sh` more than once, or delete the previous results in between two runs. This is because re-running it causes some or all keys to be overwritten, but it fails to recreate the new corresponding certs.