Exemple #1
0
def _prv(self, version):
    raw = version
    raw += int_to_byte(self.depth)
    raw += self.parent_fingerprint
    raw += int_to_big_endian(self.child_number, 4)
    raw += self.chain_code
    raw += int_to_big_endian(self.private_key.secret, 33)
    return encode_base58_checksum(raw)
Exemple #2
0
 def sec(self, compressed=True):
     # returns the binary version of the sec format, NOT hex
     # if compressed, starts with b'\x02' if self.y.num is even, b'\x03' if self.y is odd
     # then self.x.num
     # remember, you have to convert self.x.num/self.y.num to binary using int_to_big_endian
     x = int_to_big_endian(self.x.num, 32)
     if compressed:
         if self.y.num % 2 == 0:
             return b'\x02' + x
         else:
             return b'\x03' + x
     else:
         # if non-compressed, starts with b'\x04' followod by self.x and then self.y
         y = int_to_big_endian(self.y.num, 32)
         return b'\x04' + x + y
Exemple #3
0
 def raw_serialize(self, version):
     # version + depth + parent_fingerprint + child number + chain code + private key
     # start with version, which should be a constant depending on testnet
     raw = version
     # add depth, which is 1 byte using int_to_byte
     raw += int_to_byte(self.depth)
     # add the parent_fingerprint
     raw += self.parent_fingerprint
     # add the child number 4 bytes using int_to_big_endian
     raw += int_to_big_endian(self.child_number, 4)
     # add the chain code
     raw += self.chain_code
     # add the 0 byte and the private key's secret in big endian, 33 bytes
     raw += int_to_big_endian(self.private_key.secret, 33)
     return raw
Exemple #4
0
 def child(self, index):
     '''Returns the child HDPrivateKey at a particular index.
     Raises ValueError for indices >= 0x8000000.
     '''
     # if index >= 0x80000000, raise a ValueError
     if index >= 0x80000000:
         raise ValueError('child number should always be less than 2^31')
     # data is the SEC compressed and the index in 4 bytes big-endian
     data = self.point.sec() + int_to_big_endian(index, 4)
     # get hmac_sha512 with chain code, data
     h = hmac_sha512(self.chain_code, data)
     # the new public point is the current point +
     #  the first 32 bytes in big endian * G
     point = self.point + big_endian_to_int(h[:32]) * G
     # chain code is the last 32 bytes
     chain_code = h[32:]
     # depth is current depth + 1
     depth = self.depth + 1
     # parent_fingerprint is the fingerprint of this node
     parent_fingerprint = self.fingerprint()
     # child number is the index
     child_number = index
     # return the HDPublicKey instance
     return HDPublicKey(
         point=point,
         chain_code=chain_code,
         depth=depth,
         parent_fingerprint=parent_fingerprint,
         child_number=child_number,
         testnet=self.testnet,
     )
