async def write(self, msg: protobuf.MessageType, field_cache: protobuf.FieldCache = None) -> None: if __debug__: log.debug(__name__, "%s:%x write: %s", self.iface.iface_num(), self.sid, msg) if field_cache is None: field_cache = self._field_cache # write the message msg_size = protobuf.count_message(msg, field_cache) # prepare buffer if msg_size <= len(self.buffer_writer.buffer): # reuse preallocated buffer_writer = self.buffer_writer else: # message is too big, we need to allocate a new buffer buffer_writer = utils.BufferWriter(bytearray(msg_size)) buffer_writer.seek(0) protobuf.dump_message(buffer_writer, msg, field_cache) await codec_v1.write_message( self.iface, msg.MESSAGE_WIRE_TYPE, memoryview(buffer_writer.buffer)[:msg_size], ) # make sure we don't keep around fields of all protobuf types ever self._field_cache.clear()
def gen_hmac_vini(key, src_entr: MoneroTransactionSourceEntry, vini_bin: bytes, idx: int) -> bytes: """ Computes hmac (TxSourceEntry[i] || tx.vin[i]) In src_entr.outputs only src_entr.outputs[src_entr.real_output] is HMACed as it is used across the protocol. Consistency of other values across the protocol is not required as they are used only once and hard to check. I.e., indices in step 2 are uncheckable, decoy keys in step 9 are just random keys. """ import protobuf from apps.monero.xmr.keccak_hasher import get_keccak_writer kwriter = get_keccak_writer() real_outputs = src_entr.outputs real_additional = src_entr.real_out_additional_tx_keys src_entr.outputs = [src_entr.outputs[src_entr.real_output]] if real_additional and len(real_additional) > 1: src_entr.real_out_additional_tx_keys = [ src_entr.real_out_additional_tx_keys[ src_entr.real_output_in_tx_index] ] protobuf.dump_message(kwriter, src_entr) src_entr.outputs = real_outputs src_entr.real_out_additional_tx_keys = real_additional kwriter.write(vini_bin) hmac_key_vini = hmac_key_txin(key, idx) hmac_vini = crypto.compute_hmac(hmac_key_vini, kwriter.get_digest()) return hmac_vini
def set(auth_message: protobuf.MessageType) -> None: buffer = bytearray(protobuf.count_message(auth_message)) writer = utils.BufferWriter(buffer) protobuf.dump_message(writer, auth_message) storage.cache.set( storage.cache.APP_COMMON_AUTHORIZATION_TYPE, auth_message.MESSAGE_WIRE_TYPE.to_bytes(2, "big"), ) storage.cache.set(storage.cache.APP_COMMON_AUTHORIZATION_DATA, buffer)
def gen_hmac_tsxdest(key, dst_entr: MoneroTransactionDestinationEntry, idx: int) -> bytes: """ Generates HMAC for TxDestinationEntry[i] """ import protobuf from apps.monero.xmr.keccak_hasher import get_keccak_writer kwriter = get_keccak_writer() protobuf.dump_message(kwriter, dst_entr) hmac_key = hmac_key_txdst(key, idx) hmac_tsxdest = crypto.compute_hmac(hmac_key, kwriter.get_digest()) return hmac_tsxdest
def _compute_sec_keys(state: State, tsx_data: MoneroTransactionData): """ Generate master key H( H(TsxData || tx_priv) || rand ) """ import protobuf from apps.monero.xmr.keccak_hasher import get_keccak_writer writer = get_keccak_writer() protobuf.dump_message(writer, tsx_data) writer.write(crypto.encodeint(state.tx_priv)) master_key = crypto.keccak_2hash(writer.get_digest() + crypto.encodeint(crypto.random_scalar())) state.key_hmac = crypto.keccak_2hash(b"hmac" + master_key) state.key_enc = crypto.keccak_2hash(b"enc" + master_key)
def gen_hmac_vouti(key, dst_entr: MoneroTransactionDestinationEntry, tx_out_bin: bytes, idx: int) -> bytes: """ Generates HMAC for (TxDestinationEntry[i] || tx.vout[i]) """ import protobuf from apps.monero.xmr.keccak_hasher import get_keccak_writer kwriter = get_keccak_writer() protobuf.dump_message(kwriter, dst_entr) kwriter.write(tx_out_bin) hmac_key_vouti = hmac_key_txout(key, idx) hmac_vouti = crypto.compute_hmac(hmac_key_vouti, kwriter.get_digest()) return hmac_vouti
def test_validate_enum(self): # ok message: msg = Message(-42, 5) writer = ByteArrayWriter() await_result(protobuf.dump_message(writer, msg)) reader = ByteReader(bytes(writer.buf)) nmsg = await_result(protobuf.load_message(reader, Message)) self.assertEqual(msg.sint_field, nmsg.sint_field) self.assertEqual(msg.enum_field, nmsg.enum_field) # bad enum value: msg = Message(-42, 42) writer = ByteArrayWriter() await_result(protobuf.dump_message(writer, msg)) reader = ByteReader(bytes(writer.buf)) with self.assertRaises(TypeError): await_result(protobuf.load_message(reader, Message))
def test_validate_enum(self): # ok message: msg = Message(-42, 5) length = protobuf.count_message(msg) buffer_writer = BufferWriter(bytearray(length)) protobuf.dump_message(buffer_writer, msg) buffer_reader = BufferReader(buffer_writer.buffer) nmsg = protobuf.load_message(buffer_reader, Message) self.assertEqual(msg.sint_field, nmsg.sint_field) self.assertEqual(msg.enum_field, nmsg.enum_field) # bad enum value: buffer_writer.seek(0) msg = Message(-42, 42) # XXX this assumes the message will have equal size protobuf.dump_message(buffer_writer, msg) buffer_reader.seek(0) with self.assertRaises(TypeError): protobuf.load_message(buffer_reader, Message)
def dump_message(msg: protobuf.MessageType) -> bytearray: length = protobuf.count_message(msg) buffer = bytearray(length) protobuf.dump_message(BufferWriter(buffer), msg) return buffer