def __init__(self, b: bytes): if b is not None: assert_bytes(b) point = _ser_to_python_ecdsa_point(b) self._pubkey = ecdsa.ecdsa.Public_key(generator_secp256k1, point) else: self._pubkey = _PubkeyForPointAtInfinity()
def _read_expected(self, expected, actionstr=''): """Helper function that reads from the serial and compares the result with `expected` raising `LegsException` if aren't equal. Now the messages returns only a messages however in the future this may change so just prevent future errors. Args: expected(iterables of bytes): expected result actionstr(str): name of the action we are performing Raises: LegsException: if the what we have read isn't equal to the expected """ assert_bytes(expected) r = b'' for _ in range(len(expected)): r = r + self.serial.read() if r != expected: raise LegsException( 'Unable to {actionstr} due to error: {errcode}'.format( actionstr=actionstr, errcode=str(r)))
def base_encode(v: bytes, base: int) -> str: """ encode v, which is a string of bytes, to base58.""" assert_bytes(v) if base not in (58, 43): raise ValueError('not supported base: {}'.format(base)) chars = __b58chars if base == 43: chars = __b43chars long_value = 0 for (i, c) in enumerate(v[::-1]): long_value += (256**i) * c result = bytearray() while long_value >= base: div, mod = divmod(long_value, base) result.append(chars[mod]) long_value = div result.append(chars[long_value]) # Bitcoin does a little leading-zero-compression: # leading 0-bytes in the input become leading-1s nPad = 0 for c in v: if c == 0x00: nPad += 1 else: break result.extend([chars[0]] * nPad) result.reverse() return result.decode('ascii')
def verify_message(self, sig, message): assert_bytes(message) h = Hash(msg_magic(message)) public_key, compressed = pubkey_from_signature(sig, h) # check public key if point_to_ser(public_key.pubkey.point, compressed) != point_to_ser(self.pubkey.point, compressed): raise Exception("Bad signature") # check message public_key.verify_digest(sig[1:], h, sigdecode = ecdsa.util.sigdecode_string)
def verify_message_for_address(self, sig65: bytes, message: bytes) -> None: assert_bytes(message) h = Hash(msg_magic(message)) public_key, compressed = self.from_signature65(sig65, h) # check public key if public_key != self: raise Exception("Bad signature") # check message self.verify_message_hash(sig65[1:], h)
def verify_message_hash(self, sig_string: bytes, msg_hash: bytes) -> None: assert_bytes(sig_string) if len(sig_string) != 64: raise Exception('Wrong encoding') ecdsa_point = self._pubkey.point verifying_key = _MyVerifyingKey.from_public_point(ecdsa_point, curve=SECP256k1) verifying_key.verify_digest(sig_string, msg_hash, sigdecode=ecdsa.util.sigdecode_string)
def aes_encrypt_with_iv(key, iv, data): assert_bytes(key, iv, data) data = append_PKCS7_padding(data) if AES: e = AES.new(key, AES.MODE_CBC, iv).encrypt(data) else: aes_cbc = pyaes.AESModeOfOperationCBC(key, iv=iv) aes = pyaes.Encrypter(aes_cbc, padding=pyaes.PADDING_NONE) e = aes.feed(data) + aes.feed() # empty aes.feed() flushes buffer return e
def strip_PKCS7_padding(data): assert_bytes(data) if len(data) % 16 != 0 or len(data) == 0: raise InvalidPadding("invalid length") padlen = data[-1] if padlen > 16: raise InvalidPadding("invalid padding byte (large)") for i in data[-padlen:]: if i != padlen: raise InvalidPadding("invalid padding byte (inconsistent)") return data[0:-padlen]
def strip_PKCS7_padding(data: bytes) -> bytes: assert_bytes(data) if len(data) % 16 != 0 or len(data) == 0: raise InvalidPadding("invalid length") padlen = data[-1] if not (0 < padlen <= 16): raise InvalidPadding("invalid padding byte (out of range)") for i in data[-padlen:]: if i != padlen: raise InvalidPadding("invalid padding byte (inconsistent)") return data[0:-padlen]
def aes_decrypt_with_iv(key, iv, data): assert_bytes(key, iv, data) if AES: cipher = AES.new(key, AES.MODE_CBC, iv) data = cipher.decrypt(data) else: aes_cbc = pyaes.AESModeOfOperationCBC(key, iv=iv) aes = pyaes.Decrypter(aes_cbc, padding=pyaes.PADDING_NONE) data = aes.feed(data) + aes.feed() # empty aes.feed() flushes buffer try: return strip_PKCS7_padding(data) except InvalidPadding: raise InvalidPassword()
def from_sig_string(cls, sig_string: bytes, recid: int, msg_hash: bytes): assert_bytes(sig_string) if len(sig_string) != 64: raise Exception('Wrong encoding') if recid < 0 or recid > 3: raise ValueError( 'recid is {}, but should be 0 <= recid <= 3'.format(recid)) ecdsa_verifying_key = _MyVerifyingKey.from_signature(sig_string, recid, msg_hash, curve=SECP256k1) ecdsa_point = ecdsa_verifying_key.pubkey.point return ECPubkey.from_point(ecdsa_point)
def __init__(self, privkey_bytes: bytes): assert_bytes(privkey_bytes) if len(privkey_bytes) != 32: raise Exception( 'unexpected size for secret. should be 32 bytes, not {}'. format(len(privkey_bytes))) secret = string_to_number(privkey_bytes) if not is_secret_within_curve_range(secret): raise Exception('Invalid secret scalar (not within curve order)') self.secret_scalar = secret point = generator_secp256k1 * secret super().__init__(point_to_ser(point)) self._privkey = ecdsa.ecdsa.Private_key(self._pubkey, secret)
def encrypt_message(self, message, pubkey): assert_bytes(message) pk = ser_to_point(pubkey) if not ecdsa.ecdsa.point_is_valid(generator_secp256k1, pk.x(), pk.y()): raise Exception('invalid pubkey') ephemeral_exponent = number_to_string(ecdsa.util.randrange(pow(2,256)), generator_secp256k1.order()) ephemeral = EC_KEY(ephemeral_exponent) ecdh_key = point_to_ser(pk * ephemeral.privkey.secret_multiplier) key = hashlib.sha512(ecdh_key).digest() iv, key_e, key_m = key[0:16], key[16:32], key[32:] ciphertext = aes_encrypt_with_iv(key_e, iv, message) ephemeral_pubkey = bfh(ephemeral.get_public_key(compressed=True)) encrypted = b'BIE1' + ephemeral_pubkey + ciphertext mac = hmac.new(key_m, encrypted, hashlib.sha256).digest() return base64.b64encode(encrypted + mac)
def verify_message(address, sig, message): assert_bytes(sig, message) try: h = Hash(msg_magic(message)) public_key, compressed = pubkey_from_signature(sig, h) # check public key using the address pubkey = point_to_ser(public_key.pubkey.point, compressed) for txin_type in ['p2pkh','p2wpkh','p2wpkh-p2sh']: addr = pubkey_to_address(txin_type, bh2u(pubkey)) if address == addr: break else: raise Exception("Bad signature") # check message public_key.verify_digest(sig[1:], h, sigdecode = ecdsa.util.sigdecode_string) return True except Exception as e: print_error("Verification error: {0}".format(e)) return False
def encrypt_message(self, message: bytes, magic: bytes = b'BIE1'): """ ECIES encryption/decryption methods; AES-128-CBC with PKCS7 is used as the cipher; hmac-sha256 is used as the mac """ assert_bytes(message) randint = ecdsa.util.randrange(CURVE_ORDER) ephemeral_exponent = number_to_string(randint, CURVE_ORDER) ephemeral = ECPrivkey(ephemeral_exponent) ecdh_key = (self * ephemeral.secret_scalar).get_public_key_bytes( compressed=True) key = hashlib.sha512(ecdh_key).digest() iv, key_e, key_m = key[0:16], key[16:32], key[32:] ciphertext = aes_encrypt_with_iv(key_e, iv, message) ephemeral_pubkey = ephemeral.get_public_key_bytes(compressed=True) encrypted = magic + ephemeral_pubkey + ciphertext mac = hmac.new(key_m, encrypted, hashlib.sha256).digest() return base64.b64encode(encrypted + mac)
def verify_message_with_address(address: str, sig65: bytes, message: bytes): from .bitcoin import pubkey_to_address assert_bytes(sig65, message) try: h = Hash(msg_magic(message)) public_key, compressed = ECPubkey.from_signature65(sig65, h) # check public key using the address pubkey_hex = public_key.get_public_key_hex(compressed) for txin_type in ['p2pkh', 'p2wpkh', 'p2wpkh-p2sh']: addr = pubkey_to_address(txin_type, pubkey_hex) if address == addr: break else: raise Exception("Bad signature") # check message public_key.verify_message_hash(sig65[1:], h) return True except Exception as e: print_error("Verification error: {0}".format(e)) return False
def EncodeAES_bytes(secret: bytes, msg: bytes) -> bytes: assert_bytes(msg) iv = bytes(os.urandom(16)) ct = aes_encrypt_with_iv(secret, iv, msg) return iv + ct
def _send_n_read(self, msg, actionstr, async=False, ack=None): """Helper function that sends the given `msg` and reads the `ack` or if it is None it will use `create_ack` on `msg` to get the expected result. Args: msg(byte): message to send actionstr(str): action description async(bool): if True the `msg` will be lowered, otherwise Nothing will be performed ack(byte): if None the expected byte will be created calling `create_ack` on `msg` otherwise it will be used as the expected value. """ assert_bytes(msg) if async: msg = msg.lower() self.serial.write(msg) ack = ack or create_ack(msg) self._read_expected(ack, actionstr) def forward(self, async=False): """Utility function that makes the rover move forward. Args: async(bool): if True it will return immediatly, otherwise it will wait until the rover stops. """ self._send_n_read(ArduinoMessages.Forward.value, 'move forward', async=async)
def _send_n_read(self, msg, actionstr, async=False, ack=None): """Helper function that sends the given `msg` and reads the `ack` or if it is None it will use `create_ack` on `msg` to get the expected result. Args: msg(byte): message to send actionstr(str): action description async(bool): if True the `msg` will be lowered, otherwise Nothing will be performed ack(byte): if None the expected byte will be created calling `create_ack` on `msg` otherwise it will be used as the expected value. """ assert_bytes(msg) if async: msg = msg.lower() self.serial.write(msg) ack = ack or create_ack(msg) self._read_expected(ack, actionstr) def forward(self, async=False): """Utility function that makes the rover move forward. Args: async(bool): if True it will return immediatly, otherwise it will wait until the rover stops. """ self._send_n_read(ArduinoMessages.Forward.value, 'move forward',
def __init__(self, b: bytes): assert_bytes(b) point = _ser_to_python_ecdsa_point(b) self._pubkey = ecdsa.ecdsa.Public_key(generator_secp256k1, point)
def EncodeAES(secret, s): assert_bytes(s) iv = bytes(os.urandom(16)) ct = aes_encrypt_with_iv(secret, iv, s) e = iv + ct return base64.b64encode(e)
def append_PKCS7_padding(data): assert_bytes(data) padlen = 16 - (len(data) % 16) return data + bytes([padlen]) * padlen
def DecodeAES_bytes(secret: bytes, ciphertext: bytes) -> bytes: assert_bytes(ciphertext) iv, e = ciphertext[:16], ciphertext[16:] s = aes_decrypt_with_iv(secret, iv, e) return s