- 2BEBEB6EE55F0941C567E114EE01352F18F96D02AC4E2F037B9CED7E71C219CC2ED51AC615D28E22244C5E07F136EC7CE1FB565C7217C62DE4708AEE4D8B05D5
+ 2F8E9DF6CF92A779900080F585A1B9873218D949BE48299950C2B05A64FD5A3ABD8AB927F5C5D4C5D51E7C3DEF2BAB13A6FFE532907E681883730D60BD75B0E5
blatta/lib/infosec.py
(16 . 6)(16 . 7)
429 import random
430 import os
431 import pprint
432 import logging
433 pp = pprint.PrettyPrinter(indent=4)
434
435 PACKET_SIZE = 496
(34 . 32)(35 . 66)
437 IGNORED = 4
438
439 class Infosec(object):
440 def __init__(self, server=None):
441 self.server = server
442 def __init__(self, state=None):
443 self.state = state
444
445 def get_message_bytes(self, message, peer=None):
446 try:
447 timestamp = message.timestamp
448 except:
449 timestamp = None
450 command = message.command
451 speaker = self._pad(message.speaker, MAX_SPEAKER_SIZE)
452 def message(self, message):
453 # if we are not rebroadcasting we need to set the timestamp
454
455 # if we are rebroadcasting we need to use the original timestamp
456 if message.timestamp == None:
457 message.original = True
458 message.timestamp = int(time.time())
459 else:
460 message.original = False
461
462 target_peer = (self.state.get_peer_by_handle(message.handle)
463 if message.command == DIRECT
464 else None)
465
466 if target_peer and not target_peer.get_key():
467 logging.debug("No key for peer associated with %s" % message.handle)
468 return
469
470 if message.command == DIRECT and target_peer == None:
471 logging.debug("Aborting message: unknown handle: %s" % message.handle)
472 return
473
474 message_bytes = self.get_message_bytes(message, target_peer)
475 if message.command != IGNORE:
476 message_hash = binascii.hexlify(hashlib.sha256(message_bytes).digest())
477 logging.debug("generated message_hash: %s" % message_hash)
478 self.state.add_to_dedup_queue(message_hash)
479 self.state.log(message.speaker, message_bytes, target_peer)
480
481 if message.command == DIRECT:
482 signed_packet_bytes = self.pack(target_peer, message, message_bytes)
483 target_peer.send(signed_packet_bytes)
484 elif message.command == BROADCAST or message.command == IGNORE:
485 for peer in self.state.get_keyed_peers():
486
487 # we don't want to send a broadcast back to the originator
488
489 if(timestamp == None):
490 int_ts = int(time.time())
491 if message.peer and (peer.peer_id == message.peer.peer_id):
492 next
493
494 signed_packet_bytes = self.pack(peer, message, message_bytes)
495 peer.send(signed_packet_bytes)
496 else:
497 int_ts = timestamp
498 pass
499
500 def get_message_bytes(self, message, peer=None):
501 timestamp = message.timestamp
502 command = message.command
503 speaker = self._pad(message.speaker, MAX_SPEAKER_SIZE)
504
505 # let's generate the self_chain value from the last message or set it to zero if
506 # there this is the first message
507
508 if message.original:
509 if command == DIRECT:
510 self_chain = self.server.state.get_last_message_hash(message.speaker, peer.peer_id)
511 self_chain = self.state.get_last_message_hash(message.speaker, peer.peer_id)
512 elif command == BROADCAST:
513 self_chain = self.server.state.get_last_message_hash(message.speaker)
514 self_chain = self.state.get_last_message_hash(message.speaker)
515 elif command == IGNORE:
516 self_chain = "\x00" * 32
517 net_chain = "\x00" * 32
(69 . 16)(104 . 19)
519
520 # pack message bytes
521
522 message_bytes = struct.pack(MESSAGE_PACKET_FORMAT, int_ts, self_chain, net_chain, speaker, message.body)
523 if message.command != IGNORE:
524 logging.debug("packing message bytes: %s" % message.body)
525 else:
526 logging.debug("packing rubbish message bytes: %s" % binascii.hexlify(message.body))
527
528 message_bytes = struct.pack(MESSAGE_PACKET_FORMAT, message.timestamp, self_chain, net_chain, speaker, message.body)
529 return message_bytes
530
531 def pack(self, peer, message):
532 def pack(self, peer, message, message_bytes):
533 key_bytes = base64.b64decode(peer.get_key())
534 signing_key = key_bytes[:32]
535 cipher_key = key_bytes[32:]
536
537 message_bytes = self.get_message_bytes(message, peer)
538
539 # pack packet bytes
540
541 nonce = self._generate_nonce(16)
(111 . 15)(149 . 15)
543 try:
544 black_packet_bytes, signature_bytes = struct.unpack(BLACK_PACKET_FORMAT, black_packet)
545 except:
546 self.server.print_error("Discarding malformed black packet from %s" % peer.get_key())
547 return Message({ "error_code": MALFORMED_PACKET }, self.server)
548 logging.error("Discarding malformed black packet from %s" % peer.get_key())
549 return Message({ "error_code": MALFORMED_PACKET })
550
551 # check signature
552
553 signature_check_bytes = hmac.new(signing_key, black_packet_bytes, hashlib.sha384).digest()
554
555 if(signature_check_bytes != signature_bytes):
556 return Message({ "error_code": INVALID_SIGNATURE }, self.server)
557 return Message({ "error_code": INVALID_SIGNATURE })
558
559 # try to decrypt black packet
560
(130 . 10)(168 . 27)
562
563 nonce, bounces, version, command, message_bytes = struct.unpack(RED_PACKET_FORMAT, red_packet_bytes)
564
565 # compute message_hash
566
567 message_hash = binascii.hexlify(hashlib.sha256(message_bytes).digest())
568
569 # unpack message
570
571 int_ts, self_chain, net_chain, speaker, message = struct.unpack(MESSAGE_PACKET_FORMAT, message_bytes)
572 speaker = speaker.strip()
573 int_ts, self_chain, net_chain, speaker, body = struct.unpack(MESSAGE_PACKET_FORMAT, message_bytes)
574
575 # remove padding from speaker
576
577 for index, byte in enumerate(speaker):
578 if byte == '\x00':
579 speaker = speaker[0:index]
580 break
581
582 # remove padding from body
583
584 for index, byte in enumerate(body):
585 if byte == '\x00':
586 body = body[0:index]
587 break
588
589 # nothing to be done for an IGNORE command
590
(143 . 39)(198 . 26)
592 # check timestamp
593
594 if(int_ts not in self._ts_range()):
595 return Message({ "error_code": STALE_PACKET }, self.server)
596
597 # check for duplicates
598
599 message_hash = binascii.hexlify(hashlib.sha256(message_bytes).digest())
600 if(self.server.state.is_duplicate_message(message_hash)):
601 return Message({ "error_code": DUPLICATE_PACKET }, self.server)
602 else:
603 self.server.state.add_to_dedup_queue(message_hash)
604 return Message({ "error_code": STALE_PACKET })
605
606 # check self_chain
607
608 if command == DIRECT:
609 self_chain_check = self.server.state.get_last_message_hash(speaker, peer.peer_id)
610 self_chain_check = self.state.get_last_message_hash(speaker, peer.peer_id)
611 elif command == BROADCAST:
612 self_chain_check = self.server.state.get_last_message_hash(speaker)
613 self_chain_check = self.state.get_last_message_hash(speaker)
614
615 self_chain_valid = (self_chain_check == self_chain)
616
617 # log this message for use in the self_chain check
618
619 self.server.state.log(speaker, message_bytes, peer.peer_id if (command == DIRECT) else None)
620 self.state.log(speaker, message_bytes, peer if (command == DIRECT) else None)
621
622 # remove padding from message bytes
623
624 for index, byte in enumerate(message):
625 if binascii.hexlify(byte) == "00":
626 unpadded_message = message[0:index]
627 break
628 # build message object
629
630 return Message({
631 message = Message({
632 "peer": peer,
633 "body": unpadded_message.rstrip(),
634 "body": body.rstrip(),
635 "timestamp": int_ts,
636 "command": command,
637 "speaker": speaker,
(183 . 12)(225 . 19)
639 "self_chain": self_chain,
640 "net_chain": net_chain,
641 "self_chain_valid": self_chain_valid,
642 "error_code": None
643 },
644 self.server)
645 "message_hash": message_hash
646 })
647
648 # check for duplicates
649
650 if(self.state.is_duplicate_message(message_hash)):
651 message.error_code = DUPLICATE_PACKET
652 return message
653
654 return message
655
656 def _pad(self, text, size):
657 return text.ljust(size)
658 return text.ljust(size, "\x00")
659
660 def _ts_range(self):
661 current_ts = int(time.time())