def sign(self, msg): """ signature: sign(privkey, sha3(packet-type || packet-data)) signature: sign(privkey, sha3(pubkey || packet-type || packet-data)) // implementation w/MCD """ msg = crypto.sha3(msg) return crypto.sign(msg, self.privkey)
def pack(self, cmd_id, payload): """ UDP packets are structured as follows: hash || signature || packet-type || packet-data packet-type: single byte < 2**7 // valid values are [1,4] packet-data: RLP encoded list. Packet properties are serialized in the order in which they're defined. See packet-data below. Offset | 0 | MDC | Ensures integrity of packet, 65 | signature | Ensures authenticity of sender, `SIGN(sender-privkey, MDC)` 97 | type | Single byte in range [1, 4] that determines the structure of Data 98 | data | RLP encoded, see section Packet Data The packets are signed and authenticated. The sender's Node ID is determined by recovering the public key from the signature. sender-pubkey = ECRECOVER(Signature) The integrity of the packet can then be verified by computing the expected MDC of the packet as: MDC = SHA3(sender-pubkey || type || data) As an optimization, implementations may look up the public key by the UDP sending address and compute MDC before recovering the sender ID. If the MDC values do not match, the packet can be dropped. """ assert cmd_id in self.cmd_id_map.values() assert isinstance(payload, list) cmd_id = self.encoders['cmd_id'](cmd_id) expiration = self.encoders['expiration'](int(time.time() + self.expiration)) encoded_data = rlp.encode(payload + [expiration]) # print rlp.decode(encoded_data) signed_data = crypto.sha3(cmd_id + encoded_data) signature = crypto.sign(signed_data, self.privkey) assert crypto.verify(self.pubkey, signature, signed_data) # assert self.pubkey == crypto.ecdsa_recover(signed_data, signature) # assert crypto.verify(self.pubkey, signature, signed_data) assert len(signature) == 65 mdc = crypto.sha3(signature + cmd_id + encoded_data) assert len(mdc) == 32 # print dict(mdc=mdc.encode('hex'), signature=signature.encode('hex'), # data=str(cmd_id + encoded_data).encode('hex')) return mdc + signature + cmd_id + encoded_data
def pack(self, cmd_id, payload): """ UDP packets are structured as follows: hash || signature || packet-type || packet-data packet-type: single byte < 2**7 // valid values are [1,4] packet-data: RLP encoded list. Packet properties are serialized in the order in which they're defined. See packet-data below. Offset | 0 | MDC | Ensures integrity of packet, 65 | signature | Ensures authenticity of sender, `SIGN(sender-privkey, MDC)` 97 | type | Single byte in range [1, 4] that determines the structure of Data 98 | data | RLP encoded, see section Packet Data The packets are signed and authenticated. The sender's Node ID is determined by recovering the public key from the signature. sender-pubkey = ECRECOVER(Signature) The integrity of the packet can then be verified by computing the expected MDC of the packet as: MDC = SHA3(sender-pubkey || type || data) As an optimization, implementations may look up the public key by the UDP sending address and compute MDC before recovering the sender ID. If the MDC values do not match, the packet can be dropped. """ assert cmd_id in self.cmd_id_map.values() assert isinstance(payload, list) cmd_id = self.encoders['cmd_id'](cmd_id) expiration = self.encoders['expiration'](int(time.time() + self.expiration)) encoded_data = rlp.encode(payload + [expiration]) # print rlp.decode(encoded_data) signed_data = crypto.sha3(cmd_id + encoded_data) signature = crypto.sign(signed_data, self.privkey) # assert crypto.verify(self.pubkey, signature, signed_data) # assert self.pubkey == crypto.ecdsa_recover(signed_data, signature) # assert crypto.verify(self.pubkey, signature, signed_data) assert len(signature) == 65 mdc = crypto.sha3(signature + cmd_id + encoded_data) assert len(mdc) == 32 # print dict(mdc=mdc.encode('hex'), signature=signature.encode('hex'), # data=str(cmd_id + encoded_data).encode('hex')) return mdc + signature + cmd_id + encoded_data