mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-31 01:11:35 +00:00
Merge pull request #4442 from SomberNight/bip32_fix_invalid_ecpoint
handle bip32 edge cases
This commit is contained in:
commit
a4da04110e
1 changed files with 30 additions and 5 deletions
|
@ -521,6 +521,21 @@ def minikey_to_private_key(text):
|
|||
BIP32_PRIME = 0x80000000
|
||||
|
||||
|
||||
def protect_against_invalid_ecpoint(func):
|
||||
def func_wrapper(*args):
|
||||
n = args[-1]
|
||||
while True:
|
||||
is_prime = n & BIP32_PRIME
|
||||
try:
|
||||
return func(*args[:-1], n=n)
|
||||
except ecc.InvalidECPointException:
|
||||
print_error('bip32 protect_against_invalid_ecpoint: skipping index')
|
||||
n += 1
|
||||
is_prime2 = n & BIP32_PRIME
|
||||
if is_prime != is_prime2: raise OverflowError()
|
||||
return func_wrapper
|
||||
|
||||
|
||||
# Child private key derivation function (from master private key)
|
||||
# k = master private key (32 bytes)
|
||||
# c = master chain code (extra entropy for key derivation) (32 bytes)
|
||||
|
@ -529,19 +544,25 @@ BIP32_PRIME = 0x80000000
|
|||
# corresponding public key can NOT be determined without the master private key.
|
||||
# However, if n is positive, the resulting private key's corresponding
|
||||
# public key can be determined without the master private key.
|
||||
@protect_against_invalid_ecpoint
|
||||
def CKD_priv(k, c, n):
|
||||
is_prime = n & BIP32_PRIME
|
||||
return _CKD_priv(k, c, bfh(rev_hex(int_to_hex(n,4))), is_prime)
|
||||
|
||||
|
||||
def _CKD_priv(k, c, s, is_prime):
|
||||
keypair = ecc.ECPrivkey(k)
|
||||
try:
|
||||
keypair = ecc.ECPrivkey(k)
|
||||
except ecc.InvalidECPointException as e:
|
||||
raise BitcoinException('Impossible xprv (not within curve order)') from e
|
||||
cK = keypair.get_public_key_bytes(compressed=True)
|
||||
data = bytes([0]) + k + s if is_prime else cK + s
|
||||
I = hmac.new(c, data, hashlib.sha512).digest()
|
||||
k_n = ecc.number_to_string(
|
||||
(ecc.string_to_number(I[0:32]) + ecc.string_to_number(k)) % ecc.CURVE_ORDER,
|
||||
ecc.CURVE_ORDER)
|
||||
I_left = ecc.string_to_number(I[0:32])
|
||||
k_n = (I_left + ecc.string_to_number(k)) % ecc.CURVE_ORDER
|
||||
if I_left >= ecc.CURVE_ORDER or k_n == 0:
|
||||
raise ecc.InvalidECPointException()
|
||||
k_n = ecc.number_to_string(k_n, ecc.CURVE_ORDER)
|
||||
c_n = I[32:]
|
||||
return k_n, c_n
|
||||
|
||||
|
@ -551,14 +572,18 @@ def _CKD_priv(k, c, s, is_prime):
|
|||
# n = index of key we want to derive
|
||||
# This function allows us to find the nth public key, as long as n is
|
||||
# non-negative. If n is negative, we need the master private key to find it.
|
||||
@protect_against_invalid_ecpoint
|
||||
def CKD_pub(cK, c, n):
|
||||
if n & BIP32_PRIME: raise Exception()
|
||||
return _CKD_pub(cK, c, bfh(rev_hex(int_to_hex(n,4))))
|
||||
|
||||
# helper function, callable with arbitrary string
|
||||
# helper function, callable with arbitrary string.
|
||||
# note: 's' does not need to fit into 32 bits here! (c.f. trustedcoin billing)
|
||||
def _CKD_pub(cK, c, s):
|
||||
I = hmac.new(c, cK + s, hashlib.sha512).digest()
|
||||
pubkey = ecc.ECPrivkey(I[0:32]) + ecc.ECPubkey(cK)
|
||||
if pubkey.is_at_infinity():
|
||||
raise ecc.InvalidECPointException()
|
||||
cK_n = pubkey.get_public_key_bytes(compressed=True)
|
||||
c_n = I[32:]
|
||||
return cK_n, c_n
|
||||
|
|
Loading…
Add table
Reference in a new issue