diff --git a/share/rpcauth/rpcauth.py b/share/rpcauth/rpcauth.py index 1f0dd0da7..e480f0785 100755 --- a/share/rpcauth/rpcauth.py +++ b/share/rpcauth/rpcauth.py @@ -1,41 +1,34 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers +# Copyright (c) 2015-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -import hashlib import sys import os from random import SystemRandom import base64 import hmac if len(sys.argv) < 2: sys.stderr.write('Please include username as an argument.\n') sys.exit(0) username = sys.argv[1] # This uses os.urandom() underneath cryptogen = SystemRandom() # Create 16 byte hex salt salt_sequence = [cryptogen.randrange(256) for i in range(16)] hexseq = list(map(hex, salt_sequence)) salt = "".join([x[2:] for x in hexseq]) # Create 32 byte b64 password -password = base64.urlsafe_b64encode(os.urandom(32)) +password = base64.urlsafe_b64encode(os.urandom(32)).decode("utf-8") -digestmod = hashlib.sha256 - -if sys.version_info.major >= 3: - password = password.decode('utf-8') - digestmod = 'SHA256' - -m = hmac.new(bytearray(salt, 'utf-8'), bytearray(password, 'utf-8'), digestmod) +m = hmac.new(bytearray(salt, 'utf-8'), bytearray(password, 'utf-8'), "SHA256") result = m.hexdigest() print("String to be appended to bitcoin.conf:") print("rpcauth=" + username + ":" + salt + "$" + result) print("Your password:\n" + password) diff --git a/test/functional/test_framework/key.py b/test/functional/test_framework/key.py index 13eff0158..625269bf4 100755 --- a/test/functional/test_framework/key.py +++ b/test/functional/test_framework/key.py @@ -1,248 +1,242 @@ # Copyright (c) 2011 Sam Rushing """ECC secp256k1 OpenSSL wrapper. WARNING: This module does not mlock() secrets; your private keys may end up on disk in swap! Use with caution! This file is modified from python-bitcoinlib. """ import ctypes import ctypes.util import hashlib -import sys ssl = ctypes.cdll.LoadLibrary(ctypes.util.find_library('ssl') or 'libeay32') ssl.BN_new.restype = ctypes.c_void_p ssl.BN_new.argtypes = [] ssl.BN_free.restype = None ssl.BN_free.argtypes = [ctypes.c_void_p] ssl.BN_bin2bn.restype = ctypes.c_void_p ssl.BN_bin2bn.argtypes = [ctypes.c_char_p, ctypes.c_int, ctypes.c_void_p] ssl.BN_CTX_free.restype = None ssl.BN_CTX_free.argtypes = [ctypes.c_void_p] ssl.BN_CTX_new.restype = ctypes.c_void_p ssl.BN_CTX_new.argtypes = [] ssl.ECDH_compute_key.restype = ctypes.c_int ssl.ECDH_compute_key.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p] ssl.ECDSA_sign.restype = ctypes.c_int ssl.ECDSA_sign.argtypes = [ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] ssl.ECDSA_verify.restype = ctypes.c_int ssl.ECDSA_verify.argtypes = [ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p] ssl.EC_KEY_free.restype = None ssl.EC_KEY_free.argtypes = [ctypes.c_void_p] ssl.EC_KEY_new_by_curve_name.restype = ctypes.c_void_p ssl.EC_KEY_new_by_curve_name.argtypes = [ctypes.c_int] ssl.EC_KEY_get0_group.restype = ctypes.c_void_p ssl.EC_KEY_get0_group.argtypes = [ctypes.c_void_p] ssl.EC_KEY_get0_public_key.restype = ctypes.c_void_p ssl.EC_KEY_get0_public_key.argtypes = [ctypes.c_void_p] ssl.EC_KEY_set_private_key.restype = ctypes.c_int ssl.EC_KEY_set_private_key.argtypes = [ctypes.c_void_p, ctypes.c_void_p] ssl.EC_KEY_set_conv_form.restype = None ssl.EC_KEY_set_conv_form.argtypes = [ctypes.c_void_p, ctypes.c_int] ssl.EC_KEY_set_public_key.restype = ctypes.c_int ssl.EC_KEY_set_public_key.argtypes = [ctypes.c_void_p, ctypes.c_void_p] ssl.i2o_ECPublicKey.restype = ctypes.c_void_p ssl.i2o_ECPublicKey.argtypes = [ctypes.c_void_p, ctypes.c_void_p] ssl.EC_POINT_new.restype = ctypes.c_void_p ssl.EC_POINT_new.argtypes = [ctypes.c_void_p] ssl.EC_POINT_free.restype = None ssl.EC_POINT_free.argtypes = [ctypes.c_void_p] ssl.EC_POINT_mul.restype = ctypes.c_int ssl.EC_POINT_mul.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] # this specifies the curve used with ECDSA. NID_secp256k1 = 714 # from openssl/obj_mac.h SECP256K1_ORDER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 SECP256K1_ORDER_HALF = SECP256K1_ORDER // 2 # Thx to Sam Devlin for the ctypes magic 64-bit fix. def _check_result(val, func, args): if val == 0: raise ValueError else: return ctypes.c_void_p(val) ssl.EC_KEY_new_by_curve_name.restype = ctypes.c_void_p ssl.EC_KEY_new_by_curve_name.errcheck = _check_result class CECKey(): """Wrapper around OpenSSL's EC_KEY""" POINT_CONVERSION_COMPRESSED = 2 POINT_CONVERSION_UNCOMPRESSED = 4 def __init__(self): self.k = ssl.EC_KEY_new_by_curve_name(NID_secp256k1) def __del__(self): if ssl: ssl.EC_KEY_free(self.k) self.k = None def set_secretbytes(self, secret): priv_key = ssl.BN_bin2bn(secret, 32, ssl.BN_new()) group = ssl.EC_KEY_get0_group(self.k) pub_key = ssl.EC_POINT_new(group) ctx = ssl.BN_CTX_new() if not ssl.EC_POINT_mul(group, pub_key, priv_key, None, None, ctx): raise ValueError( "Could not derive public key from the supplied secret.") ssl.EC_POINT_mul(group, pub_key, priv_key, None, None, ctx) ssl.EC_KEY_set_private_key(self.k, priv_key) ssl.EC_KEY_set_public_key(self.k, pub_key) ssl.BN_free(priv_key) ssl.EC_POINT_free(pub_key) ssl.BN_CTX_free(ctx) return self.k def set_privkey(self, key): self.mb = ctypes.create_string_buffer(key) return ssl.d2i_ECPrivateKey(ctypes.byref(self.k), ctypes.byref(ctypes.pointer(self.mb)), len(key)) def set_pubkey(self, key): self.mb = ctypes.create_string_buffer(key) return ssl.o2i_ECPublicKey(ctypes.byref(self.k), ctypes.byref(ctypes.pointer(self.mb)), len(key)) def get_privkey(self): size = ssl.i2d_ECPrivateKey(self.k, 0) mb_pri = ctypes.create_string_buffer(size) ssl.i2d_ECPrivateKey(self.k, ctypes.byref(ctypes.pointer(mb_pri))) return mb_pri.raw def get_pubkey(self): size = ssl.i2o_ECPublicKey(self.k, 0) mb = ctypes.create_string_buffer(size) ssl.i2o_ECPublicKey(self.k, ctypes.byref(ctypes.pointer(mb))) return mb.raw def get_raw_ecdh_key(self, other_pubkey): ecdh_keybuffer = ctypes.create_string_buffer(32) r = ssl.ECDH_compute_key(ctypes.pointer(ecdh_keybuffer), 32, ssl.EC_KEY_get0_public_key(other_pubkey.k), self.k, 0) if r != 32: raise Exception('CKey.get_ecdh_key(): ECDH_compute_key() failed') return ecdh_keybuffer.raw def get_ecdh_key(self, other_pubkey, kdf=lambda k: hashlib.sha256(k).digest()): # FIXME: be warned it's not clear what the kdf should be as a default r = self.get_raw_ecdh_key(other_pubkey) return kdf(r) def sign(self, hash, low_s=True): # FIXME: need unit tests for below cases if not isinstance(hash, bytes): raise TypeError( 'Hash must be bytes instance; got {!r}'.format(hash.__class__)) if len(hash) != 32: raise ValueError('Hash must be exactly 32 bytes long') sig_size0 = ctypes.c_uint32() sig_size0.value = ssl.ECDSA_size(self.k) mb_sig = ctypes.create_string_buffer(sig_size0.value) result = ssl.ECDSA_sign(0, hash, len( hash), mb_sig, ctypes.byref(sig_size0), self.k) assert 1 == result assert mb_sig.raw[0] == 0x30 assert mb_sig.raw[1] == sig_size0.value - 2 total_size = mb_sig.raw[1] assert mb_sig.raw[2] == 2 r_size = mb_sig.raw[3] assert mb_sig.raw[4 + r_size] == 2 s_size = mb_sig.raw[5 + r_size] s_value = int.from_bytes( mb_sig.raw[6 + r_size:6 + r_size + s_size], byteorder='big') if (not low_s) or s_value <= SECP256K1_ORDER_HALF: return mb_sig.raw[:sig_size0.value] else: low_s_value = SECP256K1_ORDER - s_value low_s_bytes = (low_s_value).to_bytes(33, byteorder='big') while len(low_s_bytes) > 1 and low_s_bytes[0] == 0 and low_s_bytes[1] < 0x80: low_s_bytes = low_s_bytes[1:] new_s_size = len(low_s_bytes) new_total_size_byte = ( total_size + new_s_size - s_size).to_bytes(1, byteorder='big') new_s_size_byte = (new_s_size).to_bytes(1, byteorder='big') return b'\x30' + new_total_size_byte + mb_sig.raw[2:5 + r_size] + new_s_size_byte + low_s_bytes def verify(self, hash, sig): """Verify a DER signature""" return ssl.ECDSA_verify(0, hash, len(hash), sig, len(sig), self.k) == 1 def set_compressed(self, compressed): if compressed: form = self.POINT_CONVERSION_COMPRESSED else: form = self.POINT_CONVERSION_UNCOMPRESSED ssl.EC_KEY_set_conv_form(self.k, form) class CPubKey(bytes): """An encapsulated public key Attributes: is_valid - Corresponds to CPubKey.IsValid() is_fullyvalid - Corresponds to CPubKey.IsFullyValid() is_compressed - Corresponds to CPubKey.IsCompressed() """ def __new__(cls, buf, _cec_key=None): self = super(CPubKey, cls).__new__(cls, buf) if _cec_key is None: _cec_key = CECKey() self._cec_key = _cec_key self.is_fullyvalid = _cec_key.set_pubkey(self) != 0 return self @property def is_valid(self): return len(self) > 0 @property def is_compressed(self): return len(self) == 33 def verify(self, hash, sig): return self._cec_key.verify(hash, sig) def __str__(self): return repr(self) def __repr__(self): - # Always have represent as b'' so test cases don't have to - # change for py2/3 - if sys.version > '3': - return '{}({})'.format(self.__class__.__name__, super(CPubKey, self).__repr__()) - else: - return '{}(b{})'.format(self.__class__.__name__, super(CPubKey, self).__repr__()) + return '{}({})'.format(self.__class__.__name__, super(CPubKey, self).__repr__()) diff --git a/test/functional/test_framework/script.py b/test/functional/test_framework/script.py index d441ea162..46afce05c 100644 --- a/test/functional/test_framework/script.py +++ b/test/functional/test_framework/script.py @@ -1,733 +1,725 @@ #!/usr/bin/env python3 # Copyright (c) 2015-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Functionality to build scripts, as well as SignatureHash(). This file is modified from python-bitcoinlib. """ from .bignum import bn2vch from binascii import hexlify import hashlib import struct -import sys from .messages import ( CTransaction, CTxOut, hash256, ser_string, ser_uint256, sha256, uint256_from_str, ) -bchr = chr -bord = ord -if sys.version > '3': - long = int - - def bchr(x): return bytes([x]) - - def bord(x): return x - MAX_SCRIPT_ELEMENT_SIZE = 520 OPCODE_NAMES = {} def hash160(s): return hashlib.new('ripemd160', sha256(s)).digest() _opcode_instances = [] class CScriptOp(int): """A single script opcode""" __slots__ = () @staticmethod def encode_op_pushdata(d): """Encode a PUSHDATA op, returning bytes""" if len(d) < 0x4c: - return b'' + bchr(len(d)) + d # OP_PUSHDATA + # OP_PUSHDATA + return b'' + bytes([len(d)]) + d elif len(d) <= 0xff: - return b'\x4c' + bchr(len(d)) + d # OP_PUSHDATA1 + # OP_PUSHDATA1 + return b'\x4c' + bytes([len(d)]) + d elif len(d) <= 0xffff: return b'\x4d' + struct.pack(b'>= 8 if r[-1] & 0x80: r.append(0x80 if neg else 0) elif neg: r[-1] |= 0x80 - return bytes(bchr(len(r)) + r) + return bytes(bytes([len(r)]) + r) class CScript(bytes): """Serialized script A bytes subclass, so you can use this directly whenever bytes are accepted. Note that this means that indexing does *not* work - you'll get an index by byte rather than opcode. This format was chosen for efficiency so that the general case would not require creating a lot of little CScriptOP objects. iter(script) however does iterate by opcode. """ __slots__ = () @classmethod def __coerce_instance(cls, other): # Coerce other into bytes if isinstance(other, CScriptOp): - other = bchr(other) + other = bytes([other]) elif isinstance(other, CScriptNum): if (other.value == 0): - other = bchr(CScriptOp(OP_0)) + other = bytes([CScriptOp(OP_0)]) else: other = CScriptNum.encode(other) elif isinstance(other, int): if 0 <= other <= 16: - other = bytes(bchr(CScriptOp.encode_op_n(other))) + other = bytes([CScriptOp.encode_op_n(other)]) elif other == -1: - other = bytes(bchr(OP_1NEGATE)) + other = bytes([OP_1NEGATE]) else: other = CScriptOp.encode_op_pushdata(bn2vch(other)) elif isinstance(other, (bytes, bytearray)): other = CScriptOp.encode_op_pushdata(other) return other def __add__(self, other): # Do the coercion outside of the try block so that errors in it are # noticed. other = self.__coerce_instance(other) try: # bytes.__add__ always returns bytes instances unfortunately return CScript(super(CScript, self).__add__(other)) except TypeError: raise TypeError( 'Can not add a {!r} instance to a CScript'.format(other.__class__)) def join(self, iterable): # join makes no sense for a CScript() raise NotImplementedError def __new__(cls, value=b''): if isinstance(value, bytes) or isinstance(value, bytearray): return super(CScript, cls).__new__(cls, value) else: def coerce_iterable(iterable): for instance in iterable: yield cls.__coerce_instance(instance) # Annoyingly on both python2 and python3 bytes.join() always # returns a bytes instance even when subclassed. return super(CScript, cls).__new__(cls, b''.join(coerce_iterable(value))) def raw_iter(self): """Raw iteration Yields tuples of (opcode, data, sop_idx) so that the different possible PUSHDATA encodings can be accurately distinguished, as well as determining the exact opcode byte indexes. (sop_idx) """ i = 0 while i < len(self): sop_idx = i - opcode = bord(self[i]) + opcode = self[i] i += 1 if opcode > OP_PUSHDATA4: yield (opcode, None, sop_idx) else: datasize = None pushdata_type = None if opcode < OP_PUSHDATA1: pushdata_type = 'PUSHDATA({})'.format(opcode) datasize = opcode elif opcode == OP_PUSHDATA1: pushdata_type = 'PUSHDATA1' if i >= len(self): raise CScriptInvalidError( 'PUSHDATA1: missing data length') - datasize = bord(self[i]) + datasize = self[i] i += 1 elif opcode == OP_PUSHDATA2: pushdata_type = 'PUSHDATA2' if i + 1 >= len(self): raise CScriptInvalidError( 'PUSHDATA2: missing data length') - datasize = bord(self[i]) + (bord(self[i + 1]) << 8) + datasize = self[i] + (self[i + 1] << 8) i += 2 elif opcode == OP_PUSHDATA4: pushdata_type = 'PUSHDATA4' if i + 3 >= len(self): raise CScriptInvalidError( 'PUSHDATA4: missing data length') - datasize = bord(self[i]) + (bord(self[i + 1]) << 8) + \ - (bord(self[i + 2]) << 16) + (bord(self[i + 3]) << 24) + datasize = self[i] + (self[i + 1] << 8) + \ + (self[i + 2] << 16) + (self[i + 3] << 24) i += 4 else: assert False # shouldn't happen data = bytes(self[i:i + datasize]) # Check for truncation if len(data) < datasize: raise CScriptTruncatedPushDataError( '{}: truncated data'.format(pushdata_type, data)) i += datasize yield (opcode, data, sop_idx) def __iter__(self): """'Cooked' iteration Returns either a CScriptOP instance, an integer, or bytes, as appropriate. See raw_iter() if you need to distinguish the different possible PUSHDATA encodings. """ for (opcode, data, sop_idx) in self.raw_iter(): if data is not None: yield data else: opcode = CScriptOp(opcode) if opcode.is_small_int(): yield opcode.decode_op_n() else: yield CScriptOp(opcode) def __repr__(self): def _repr(o): if isinstance(o, bytes): return "x('{}')".format(hexlify(o).decode('ascii')) else: return repr(o) ops = [] i = iter(self) while True: op = None try: op = _repr(next(i)) except CScriptTruncatedPushDataError as err: op = '{}...'.format(_repr(err.data), err) break except CScriptInvalidError as err: op = ''.format(err) break except StopIteration: break finally: if op is not None: ops.append(op) return "CScript([{}])".format(', '.join(ops)) def GetSigOpCount(self, fAccurate): """Get the SigOp count. fAccurate - Accurately count CHECKMULTISIG, see BIP16 for details. Note that this is consensus-critical. """ n = 0 lastOpcode = OP_INVALIDOPCODE for (opcode, data, sop_idx) in self.raw_iter(): if opcode in (OP_CHECKSIG, OP_CHECKSIGVERIFY): n += 1 elif opcode in (OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY): if fAccurate and (OP_1 <= lastOpcode <= OP_16): n += opcode.decode_op_n() else: n += 20 lastOpcode = opcode return n SIGHASH_ALL = 1 SIGHASH_NONE = 2 SIGHASH_SINGLE = 3 SIGHASH_FORKID = 0x40 SIGHASH_ANYONECANPAY = 0x80 def FindAndDelete(script, sig): """Consensus critical, see FindAndDelete() in Satoshi codebase""" r = b'' last_sop_idx = sop_idx = 0 skip = True for (opcode, data, sop_idx) in script.raw_iter(): if not skip: r += script[last_sop_idx:sop_idx] last_sop_idx = sop_idx if script[sop_idx:sop_idx + len(sig)] == sig: skip = True else: skip = False if not skip: r += script[last_sop_idx:] return CScript(r) def SignatureHash(script, txTo, inIdx, hashtype): """Consensus-correct SignatureHash Returns (hash, err) to precisely match the consensus-critical behavior of the SIGHASH_SINGLE bug. (inIdx is *not* checked for validity) """ HASH_ONE = b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' if inIdx >= len(txTo.vin): return (HASH_ONE, "inIdx {} out of range ({})".format(inIdx, len(txTo.vin))) txtmp = CTransaction(txTo) for txin in txtmp.vin: txin.scriptSig = b'' txtmp.vin[inIdx].scriptSig = FindAndDelete( script, CScript([OP_CODESEPARATOR])) if (hashtype & 0x1f) == SIGHASH_NONE: txtmp.vout = [] for i in range(len(txtmp.vin)): if i != inIdx: txtmp.vin[i].nSequence = 0 elif (hashtype & 0x1f) == SIGHASH_SINGLE: outIdx = inIdx if outIdx >= len(txtmp.vout): return (HASH_ONE, "outIdx {} out of range ({})".format(outIdx, len(txtmp.vout))) tmp = txtmp.vout[outIdx] txtmp.vout = [] for i in range(outIdx): txtmp.vout.append(CTxOut(-1)) txtmp.vout.append(tmp) for i in range(len(txtmp.vin)): if i != inIdx: txtmp.vin[i].nSequence = 0 if hashtype & SIGHASH_ANYONECANPAY: tmp = txtmp.vin[inIdx] txtmp.vin = [] txtmp.vin.append(tmp) s = txtmp.serialize() s += struct.pack(b"