| 505 | |
| 506 | |
| 507 | class RoomPasswordProvider(object): |
| 508 | CONTROLLED_ROOM_REGEX = re.compile(r"^\+(.*):(\w{12})$") |
| 509 | PASSWORD_REGEX = re.compile(r"[A-Z]{2}-\d{3}-\d{3}") |
| 510 | |
| 511 | @staticmethod |
| 512 | def isControlledRoom(roomName): |
| 513 | return bool(re.match(RoomPasswordProvider.CONTROLLED_ROOM_REGEX, roomName)) |
| 514 | |
| 515 | @staticmethod |
| 516 | def check(roomName, password, salt): |
| 517 | if not password or not re.match(RoomPasswordProvider.PASSWORD_REGEX, password): |
| 518 | raise ValueError() |
| 519 | |
| 520 | if not roomName: |
| 521 | raise NotControlledRoom() |
| 522 | match = re.match(RoomPasswordProvider.CONTROLLED_ROOM_REGEX, roomName) |
| 523 | if not match: |
| 524 | raise NotControlledRoom() |
| 525 | roomHash = match.group(2) |
| 526 | computedHash = RoomPasswordProvider._computeRoomHash(match.group(1), password, salt) |
| 527 | return roomHash == computedHash |
| 528 | |
| 529 | @staticmethod |
| 530 | def getControlledRoomName(roomName, password, salt): |
| 531 | return "+" + roomName + ":" + RoomPasswordProvider._computeRoomHash(roomName, password, salt) |
| 532 | |
| 533 | @staticmethod |
| 534 | def _computeRoomHash(roomName, password, salt): |
| 535 | roomName = roomName.encode('utf8') |
| 536 | salt = salt.encode('utf8') |
| 537 | password = password.encode('utf8') |
| 538 | salt = hashlib.sha256(salt).hexdigest().encode('utf8') |
| 539 | provisionalHash = hashlib.sha256(roomName + salt).hexdigest().encode('utf8') |
| 540 | return hashlib.sha1(provisionalHash + salt + password).hexdigest()[:12].upper() |
| 541 | |
| 542 | |
| 543 | class RandomStringGenerator(object): |