Exemple #5
0
def secure_mnemonic(entropy=0, num_bits=128):
    '''Generates a mnemonic phrase using the number of bits'''
    # if we have more than 128 bits, just mask everything but the last 128 bits
    if len(bin(entropy)) > num_bits + 2:
        entropy &= (1 << num_bits) - 1
    # xor some random bits with the entropy that was passed in
    preseed = randbits(num_bits) ^ entropy
    # convert the number to big-endian
    s = int_to_big_endian(preseed, 16)
    # 1 extra bit for checksum is needed per 32 bits
    checksum_bits_needed = num_bits // 32
    # the checksum is the sha256's first n bits. At most this is 8
    checksum = sha256(s)[0] >> (8 - checksum_bits_needed)
    # we concatenate the checksum to the preseed
    total = (preseed << checksum_bits_needed) | checksum
    # now we get the mnemonic passphrase
    mnemonic = []
    # now group into groups of 11 bits
    for _ in range((num_bits + checksum_bits_needed) // 11):
        # grab the last 11 bits
        current = total & ((1 << 11) - 1)
        # insert the correct word at the front
        mnemonic.insert(0, WORD_LIST[current])
        # shift by 11 bits so we can move to the next set
        total >>= 11
    # return the mnemonic phrase by putting spaces between
    return ' '.join(mnemonic)
Exemple #6
0
def _serialize(self, version):
    raw = version
    raw += int_to_byte(self.depth)
    raw += self.parent_fingerprint
    raw += int_to_big_endian(self.child_number, 4)
    raw += self.chain_code
    raw += self.point.sec()
    return raw
Exemple #7
0
 def _prv(self, version):
     '''Returns the base58-encoded x/y/z prv.
     Expects a 4-byte version.'''
     # version + depth + parent_fingerprint + child number + chain code + private key
     # start with version, which should be a constant depending on testnet
     raw = version
     # add depth, which is 1 byte using int_to_byte
     raw += int_to_byte(self.depth)
     # add the parent_fingerprint
     raw += self.parent_fingerprint
     # add the child number 4 bytes using int_to_big_endian
     raw += int_to_big_endian(self.child_number, 4)
     # add the chain code
     raw += self.chain_code
     # add the 0 byte and the private key's secret in big endian, 33 bytes
     raw += int_to_big_endian(self.private_key.secret, 33)
     # return the whole thing base58-encoded
     return encode_base58_checksum(raw)
Exemple #8
0
 def deterministic_k(self, z):
     k = b'\x00' * 32
     v = b'\x01' * 32
     if z > N:
         z -= N
     z_bytes = int_to_big_endian(z, 32)
     secret_bytes = int_to_big_endian(self.secret, 32)
     s256 = hashlib.sha256
     k = hmac.new(k, v + b'\x00' + secret_bytes + z_bytes, s256).digest()
     v = hmac.new(k, v, s256).digest()
     k = hmac.new(k, v + b'\x01' + secret_bytes + z_bytes, s256).digest()
     v = hmac.new(k, v, s256).digest()
     while True:
         v = hmac.new(k, v, s256).digest()
         candidate = big_endian_to_int(v)
         if candidate >= 1 and candidate < N:
             return candidate
         k = hmac.new(k, v + b'\x00', s256).digest()
         v = hmac.new(k, v, s256).digest()
Exemple #9
0
def xprv_child(self, index):
    if index >= 0x80000000:
        data = int_to_big_endian(self.private_key.secret, 33) + int_to_big_endian(index, 4)
    else:
        data = self.private_key.point.sec() + int_to_big_endian(index, 4)
    h = hmac_sha512(self.chain_code, data)
    secret = (big_endian_to_int(h[:32]) + self.private_key.secret) % N
    private_key = PrivateKey(secret=secret)
    chain_code = h[32:]
    depth = self.depth + 1
    parent_fingerprint = self.pub.hash160()[:4]
    child_number = index
    return HDPrivateKey(
        private_key=private_key,
        chain_code=chain_code,
        depth=depth,
        parent_fingerprint=parent_fingerprint,
        child_number=child_number,
        testnet=self.testnet,
    )
Exemple #10
0
 def child(self, index):
     '''Returns the child HDPrivateKey at a particular index.
     Hardened children return for indices >= 0x8000000.
     '''
     # if index >= 0x80000000
     if index >= 0x80000000:
         # the message data is the private key secret in 33 bytes in
         #  big-endian and the index in 4 bytes big-endian.
         data = int_to_big_endian(self.private_key.secret,
                                  33) + int_to_big_endian(index, 4)
     else:
         # the message data is the public key compressed SEC
         #  and the index in 4 bytes big-endian.
         data = self.private_key.point.sec() + int_to_big_endian(index, 4)
     # get the hmac_sha512 with chain code and data
     h = hmac_sha512(self.chain_code, data)
     # the new secret is the first 32 bytes as a big-endian integer
     #  plus the secret mod N
     secret = (big_endian_to_int(h[:32]) + self.private_key.secret) % N
     # create the PrivateKey object
     private_key = PrivateKey(secret=secret)
     # the chain code is the last 32 bytes
     chain_code = h[32:]
     # depth is whatever the current depth + 1
     depth = self.depth + 1
     # parent_fingerprint is the fingerprint of this node
     parent_fingerprint = self.fingerprint()
     # child number is the index
     child_number = index
     # return a new HDPrivateKey instance
     return HDPrivateKey(
         private_key=private_key,
         chain_code=chain_code,
         depth=depth,
         parent_fingerprint=parent_fingerprint,
         child_number=child_number,
         testnet=self.testnet,
     )
Exemple #11
0
 def der(self):
     # convert the r part to bytes
     rbin = int_to_big_endian(self.r, 32)
     # if rbin has a high bit, add a 00
     if rbin[0] >= 128:
         rbin = b'\x00' + rbin
     while rbin[0] == 0:
         if rbin[1] >= 128:
             break
         else:
             rbin = rbin[1:]
     result = bytes([2, len(rbin)]) + rbin
     sbin = int_to_big_endian(self.s, 32)
     # if sbin has a high bit, add a 00
     if sbin[0] >= 128:
         sbin = b'\x00' + sbin
     while sbin[0] == 0:
         if sbin[1] >= 128:
             break
         else:
             sbin = sbin[1:]
     result += bytes([2, len(sbin)]) + sbin
     return bytes([0x30, len(result)]) + result
Exemple #12
0
 def _serialize(self, version):
     # start with the version
     raw = version
     # add the depth using int_to_byte
     raw += int_to_byte(self.depth)
     # add the parent_fingerprint
     raw += self.parent_fingerprint
     # add the child number in 4 bytes using int_to_big_endian
     raw += int_to_big_endian(self.child_number, 4)
     # add the chain code
     raw += self.chain_code
     # add the SEC pubkey
     raw += self.point.sec()
     return raw
Exemple #13
0
 def wif(self, compressed=True):
     # convert the secret from integer to a 32-bytes in big endian using int_to_big_endian(x, 32)
     secret_bytes = int_to_big_endian(self.secret, 32)
     # prepend b'\xef' on testnet, b'\x80' on mainnet
     if self.testnet:
         prefix = b'\xef'
     else:
         prefix = b'\x80'
     # append b'\x01' if compressed
     if compressed:
         suffix = b'\x01'
     else:
         suffix = b''
     # encode_base58_checksum the whole thing
     return encode_base58_checksum(prefix + secret_bytes + suffix)
Exemple #14
0
def xpub_child(self, index):
    if index >= 0x80000000:
        raise ValueError('child number should always be less than 2^31')
    data = self.point.sec() + int_to_big_endian(index, 4)
    h = hmac_sha512(key=self.chain_code, msg=data)
    point = self.point + big_endian_to_int(h[:32]) * G
    chain_code = h[32:]
    depth = self.depth + 1
    parent_fingerprint = self.fingerprint()
    child_number = index
    return HDPublicKey(
        point=point,
        chain_code=chain_code,
        depth=depth,
        parent_fingerprint=parent_fingerprint,
        child_number=child_number,
        testnet=self.testnet,
    )
Exemple #15
0
 def from_mnemonic(cls, mnemonic, password=b'', path='m', testnet=False):
     '''Returns a HDPrivateKey object from the mnemonic.'''
     # split the mnemonic into words with .split()
     words = mnemonic.split()
     # check that there are 12, 15, 18, 21 or 24 words
     # if not, raise a ValueError
     if len(words) not in (12, 15, 18, 21, 24):
         raise ValueError('you need 12, 15, 18, 21, or 24 words')
     # calculate the number
     number = 0
     # each word is 11 bits
     for word in words:
         # get the number that the word represents using WORD_LOOKUP
         index = WORD_LOOKUP[word]
         # left-shift the number by 11 bits and bitwise-or the index
         number = (number << 11) | index
     # checksum is the last n bits where n = (# of words / 3)
     checksum_bits_length = len(words) // 3
     # grab the checksum bits
     checksum = number & ((1 << checksum_bits_length) - 1)
     # get the actual number by right-shifting by the checksum bits length
     data_num = number >> checksum_bits_length
     # convert the number to big-endian
     data = int_to_big_endian(data_num, checksum_bits_length * 4)
     # the one byte we get is from sha256 of the data, shifted by
     #  8 - the number of bits we need for the checksum
     computed_checksum = sha256(data)[0] >> (8 - checksum_bits_length)
     # check that the checksum is correct or raise ValueError
     if checksum != computed_checksum:
         raise ValueError('words fail checksum: {}'.format(words))
     # normalize in case we got a mnemonic that's just the first 4 letters
     normalized_words = []
     for word in words:
         normalized_words.append(WORD_LIST[WORD_LOOKUP[word]])
     normalized_mnemonic = ' '.join(normalized_words)
     # salt is b'mnemonic' + password
     salt = b'mnemonic' + password
     # the seed is the hmac_sha512_kdf with normalized mnemonic and salt
     seed = hmac_sha512_kdf(normalized_mnemonic, salt)
     # return the HDPrivateKey at the path specified
     return cls.from_seed(seed, testnet=testnet).traverse(path)
Exemple #16
0
def from_mnemonic(cls, mnemonic, password=b'', path='m', testnet=False):
    words = mnemonic.split()
    if len(words) not in (12, 15, 18, 21, 24):
        raise ValueError('you need 12, 15, 18, 21, or 24 words')
    number = 0
    for word in words:
        index = WORD_LOOKUP[word]
        number = (number << 11) | index
    checksum_bits_length = len(words) // 3
    checksum = number & ((1 << checksum_bits_length) - 1)
    data_num = number >> checksum_bits_length
    data = int_to_big_endian(data_num, checksum_bits_length * 4)
    computed_checksum = sha256(data)[0] >> (8 - checksum_bits_length)
    if checksum != computed_checksum:
        raise ValueError('words fail checksum: {}'.format(words))
    normalized_words = []
    for word in words:
        normalized_words.append(WORD_LIST[WORD_LOOKUP[word]])
    normalized_mnemonic = ' '.join(normalized_words)
    salt = b'mnemonic' + password
    seed = hmac_sha512_kdf(normalized_mnemonic, salt)
    return cls.from_seed(seed, testnet=testnet).traverse(path)