From 39db24ab7c54f1d34795676f8c043fd1146573ac Mon Sep 17 00:00:00 2001 From: Switck <69336248+switck@users.noreply.github.com> Date: Wed, 3 Feb 2021 11:54:48 -0500 Subject: [PATCH 1/2] ref/c: segwit_decode_addr_details: capture details and return --- ref/c/segwit_addr.c | 31 +++++++++++++++++++++++++++---- ref/c/segwit_addr.h | 35 +++++++++++++++++++++++++++++------ 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/ref/c/segwit_addr.c b/ref/c/segwit_addr.c index a1164e7..bf50cfc 100644 --- a/ref/c/segwit_addr.c +++ b/ref/c/segwit_addr.c @@ -189,21 +189,44 @@ int segwit_addr_encode(char *output, const char *hrp, int witver, const uint8_t return bech32_encode(output, hrp, data, datalen, enc); } -int segwit_addr_decode(int* witver, uint8_t* witdata, size_t* witdata_len, const char* hrp, const char* addr) { +int segwit_addr_decode_detailed(int* witver, uint8_t* witdata, size_t* witdata_len, + char *hrp_out, bech32_encoding* enc_out, const char* addr) +{ uint8_t data[84]; char hrp_actual[84]; size_t data_len; + bech32_encoding enc = bech32_decode(hrp_actual, data, &data_len, addr); if (enc == BECH32_ENCODING_NONE) return 0; if (data_len == 0 || data_len > 65) return 0; - if (strncmp(hrp, hrp_actual, 84) != 0) return 0; if (data[0] > 16) return 0; - if (data[0] == 0 && enc != BECH32_ENCODING_BECH32) return 0; - if (data[0] > 0 && enc != BECH32_ENCODING_BECH32M) return 0; + *witdata_len = 0; if (!convert_bits(witdata, witdata_len, 8, data + 1, data_len - 1, 5, 0)) return 0; if (*witdata_len < 2 || *witdata_len > 40) return 0; if (data[0] == 0 && *witdata_len != 20 && *witdata_len != 32) return 0; + *witver = data[0]; + + if(hrp_out) { + strncpy(hrp_out, hrp_actual, 20); + } + if(enc_out) *enc_out = enc; + + return 1; +} + +int segwit_addr_decode(int* witver, uint8_t* witdata, size_t* witdata_len, const char* hrp, const char* addr) { + + char hrp_actual[84]; + bech32_encoding enc; + + int ok = segwit_addr_decode_detailed(witver, witdata, witdata_len, hrp_actual, &enc, addr); + if (!ok) return 0; + + if (strncmp(hrp, hrp_actual, 84) != 0) return 0; + if ((*witver) == 0 && enc != BECH32_ENCODING_BECH32) return 0; + if ((*witver) > 0 && enc != BECH32_ENCODING_BECH32M) return 0; + return 1; } diff --git a/ref/c/segwit_addr.h b/ref/c/segwit_addr.h index 511970a..1d768b9 100644 --- a/ref/c/segwit_addr.h +++ b/ref/c/segwit_addr.h @@ -24,6 +24,13 @@ #include +/** Supported encodings. */ +typedef enum { + BECH32_ENCODING_NONE, + BECH32_ENCODING_BECH32, + BECH32_ENCODING_BECH32M +} bech32_encoding; + /** Encode a SegWit address * @@ -65,12 +72,28 @@ int segwit_addr_decode( const char* addr ); -/** Supported encodings. */ -typedef enum { - BECH32_ENCODING_NONE, - BECH32_ENCODING_BECH32, - BECH32_ENCODING_BECH32M -} bech32_encoding; + +/** Decode a SegWit address, capturing details. + * + * Out: ver: Pointer to an int that will be updated to contain the witness + * program version (between 0 and 16 inclusive). + * prog: Pointer to a buffer of size 40 that will be updated to + * contain the witness program bytes. + * prog_len: Pointer to a size_t that will be updated to contain the length + * of bytes in prog. + * hrp_out: Pointer to char[10] to hold observed HRP value, or NULL if not wanted. + * encoding: Pointer to return observed bech32 encoding (or NULL, unused) + * addr: Pointer to the null-terminated address. + * Returns 1 if successful. + */ +int segwit_addr_decode_detailed( + int* ver, + uint8_t* prog, + size_t* prog_len, + char *hrp_out, + bech32_encoding* encoding, + const char* addr +); /** Encode a Bech32 or Bech32m string * From 10d38fbba12da9f93c54c7fd44376152e1c06d85 Mon Sep 17 00:00:00 2001 From: Switck <69336248+switck@users.noreply.github.com> Date: Fri, 5 Feb 2021 08:44:02 -0500 Subject: [PATCH 2/2] Restore encoding vs. version checks --- ref/c/segwit_addr.c | 13 ++++++------- ref/c/segwit_addr.h | 6 ++---- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/ref/c/segwit_addr.c b/ref/c/segwit_addr.c index bf50cfc..390b3da 100644 --- a/ref/c/segwit_addr.c +++ b/ref/c/segwit_addr.c @@ -190,7 +190,7 @@ int segwit_addr_encode(char *output, const char *hrp, int witver, const uint8_t } int segwit_addr_decode_detailed(int* witver, uint8_t* witdata, size_t* witdata_len, - char *hrp_out, bech32_encoding* enc_out, const char* addr) + char *hrp_out, const char* addr) { uint8_t data[84]; char hrp_actual[84]; @@ -202,16 +202,18 @@ int segwit_addr_decode_detailed(int* witver, uint8_t* witdata, size_t* witdata_l if (data[0] > 16) return 0; *witdata_len = 0; + *witver = data[0]; + if (!convert_bits(witdata, witdata_len, 8, data + 1, data_len - 1, 5, 0)) return 0; if (*witdata_len < 2 || *witdata_len > 40) return 0; if (data[0] == 0 && *witdata_len != 20 && *witdata_len != 32) return 0; - *witver = data[0]; + if (data[0] == 0 && enc != BECH32_ENCODING_BECH32) return 0; + if (data[0] > 0 && enc != BECH32_ENCODING_BECH32M) return 0; if(hrp_out) { strncpy(hrp_out, hrp_actual, 20); } - if(enc_out) *enc_out = enc; return 1; } @@ -219,14 +221,11 @@ int segwit_addr_decode_detailed(int* witver, uint8_t* witdata, size_t* witdata_l int segwit_addr_decode(int* witver, uint8_t* witdata, size_t* witdata_len, const char* hrp, const char* addr) { char hrp_actual[84]; - bech32_encoding enc; - int ok = segwit_addr_decode_detailed(witver, witdata, witdata_len, hrp_actual, &enc, addr); + int ok = segwit_addr_decode_detailed(witver, witdata, witdata_len, hrp_actual, addr); if (!ok) return 0; if (strncmp(hrp, hrp_actual, 84) != 0) return 0; - if ((*witver) == 0 && enc != BECH32_ENCODING_BECH32) return 0; - if ((*witver) > 0 && enc != BECH32_ENCODING_BECH32M) return 0; return 1; } diff --git a/ref/c/segwit_addr.h b/ref/c/segwit_addr.h index 1d768b9..096870f 100644 --- a/ref/c/segwit_addr.h +++ b/ref/c/segwit_addr.h @@ -73,7 +73,7 @@ int segwit_addr_decode( ); -/** Decode a SegWit address, capturing details. +/** Decode a SegWit address, capturing HRP. * * Out: ver: Pointer to an int that will be updated to contain the witness * program version (between 0 and 16 inclusive). @@ -81,8 +81,7 @@ int segwit_addr_decode( * contain the witness program bytes. * prog_len: Pointer to a size_t that will be updated to contain the length * of bytes in prog. - * hrp_out: Pointer to char[10] to hold observed HRP value, or NULL if not wanted. - * encoding: Pointer to return observed bech32 encoding (or NULL, unused) + * hrp_out: Pointer to char[20] to hold observed HRP value, or NULL if not wanted. * addr: Pointer to the null-terminated address. * Returns 1 if successful. */ @@ -91,7 +90,6 @@ int segwit_addr_decode_detailed( uint8_t* prog, size_t* prog_len, char *hrp_out, - bech32_encoding* encoding, const char* addr );