Skip to content

Commit

Permalink
Merge pull request #3 from jaxlotl/verify_address_new
Browse files Browse the repository at this point in the history
Refactored address verification
  • Loading branch information
xanimo authored Mar 8, 2022
2 parents 02602dd + ee33917 commit 96639d0
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 89 deletions.
53 changes: 0 additions & 53 deletions bindings/py_wrappers/pytest/block_test.py

This file was deleted.

5 changes: 3 additions & 2 deletions bindings/py_wrappers/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def verify_master_priv_pub_keypair(wif_privkey_master, p2pkh_pubkey_master, chai

# call c function
res = ct.c_bool()
res = lib.verifyHDMasterPubKeypair(wif_privkey_master_ptr, p2pkh_pubkey_master_ptr, ct.c_int(chain_code))
res = lib.verifyHDMasterPubKeypair(wif_privkey_master_ptr, p2pkh_pubkey_master_ptr, ct.c_bool(chain_code))

# stop context
lib.dogecoin_ecc_stop()
Expand All @@ -190,13 +190,14 @@ def verify_p2pkh_address(p2pkh_pubkey, chain_code=0):

# prepare arguments
p2pkh_pubkey_ptr = ct.c_char_p(p2pkh_pubkey.encode('utf-8'))
strlen = ct.c_ubyte(len(p2pkh_pubkey))

# start context
lib.dogecoin_ecc_start()

# call c function
res = ct.c_bool()
res = lib.verifyP2pkhAddress(p2pkh_pubkey_ptr, ct.c_int(chain_code))
res = lib.verifyP2pkhAddress(p2pkh_pubkey_ptr, strlen, ct.c_int(chain_code))

# stop context
lib.dogecoin_ecc_stop()
Expand Down
8 changes: 4 additions & 4 deletions include/dogecoin/address.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,17 @@ LIBDOGECOIN_API int generatePrivPubKeypair(char* wif_privkey, char* p2pkh_pubkey
LIBDOGECOIN_API int generateHDMasterPubKeypair(char* wif_privkey_master, char* p2pkh_pubkey_master, bool is_testnet);

/* generate an extended public key */
LIBDOGECOIN_API int generateDerivedHDPubkey(char* wif_privkey_master, char* p2pkh_pubkey);
LIBDOGECOIN_API int generateDerivedHDPubkey(const char* wif_privkey_master, char* p2pkh_pubkey);

/* verify private and public keys are valid and associated with each other*/
LIBDOGECOIN_API int verifyPrivPubKeypair(char* wif_privkey, char* p2pkh_pubkey, bool is_testnet);

/* verify private and public masters keys are valid and associated with each other */
LIBDOGECOIN_API int verifyHDMasterPubKeypair(char* wif_privkey_master, char* p2pkh_pubkey_master, bool is_testnet);

/* verify address based on appearance only */
LIBDOGECOIN_API int verifyP2pkhAddress(char* p2pkh_pubkey, uint8_t len, bool is_testnet);
/* verify address based on length and checksum */
LIBDOGECOIN_API int verifyP2pkhAddress(char* p2pkh_pubkey, uint8_t len);

LIBDOGECOIN_END_DECL

#endif // __LIBDOGECOIN_ADDRESS_H__
#endif // __LIBDOGECOIN_ADDRESS_H__
51 changes: 35 additions & 16 deletions src/address.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
#include <dogecoin/bip32.h>
#include <dogecoin/crypto/key.h>
#include <dogecoin/crypto/random.h>
#include <dogecoin/crypto/sha2.h>
#include <dogecoin/crypto/base58.h>
#include <dogecoin/tool.h>
#include <dogecoin/utils.h>

Expand Down Expand Up @@ -141,10 +143,10 @@ int generateHDMasterPubKeypair(char* wif_privkey_master, char* p2pkh_pubkey_mast
return true;
}

int generateDerivedHDPubkey(char* wif_privkey_master, char* p2pkh_pubkey)
int generateDerivedHDPubkey(const char* wif_privkey_master, char* p2pkh_pubkey)
{
/* require master key */
if (!wif_privkey_master || !p2pkh_pubkey) {
if (!wif_privkey_master) {
return false;
}

Expand All @@ -153,8 +155,26 @@ int generateDerivedHDPubkey(char* wif_privkey_master, char* p2pkh_pubkey)
memcpy(prefix, wif_privkey_master, 1);
const dogecoin_chainparams* chain = memcmp(prefix, "d", 1) == 0 ? &dogecoin_chainparams_main : &dogecoin_chainparams_test;

/* generate p2pkh from private key */
generatePrivPubKeypair(wif_privkey_master, p2pkh_pubkey, memcmp(prefix, "d", 1) == 0 ? false : true);
size_t strsize = 128;
char str[strsize];

/* if nothing is passed in use internal variables */
if (p2pkh_pubkey) {
memcpy(str, p2pkh_pubkey, strsize);
}

dogecoin_hdnode node;
dogecoin_hdnode_deserialize(wif_privkey_master, chain, &node);

dogecoin_hdnode_get_p2pkh_address(&node, chain, str, strsize);

/* pass back to external variable if exists */
if (p2pkh_pubkey) {
memcpy(p2pkh_pubkey, str, strsize);
}

/* reset internal variables */
memset(str, 0, strlen(str));

return true;
}
Expand Down Expand Up @@ -211,21 +231,20 @@ int verifyHDMasterPubKeypair(char* wif_privkey_master, char* p2pkh_pubkey_master
return true;
}

int verifyP2pkhAddress(char* p2pkh_pubkey, uint8_t len, bool is_testnet) {
if (!p2pkh_pubkey) return false;
int verifyP2pkhAddress(char* p2pkh_pubkey, uint8_t len) {
if (!p2pkh_pubkey || !len) return false;
/* check length */
if (len != 33) {
return false;
}
/* check first character */
if (p2pkh_pubkey[0] != (is_testnet ? 110 : 68)) {
unsigned char dec[len], d1[SHA256_DIGEST_LENGTH], d2[SHA256_DIGEST_LENGTH];
if (!dogecoin_base58_decode_check(p2pkh_pubkey, dec, len)) {
printf("address length is not valid!\n");
return false;
}
/* check randomness */
double entropy;
utils_calculate_shannon_entropy(p2pkh_pubkey, len + 1, &entropy);
if (entropy < 0.12244) {
/* check validity */
sha256_raw(dec, 21, d1);
sha256_raw(d1, SHA256_DIGEST_LENGTH, d2);
if (memcmp(dec + 21, d2, 4) != 0) {
printf("checksums do not match!\n");
return false;
}
return true;
}
}
37 changes: 23 additions & 14 deletions test/address_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@

#include <dogecoin/address.h>
#include <dogecoin/chainparams.h>
#include <dogecoin/crypto/base58.h>
#include <dogecoin/dogecoin.h>
#include <dogecoin/utils.h>

void test_address()
{
size_t privkeywiflen = 53;
size_t privkeywiflen = 100;
char privkeywif_main[privkeywiflen];
char privkeywif_test[privkeywiflen];
char p2pkh_pubkey_main[DOGECOIN_ECKEY_COMPRESSED_LENGTH];
Expand All @@ -35,15 +35,12 @@ void test_address()
u_assert_int_eq(verifyPrivPubKeypair("QWgNKvA5LPD1HpopRFghjz6jPipHRAUrLjqTt7paxYX8cTbu5eRs", "DCncxpcZW3GEyqs17KrqAfs4cR844JkimG", false), false);

// test entropy check
u_assert_int_eq(verifyP2pkhAddress("Dasdfasdfasdfasdfasdfasdfasdfasdfx", 33, false), false);
u_assert_int_eq(verifyP2pkhAddress("DP6xxxDJxxxJAaWucRfsPvXLPGRyF3DdeP", 33, false), false);
u_assert_int_eq(verifyP2pkhAddress("Dasdfasdfasdfasdfasdfasdfasdfasdfx", strlen("Dasdfasdfasdfasdfasdfasdfasdfasdfx")), false);
u_assert_int_eq(verifyP2pkhAddress("DP6xxxDJxxxJAaWucRfsPvXLPGRyF3DdeP", strlen("DP6xxxDJxxxJAaWucRfsPvXLPGRyF3DdeP")), false);

// test address format correctness (0.3% false negative rate)

u_assert_int_eq(verifyP2pkhAddress(p2pkh_pubkey_main, DOGECOIN_ECKEY_COMPRESSED_LENGTH, false), true);
u_assert_int_eq(verifyP2pkhAddress(p2pkh_pubkey_test, DOGECOIN_ECKEY_COMPRESSED_LENGTH, true), true);
u_assert_int_eq(verifyP2pkhAddress(p2pkh_pubkey_main, DOGECOIN_ECKEY_COMPRESSED_LENGTH, true), false);
u_assert_int_eq(verifyP2pkhAddress(p2pkh_pubkey_test, DOGECOIN_ECKEY_COMPRESSED_LENGTH, false), false);
u_assert_int_eq(verifyP2pkhAddress(p2pkh_pubkey_main, strlen(p2pkh_pubkey_main)), true);
u_assert_int_eq(verifyP2pkhAddress(p2pkh_pubkey_test, strlen(p2pkh_pubkey_test)), true);

// test master key generation ability
size_t masterkeysize = 200;
Expand All @@ -60,20 +57,32 @@ void test_address()
// test child key derivation ability
char child_key_main[DOGECOIN_ECKEY_COMPRESSED_LENGTH];
char child_key_test[DOGECOIN_ECKEY_COMPRESSED_LENGTH];
u_assert_int_eq(generateDerivedHDPubkey(masterkey_main, NULL), true)
u_assert_int_eq(generateDerivedHDPubkey(NULL, NULL), false)
u_assert_int_eq(generateDerivedHDPubkey(masterkey_main, child_key_main), true);
u_assert_int_eq(generateDerivedHDPubkey(masterkey_test, child_key_test), true);

// test master keypair validity and association
u_assert_int_eq(verifyHDMasterPubKeypair(masterkey_main, child_key_main, false), true);
// u_assert_int_eq(verifyHDMasterPubKeypair(masterkey_test, child_key_test, true), true);
u_assert_int_eq(verifyHDMasterPubKeypair("dgpv51eADS3spNJh7z2oc8LgNLeJiwiPNgdEFcdtAhtCqDQ76SwphcQq74jZCRTZ2nF5RpmKx9P4Mm55RTopNQePWiSBfzyJ3jgRoxVbVLF6BCY", "DJt45oTXDxBiJBRZeMtXm4wu4kc5yPePYn", false), true);
u_assert_int_eq(verifyHDMasterPubKeypair("dgpv51eADS3spNJh7z2oc8LgNLeJiwiPNgdEFcdtAhtCqDQ76SwphcQq74jZCRTZ2nF5RpmKx9P4Mm55RTopNQePWiSBfzyJ3jgRoxVbVLF6BCY", "DDDXCMUCXCFK3UHXsjqSkzwoqt79K6Rn6k", false), false);

// test hd address format correctness
u_assert_int_eq(verifyP2pkhAddress(p2pkh_master_pubkey_main, DOGECOIN_ECKEY_COMPRESSED_LENGTH, false), true);
// u_assert_int_eq(verifyP2pkhAddress(p2pkh_master_pubkey_test, DOGECOIN_ECKEY_COMPRESSED_LENGTH, true), true);
u_assert_int_eq(verifyP2pkhAddress(p2pkh_master_pubkey_main, strlen(p2pkh_master_pubkey_main)), true);
// u_assert_int_eq(verifyP2pkhAddress(p2pkh_master_pubkey_test, true), true);

// test derived hd address format correctness
u_assert_int_eq(generateDerivedHDPubkey(masterkey_main, child_key_main), true);
u_assert_int_eq(verifyP2pkhAddress(child_key_main, DOGECOIN_ECKEY_COMPRESSED_LENGTH, false), false);
u_assert_int_eq(verifyP2pkhAddress(child_key_main, strlen(child_key_main)), true);
u_assert_int_eq(generateDerivedHDPubkey(masterkey_test, child_key_test), true);
u_assert_int_eq(verifyP2pkhAddress(child_key_test, DOGECOIN_ECKEY_COMPRESSED_LENGTH, true), true);
}
//u_assert_int_eq(verifyP2pkhAddress(child_key_test, true), true);

size_t strsize = 128;
char str[strsize];
u_assert_int_eq(generateDerivedHDPubkey("dgpv51eADS3spNJhA6LG5QycrFmQQtxg7ztFJQuamYiytZ4x4FUC7pG5B7fUTHBDB7g6oGaCVwuGF2i75r1DQKyFSauAHUGBAi89NaggpdUP3yK", str), true)
u_assert_str_eq("DEByFfUQ3AxcFFet9afr8wxxedQysRduWN", str);

u_assert_int_eq(generateDerivedHDPubkey("tprv8ZgxMBicQKsPeM5HaRoH4AuGX2Jsf8rgQvcFGCvjQxvAn1Bv8SAx8cPQsnmKsB6WjvGWsNiNsrNS2d3quUkYpK2ofctFw87SXodGhBPHiUM", str), true)
u_assert_str_eq("noBtVVtAvvh5oapFjHHyTSxxEUTykUZ3oR", str);
}

0 comments on commit 96639d0

Please sign in to comment.