Page MenuHomePhabricator

[paymentservertests] fix certificates and payment requests
ClosedPublic

Authored by PiRK on Dec 14 2022, 11:35.

Details

Reviewers
Fabien
Group Reviewers
Restricted Project
Commits
rABC0c1aa523d1ac: [paymentservertests] fix certificates and payment requests
Summary

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

# get caCert1_BASE64 (root authority)
openssl x509 -in ca_in_a_box/certs/cacert.pem -inform PEM -outform DER | openssl enc -base64

cd c++
# ... fix outdated openssl code and then compile
make

mv ../ca_in_a_box .

# get paymentrequest1_cert1_BASE64 by running the program with default certs and privatekey
./paymentrequest-create paytoaddress=1Nf4eZ76SFZdhrHVNLQkLAiS1oPPGaZxSv  amount=42 expires=1986627327 | ./paymentrequest-dump
./paymentrequest-create paytoaddress=1Nf4eZ76SFZdhrHVNLQkLAiS1oPPGaZxSv  amount=42 expires=1986627327 | base64

# get paymentrequest3_cert1_BASE64 by chaining the certificates
./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.
Test Plan

ninja check-bitcoin-qt

Diff Detail