Skip to content

Commit

Permalink
Improve the verification of v value in signature
Browse files Browse the repository at this point in the history
  • Loading branch information
joii2020 committed Oct 23, 2023
1 parent 3303d5f commit 5161503
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 17 deletions.
59 changes: 44 additions & 15 deletions c/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ int md_string(const mbedtls_md_info_t *md_info, const uint8_t *buf, size_t n,
static int _recover_secp256k1_pubkey(const uint8_t *sig, size_t sig_len,
const uint8_t *msg, size_t msg_len,
uint8_t *out_pubkey,
size_t *out_pubkey_size, bool compressed) {
size_t *out_pubkey_size, int recid, bool compressed) {
int ret = 0;

if (sig_len != SECP256K1_SIGNATURE_SIZE) {
Expand All @@ -102,8 +102,7 @@ static int _recover_secp256k1_pubkey(const uint8_t *sig, size_t sig_len,
}

secp256k1_ecdsa_recoverable_signature signature;
if (secp256k1_ecdsa_recoverable_signature_parse_compact(
&context, &signature, sig, sig[RECID_INDEX]) == 0) {
if (secp256k1_ecdsa_recoverable_signature_parse_compact(&context, &signature, sig, (int)recid) == 0) {
return ERROR_WRONG_STATE;
}

Expand All @@ -128,12 +127,27 @@ static int _recover_secp256k1_pubkey(const uint8_t *sig, size_t sig_len,
return ret;
}

// Refer to: https://en.bitcoin.it/wiki/BIP_0137
int get_btc_recid(uint8_t d, bool *compressed) {
if (d >= 27 && d <= 30) { // P2PKH uncompressed
if (compressed) *compressed = false;
return d - 27;
} else if (d >= 31 && d <= 34) { // P2PKH compressed
if (compressed) *compressed = true;
return d - 31;
} else if (d >= 35 && d <= 38) { // Segwit P2SH
return d - 35;
} else if (d >= 39 && d <= 42) { // Segwit Bech32
return d - 39;
} else {
return -1;
}
}

static int _recover_secp256k1_pubkey_btc(const uint8_t *sig, size_t sig_len,
const uint8_t *msg, size_t msg_len,
uint8_t *out_pubkey,
size_t *out_pubkey_size,
bool compressed) {
(void)compressed;
size_t *out_pubkey_size) {
int ret = 0;

if (sig_len != SECP256K1_SIGNATURE_SIZE) {
Expand All @@ -143,9 +157,11 @@ static int _recover_secp256k1_pubkey_btc(const uint8_t *sig, size_t sig_len,
return ERROR_INVALID_ARG;
}

// change 1
int recid = (sig[0] - 27) & 3;
bool comp = ((sig[0] - 27) & 4) != 0;
bool rec_compressed = false;
int recid = get_btc_recid(sig[0], &rec_compressed);
if (recid == -1) {
return ERROR_INVALID_ARG;
}

/* Load signature */
secp256k1_context context;
Expand All @@ -169,7 +185,7 @@ static int _recover_secp256k1_pubkey_btc(const uint8_t *sig, size_t sig_len,
}

unsigned int flag = SECP256K1_EC_COMPRESSED;
if (comp) {
if (rec_compressed) {
*out_pubkey_size = SECP256K1_PUBKEY_SIZE;
flag = SECP256K1_EC_COMPRESSED;
} else {
Expand All @@ -193,8 +209,8 @@ int validate_signature_ckb(void *prefilled_data, const uint8_t *sig,
}
uint8_t out_pubkey[SECP256K1_PUBKEY_SIZE];
size_t out_pubkey_size = SECP256K1_PUBKEY_SIZE;
ret = _recover_secp256k1_pubkey(sig, sig_len, msg, msg_len, out_pubkey,
&out_pubkey_size, true);

ret = _recover_secp256k1_pubkey(sig, sig_len, msg, msg_len, out_pubkey, &out_pubkey_size, sig[RECID_INDEX], true);
if (ret != 0) return ret;

blake2b_state ctx;
Expand All @@ -217,8 +233,21 @@ int validate_signature_eth(void *prefilled_data, const uint8_t *sig,
}
uint8_t out_pubkey[UNCOMPRESSED_SECP256K1_PUBKEY_SIZE];
size_t out_pubkey_size = UNCOMPRESSED_SECP256K1_PUBKEY_SIZE;
ret = _recover_secp256k1_pubkey(sig, sig_len, msg, msg_len, out_pubkey,
&out_pubkey_size, false);

// https://github.com/ethereum/go-ethereum/blob/v1.13.4/crypto/signature_nocgo.go#L72
// The produced signature is in the [R || S || V] format where V is 0 or 1.
int recid = sig[RECID_INDEX];

// where the V value will be 27 or 28 for legacy reasons
// https://ethereum.github.io/yellowpaper/paper.pdf
if (recid == 27 || recid == 28) {
recid = recid - 27;
}
if (recid != 0 && recid != 1) {
return ERROR_INVALID_ARG;
}

ret = _recover_secp256k1_pubkey(sig, sig_len, msg, msg_len, out_pubkey, &out_pubkey_size, recid, false);
if (ret != 0) return ret;

// here are the 2 differences than validate_signature_secp256k1
Expand All @@ -243,7 +272,7 @@ int validate_signature_btc(void *prefilled_data, const uint8_t *sig,
uint8_t out_pubkey[UNCOMPRESSED_SECP256K1_PUBKEY_SIZE];
size_t out_pubkey_size = UNCOMPRESSED_SECP256K1_PUBKEY_SIZE;
err = _recover_secp256k1_pubkey_btc(sig, sig_len, msg, msg_len, out_pubkey,
&out_pubkey_size, false);
&out_pubkey_size);
CHECK(err);

const mbedtls_md_info_t *md_info =
Expand Down
11 changes: 9 additions & 2 deletions tests/auth_rust/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ fn bitcoin_pubkey_recid_verify() {
verify_unit(&config),
"failed conver btc",
&[
AuthErrorCodeType::InvalidArg as i32,
AuthErrorCodeType::Mismatched as i32,
AuthErrorCodeType::ErrorWrongState as i32,
],
Expand Down Expand Up @@ -476,7 +477,10 @@ fn convert_btc_error() {
assert_result_error(
verify_unit(&config),
"failed conver btc",
&[AuthErrorCodeType::Mismatched as i32],
&[
AuthErrorCodeType::Mismatched as i32,
AuthErrorCodeType::InvalidArg as i32,
],
);
}

Expand Down Expand Up @@ -522,7 +526,10 @@ fn convert_doge_error() {
assert_result_error(
verify_unit(&config),
"failed conver doge",
&[AuthErrorCodeType::Mismatched as i32],
&[
AuthErrorCodeType::Mismatched as i32,
AuthErrorCodeType::InvalidArg as i32,
],
);
}

Expand Down

0 comments on commit 5161503

Please sign in to comment.