def _buildPacket(payload, exitType, exitInfo, path1, path2, paddingPRNG=None, paranoia=0, suppressTag=0): """Helper method to create a message. The following fields must be set: payload: the intended exit payload. Must be 28K. (exitType, exitInfo): the routing type and info for the final node. (Ignored for reply messages; 'exitInfo' should include the 20-byte decoding tag.) path1: a sequence of ServerInfo objects, one for each node on the first leg of the path. path2: EITHER a sequence of ServerInfo objects, one for each node on the second leg of the path. OR a ReplyBlock object. The following fields are optional: paddingPRNG: A pseudo-random number generator used to pad the headers. If not provided, we use a counter-mode AES stream seeded from our entropy source. paranoia: If this is false, we use the padding PRNG to generate header secrets too. Otherwise, we read all of our header secrets from the true entropy source. """ assert len(payload) == PAYLOAD_LEN reply = None if isinstance(path2, ReplyBlock): reply = path2 path2 = None else: if len(exitInfo) < TAG_LEN and not suppressTag: raise MixError("Implausibly short exit info: %r" % exitInfo) if exitType < MIN_EXIT_TYPE and exitType != DROP_TYPE: raise MixError("Invalid exit type: %4x" % exitType) checkPathLength(path1, path2, exitType, exitInfo, explicitSwap=(reply is None), suppressTag=suppressTag) ### SETUP CODE: let's handle all the variant cases. # Set up the random number generators. if paddingPRNG is None: paddingPRNG = Crypto.getCommonPRNG() if paranoia: nHops = len(path1) if path2: nHops += len(path2) secretRNG = Crypto.getTrueRNG() else: secretRNG = paddingPRNG # Determine exit routing for path1. if reply: path1exittype = reply.routingType path1exitinfo = reply.routingInfo else: path1exittype, path1exitinfo = path1[-1].getRoutingFor(path2[0], swap=1) # Generate secrets for path1. secrets1 = [secretRNG.getBytes(SECRET_LEN) for _ in path1] if path2: # Make secrets for header 2, and construct header 2. We do this before # making header1 so that our rng won't be used for padding yet. secrets2 = [secretRNG.getBytes(SECRET_LEN) for _ in range(len(path2))] header2 = _buildHeader(path2, secrets2, exitType, exitInfo, paddingPRNG) else: secrets2 = None header2 = reply.header # Construct header1. header1 = _buildHeader(path1, secrets1, path1exittype, path1exitinfo, paddingPRNG) return _constructMessage(secrets1, secrets2, header1, header2, payload)
def _buildPacket(payload, exitType, exitInfo, path1, path2, paddingPRNG=None, paranoia=0, suppressTag=0): """Helper method to create a message. The following fields must be set: payload: the intended exit payload. Must be 28K. (exitType, exitInfo): the routing type and info for the final node. (Ignored for reply messages; 'exitInfo' should include the 20-byte decoding tag.) path1: a sequence of ServerInfo objects, one for each node on the first leg of the path. path2: EITHER a sequence of ServerInfo objects, one for each node on the second leg of the path. OR a ReplyBlock object. The following fields are optional: paddingPRNG: A pseudo-random number generator used to pad the headers. If not provided, we use a counter-mode AES stream seeded from our entropy source. paranoia: If this is false, we use the padding PRNG to generate header secrets too. Otherwise, we read all of our header secrets from the true entropy source. """ assert len(payload) == PAYLOAD_LEN reply = None if isinstance(path2, ReplyBlock): reply = path2 path2 = None else: if len(exitInfo) < TAG_LEN and not suppressTag: raise MixError("Implausibly short exit info: %r"%exitInfo) if exitType < MIN_EXIT_TYPE and exitType != DROP_TYPE: raise MixError("Invalid exit type: %4x"%exitType) checkPathLength(path1, path2, exitType, exitInfo, explicitSwap=(reply is None), suppressTag=suppressTag) ### SETUP CODE: let's handle all the variant cases. # Set up the random number generators. if paddingPRNG is None: paddingPRNG = Crypto.getCommonPRNG() if paranoia: nHops = len(path1) if path2: nHops += len(path2) secretRNG = Crypto.getTrueRNG() else: secretRNG = paddingPRNG # Determine exit routing for path1. if reply: path1exittype = reply.routingType path1exitinfo = reply.routingInfo else: path1exittype, path1exitinfo = path1[-1].getRoutingFor(path2[0],swap=1) # Generate secrets for path1. secrets1 = [ secretRNG.getBytes(SECRET_LEN) for _ in path1 ] if path2: # Make secrets for header 2, and construct header 2. We do this before # making header1 so that our rng won't be used for padding yet. secrets2 = [ secretRNG.getBytes(SECRET_LEN) for _ in range(len(path2))] header2 = _buildHeader(path2,secrets2,exitType,exitInfo,paddingPRNG) else: secrets2 = None header2 = reply.header # Construct header1. header1 = _buildHeader(path1,secrets1,path1exittype,path1exitinfo, paddingPRNG) return _constructMessage(secrets1, secrets2, header1, header2, payload)