🔥 Burn Fat Fast. Discover How! 💪

The decrypt method uses the following methods: 1) get_eckey_fr | 🎩BLACK HAT🎩

The decrypt method uses the following methods:
1) get_eckey_from_password - getting the EC_KEY from the secret. The method returns an object of the ECPrivkey class, which we will refer to later.
2) get_encryption_magic - getting the encryption method (password, key, etc.). You can see that I have shortened this method to return b'BIE1 ', since I will only be looking at the password encryption method. BIE1 - the first 4 characters of the wallet, which are responsible for the encryption method (do base64 decode if you don't trust)

The next step is to consider the methods of the ECPrivkey class, specifically, the decrypt_message method, which will give us the desired YES or NO when checking the password. Let's start in order: first we call the decrypt (password) -> get_eckey_from_password (password) method which refers to the ecc.ECPrivkey.from_arbitrary_size_secret (secret) method

Let's create an ecc.py file in the src working directory, which will contain the ECPrivkey class :

PS: I follow the same naming conventions for the electrum project to avoid confusion.

it should look like this:


electrum
venv
main.py
src
├── ecc.py
└── __init__.py



In init.py, let's denote our ecc.py
init.py



from . import ecc



Let's start generating ecc.py: at this stage we need the ECPubkey and ECPrivkey classes with the set of methods necessary for our purposes.

First of all, we call the static method of the class: ECPrivkey.from_arbitrary_size_secret (secret), let's see what happens there: refer to electrum / ecc.py

Again, everything is confusing ... let's write it in a readable form:



from_arbitrary_size_secret() --> init class ECPrivkey(какой-то скаляр) --> init class ECPubkey(что-то нечеловеческое).


Those. the static method from_arbitrary_size_secret initializes the ECPrivkey class, which in turn, upon initialization, initializes the ECPubkey (GENERATOR) class.

Let's put it all out:

ecc.py


from typing import Union, Tuple, Optional
from ctypes import (
byref, c_byte, c_int, c_uint, c_char_p, c_size_t, c_void_p, create_string_buffer,
CFUNCTYPE, POINTER, cast
)
import base64
import hashlib

from src.util import assert_bytes
from src.ecc_fast import _libsecp256k1, SECP256K1_EC_UNCOMPRESSED
from src.crypto import hmac_oneshot

def string_to_number(b: bytes) -> int:
return int.from_bytes(b, byteorder='big', signed=False)

def is_secret_within_curve_range(secret: Union[int, bytes]) -> bool:
if isinstance(secret, bytes):
secret = string_to_number(secret)
return 0 < secret < CURVE_ORDER

def _x_and_y_from_pubkey_bytes(pubkey: bytes) -> Tuple[int, int]:
assert isinstance(pubkey, bytes), f'pubkey must be bytes, not {type(pubkey)}'

pubkey_ptr = create_string_buffer(64)
ret = _libsecp256k1.secp256k1_ec_pubkey_parse(
_libsecp256k1.ctx, pubkey_ptr, pubkey, len(pubkey))
if not ret:
raise InvalidECPointException('public key could not be parsed or is invalid')

pubkey_serialized = create_string_buffer(65)
pubkey_size = c_size_t(65)
_libsecp256k1.secp256k1_ec_pubkey_serialize(
_libsecp256k1.ctx, pubkey_serialized, byref(pubkey_size), pubkey_ptr, SECP256K1_EC_UNCOMPRESSED)
pubkey_serialized = bytes(pubkey_serialized)
assert pubkey_serialized[0] == 0x04, pubkey_serialized
x = int.from_bytes(pubkey_serialized[1:33], byteorder='big', signed=False)
y = int.from_bytes(pubkey_serialized[33:65], byteorder='big', signed=False)
return x, y

class ECPubkey(object):

def __init__(self, b: Optional[bytes]):
if b is not None:
assert isinstance(b, (bytes, bytearray)), f'pubkey must be bytes-like, not {type(b)}'
if isinstance(b, bytearray):
b = bytes(b)
self._x, self._y = _x_and_y_from_pubkey_bytes(b)
else:
self._x, self._y = None, None

def is_at_infinity(self):
return self == POINT_AT_INFINITY

def x(self) -> int:
return self._x

def y(self) -> int:
return self._y