genesis 1 import hashlib
genesis 2 import lib.serpent
genesis 3 from lib.serpent import Serpent
genesis 4 from lib.serpent import serpent_cbc_encrypt
genesis 5 from lib.serpent import serpent_cbc_decrypt
genesis 6 from commands import BROADCAST
genesis 7 from commands import DIRECT
9990-keep-ephemer... 8 from commands import IGNORE
9990-keep-ephemer... 9 from lib.message import Message
genesis 10 import base64
genesis 11 import binascii
genesis 12 import time
genesis 13 import struct
genesis 14 import sys
genesis 15 import hmac
genesis 16 import random
9990-keep-ephemer... 17 import os
genesis 18 import pprint
genesis 19 pp = pprint.PrettyPrinter(indent=4)
genesis 20
genesis 21 PACKET_SIZE = 496
genesis 22 MAX_SPEAKER_SIZE = 32
genesis 23 TS_ACCEPTABLE_SKEW = 60 * 15
genesis 24 BLACK_PACKET_FORMAT = "<448s48s"
genesis 25 RED_PACKET_FORMAT = "<16sBBxB428s"
genesis 26 RED_PACKET_LENGTH_WITH_PADDING = 448
genesis 27 MESSAGE_PACKET_FORMAT = "<q32s32s32s324s"
genesis 28 MAX_MESSAGE_LENGTH = 428
genesis 29 MAX_BOUNCES = 3
9991-improved-log... 30 STALE_PACKET = 0
9991-improved-log... 31 DUPLICATE_PACKET = 1
9991-improved-log... 32 MALFORMED_PACKET = 2
9991-improved-log... 33 INVALID_SIGNATURE = 3
9990-keep-ephemer... 34 IGNORED = 4
genesis 35
genesis 36 class Infosec(object):
genesis 37 def __init__(self, server=None):
genesis 38 self.server = server
genesis 39
genesis 40 def pack(self, peer, message):
genesis 41 try:
9990-keep-ephemer... 42 timestamp = message.timestamp
genesis 43 except:
genesis 44 timestamp = None
9990-keep-ephemer... 45 command = message.command
9990-keep-ephemer... 46 speaker = self._pad(message.speaker, MAX_SPEAKER_SIZE)
genesis 47
genesis 48
genesis 49
genesis 50 if(timestamp == None):
genesis 51 int_ts = int(time.time())
genesis 52 else:
genesis 53 int_ts = timestamp
genesis 54
genesis 55 key_bytes = base64.b64decode(peer.get_key())
genesis 56 signing_key = key_bytes[:32]
genesis 57 cipher_key = key_bytes[32:]
genesis 58
genesis 59
genesis 60
genesis 61
genesis 62
9990-keep-ephemer... 63 if message.original:
genesis 64 if command == DIRECT:
9990-keep-ephemer... 65 self_chain = self.server.state.get_last_message_hash(message.speaker, peer.peer_id)
genesis 66 elif command == BROADCAST:
9990-keep-ephemer... 67 self_chain = self.server.state.get_last_message_hash(message.speaker)
9990-keep-ephemer... 68 elif command == IGNORE:
9990-keep-ephemer... 69 self_chain = "\x00" * 32
genesis 70 net_chain = "\x00" * 32
genesis 71 else:
9990-keep-ephemer... 72 self_chain = message.self_chain
9990-keep-ephemer... 73 net_chain = message.net_chain
genesis 74
genesis 75
genesis 76
9990-keep-ephemer... 77 message_bytes = struct.pack(MESSAGE_PACKET_FORMAT, int_ts, self_chain, net_chain, speaker, message.body)
genesis 78
genesis 79
genesis 80
9990-keep-ephemer... 81 if message.original:
genesis 82 if command == DIRECT:
9990-keep-ephemer... 83 self.server.state.log(message.speaker, message_bytes, peer.peer_id)
genesis 84 elif command == BROADCAST:
9990-keep-ephemer... 85 self.server.state.log(message.speaker, message_bytes)
genesis 86
genesis 87
genesis 88
genesis 89 nonce = self._generate_nonce(16)
9990-keep-ephemer... 90 bounces = message.bounces
genesis 91 version = 0xfe
genesis 92 red_packet_bytes = struct.pack(RED_PACKET_FORMAT, nonce, bounces, version, command, self._pad(message_bytes, MAX_MESSAGE_LENGTH))
genesis 93
genesis 94
genesis 95
genesis 96 serpent = Serpent(cipher_key)
genesis 97 black_packet_bytes = serpent_cbc_encrypt(cipher_key, red_packet_bytes)
genesis 98
genesis 99
genesis 100
genesis 101 signature_bytes = hmac.new(signing_key, black_packet_bytes, hashlib.sha384).digest()
genesis 102
genesis 103
genesis 104
genesis 105 signed_packet_bytes = struct.pack(BLACK_PACKET_FORMAT, black_packet_bytes, signature_bytes)
genesis 106
genesis 107
genesis 108
genesis 109 self.server.recent.insert(int_ts)
genesis 110 return signed_packet_bytes
genesis 111
genesis 112 def unpack(self, peer, black_packet):
genesis 113
genesis 114
genesis 115 key_bytes = base64.b64decode(peer.get_key())
genesis 116 signing_key = key_bytes[:32]
genesis 117 cipher_key = key_bytes[32:]
genesis 118
genesis 119 try:
genesis 120 black_packet_bytes, signature_bytes = struct.unpack(BLACK_PACKET_FORMAT, black_packet)
genesis 121 except:
genesis 122 self.server.print_error("Discarding malformed black packet from %s" % peer.get_key())
9990-keep-ephemer... 123 return Message({ "error_code": MALFORMED_PACKET }, self.server)
genesis 124
genesis 125
genesis 126
genesis 127 signature_check_bytes = hmac.new(signing_key, black_packet_bytes, hashlib.sha384).digest()
genesis 128
genesis 129 if(signature_check_bytes != signature_bytes):
9990-keep-ephemer... 130 return Message({ "error_code": INVALID_SIGNATURE }, self.server)
genesis 131
genesis 132
genesis 133
genesis 134 serpent = Serpent(cipher_key)
genesis 135 red_packet_bytes = serpent_cbc_decrypt(cipher_key, black_packet_bytes)
genesis 136
genesis 137
genesis 138
genesis 139 nonce, bounces, version, command, message_bytes = struct.unpack(RED_PACKET_FORMAT, red_packet_bytes)
genesis 140
9990-keep-ephemer... 141
9990-keep-ephemer... 142
9990-keep-ephemer... 143 if command == IGNORE:
9990-keep-ephemer... 144 return Message({"error_code": IGNORED})
9990-keep-ephemer... 145
genesis 146
genesis 147
genesis 148 int_ts, self_chain, net_chain, speaker, message = struct.unpack(MESSAGE_PACKET_FORMAT, message_bytes)
genesis 149 speaker = speaker.strip()
genesis 150
genesis 151
genesis 152
genesis 153 if(int_ts not in self._ts_range()):
9990-keep-ephemer... 154 return Message({ "error_code": STALE_PACKET }, self.server)
genesis 155
genesis 156 if(self.server.recent.has(int_ts)):
9990-keep-ephemer... 157 return Message({ "error_code": DUPLICATE_PACKET }, self.server)
genesis 158 else:
genesis 159 self.server.recent.insert(int_ts)
genesis 160
genesis 161
genesis 162
genesis 163 if command == DIRECT:
genesis 164 self_chain_check = self.server.state.get_last_message_hash(speaker, peer.peer_id)
genesis 165 elif command == BROADCAST:
genesis 166 self_chain_check = self.server.state.get_last_message_hash(speaker)
genesis 167
genesis 168 self_chain_valid = (self_chain_check == self_chain)
genesis 169
genesis 170
genesis 171
genesis 172 self.server.state.log(speaker, message_bytes, peer.peer_id if (command == DIRECT) else None)
genesis 173
genesis 174
genesis 175
genesis 176 for index, byte in enumerate(message):
genesis 177 if binascii.hexlify(byte) == "00":
genesis 178 unpadded_message = message[0:index]
genesis 179 break
genesis 180
9990-keep-ephemer... 181 return Message({
9990-keep-ephemer... 182 "peer": peer,
9990-keep-ephemer... 183 "body": unpadded_message.rstrip(),
9990-keep-ephemer... 184 "timestamp": int_ts,
9990-keep-ephemer... 185 "command": command,
9990-keep-ephemer... 186 "speaker": speaker,
9990-keep-ephemer... 187 "bounces": bounces,
9990-keep-ephemer... 188 "self_chain": self_chain,
9990-keep-ephemer... 189 "net_chain": net_chain,
9990-keep-ephemer... 190 "self_chain_valid": self_chain_valid,
9990-keep-ephemer... 191 "error_code": None
9990-keep-ephemer... 192 },
9990-keep-ephemer... 193 self.server)
genesis 194
genesis 195 def _pad(self, text, size):
genesis 196 return text.ljust(size)
genesis 197
genesis 198 def _ts_range(self):
genesis 199 current_ts = int(time.time())
genesis 200 return range(current_ts - TS_ACCEPTABLE_SKEW, current_ts + TS_ACCEPTABLE_SKEW)
genesis 201
genesis 202 def _generate_nonce(self, length=8):
genesis 203 """Generate pseudorandom number."""
genesis 204 return ''.join([str(random.randint(0, 9)) for i in range(length)])
9990-keep-ephemer... 205
9990-keep-ephemer... 206 def gen_rubbish_body(self):
9990-keep-ephemer... 207 return os.urandom(MAX_MESSAGE_LENGTH)