diff -uNr a/blatta/README.txt b/blatta/README.txt --- a/blatta/README.txt false +++ b/blatta/README.txt 0a24e35c1f08fa449b1f6acc9a61b373aca19bf43fbb3a728c1fc89123b8a456d193cc8bf4eeb9bba90f18e7a82094f1b24bf10e20f6d0729367127d502d3fe7 @@ -0,0 +1,39 @@ +Blatta implements a subset of the Pest spec, which can be found +here: http://www.loper-os.org/pub/pest/pest_draft.html + +Although it is a work in progress and much is yet to be completed, Blatta +*should* be able to interact with another Pest client +successfully. + +Notably missing: + +- Pest-specific warning/informational output for incoming/outgoing messages +- GetData message support +- Key Offer message support +- Key Slice message support + +Blatta supports the following Pest-specific commands: + +AT +WOT +PEER +UNPEER +GENKEY +KEY +UNKEY + +GETTING STARTED + +1. Launch blatta with something like the following command: +./blatta --port=6668 --address-table-path config.py +2. Add a peer using the peer command. +3. Use genkey to generate a key. +4. Add the key to the peer using the key command. +5. Add an address for the peer using the address command. + +NOTES FOR DIFF/PATCH N00B5 + +To apply the genesis patch (or any patch) to the current directory +and recreate the directory structure of the original: + +patch -p1 -ruN < /genesis.vdiff diff -uNr a/blatta/blatta b/blatta/blatta --- a/blatta/blatta false +++ b/blatta/blatta 01f00ef74cd2143c7b07ea439284cea743c0406301e7d9255ed9287a022d8c2db04125a346caa2b1085e38bfd44d1fe342a52467c2511f6c714c79db9954f89d @@ -0,0 +1,146 @@ +#! /usr/bin/env python + +import os +import re +import select +import socket +import string +import sys +import tempfile +import time +from lib.server import VERSION +from lib.server import Server +from lib.peer import Peer +from datetime import datetime +from optparse import OptionParser + + +def main(argv): + op = OptionParser( + version=VERSION, + description="alcuin is a small and limited IRC server emulator for gossip networks.") + op.add_option( + "-a", "--address-table-path", + help="Import address table from specified file") + op.add_option( + "-b", "--db-path", + help="Specify path to settings database file") + op.add_option( + "-c", "--config-file-path", + metavar="X", + help="load the configfile from X") + op.add_option( + "-d", "--daemon", + action="store_true", + help="fork and become a daemon") + op.add_option( + "--debug", + action="store_true", + help="print debug messages to stdout") + op.add_option( + "--listen", + metavar="X", + help="listen on specific IP address X") + op.add_option( + "--logdir", + metavar="X", + help="store channel log in directory X") + op.add_option( + "--motd", + metavar="X", + help="display file X as message of the day") + op.add_option( + "-s", "--ssl-pem-file", + metavar="FILE", + help="enable SSL and use FILE as the .pem certificate+key") + op.add_option( + "-p", "--password", + metavar="X", + help="require connection password X; default: no password") + op.add_option( + "--ports", + metavar="X", + help="listen to ports X (a list separated by comma or whitespace);" + " default: 6667 or 6697 if SSL is enabled") + op.add_option( + "--udp-port", + metavar="X", + help="listen for UDP packets on X;" + " default: 7778") + op.add_option( + "--statedir", + metavar="X", + help="save persistent channel state (topic, key) in directory X") + op.add_option( + "--verbose", + action="store_true", + help="be verbose (print some progress messages to stdout)") + if os.name == "posix": + op.add_option( + "--chroot", + metavar="X", + help="change filesystem root to directory X after startup" + " (requires root)") + op.add_option( + "--setuid", + metavar="U[:G]", + help="change process user (and optionally group) after startup" + " (requires root)") + + (options, args) = op.parse_args(argv[1:]) + if options.debug: + options.verbose = True + if options.ports is None: + if options.ssl_pem_file is None: + options.ports = "6667" + else: + options.ports = "6697" + if options.udp_port is None: + options.udp_port = 7778 + else: + options.udp_port = int(options.udp_port) + if options.db_path is None: + options.db_path = "alcuin.db" + if options.config_file_path is None: + options.config_file_path = "config.py" + if options.chroot: + if os.getuid() != 0: + op.error("Must be root to use --chroot") + if options.setuid: + from pwd import getpwnam + from grp import getgrnam + if os.getuid() != 0: + op.error("Must be root to use --setuid") + matches = options.setuid.split(":") + if len(matches) == 2: + options.setuid = (getpwnam(matches[0]).pw_uid, + getgrnam(matches[1]).gr_gid) + elif len(matches) == 1: + options.setuid = (getpwnam(matches[0]).pw_uid, + getpwnam(matches[0]).pw_gid) + else: + op.error("Specify a user, or user and group separated by a colon," + " e.g. --setuid daemon, --setuid nobody:nobody") + if (os.getuid() == 0 or os.getgid() == 0) and not options.setuid: + op.error("Running this service as root is not recommended. Use the" + " --setuid option to switch to an unprivileged account after" + " startup. If you really intend to run as root, use" + " \"--setuid root\".") + + ports = [] + for port in re.split(r"[,\s]+", options.ports): + try: + ports.append(int(port)) + except ValueError: + op.error("bad port: %r" % port) + options.ports = ports + server = Server(options) + if options.daemon: + server.daemonize() + try: + server.start() + except KeyboardInterrupt: + server.print_error("Interrupted.") + + +main(sys.argv) diff -uNr a/blatta/config.py.example b/blatta/config.py.example --- a/blatta/config.py.example false +++ b/blatta/config.py.example 79e611c4ec3b9dcbfc23c09140f4f2db23923b97bec5427fb28e3886ddac5f074da2a80c379837a011fc834d41dd2273f9d9a85635983ddde769f5924f0ab74f @@ -0,0 +1,10 @@ +peers = [ + { + "name":"schellenberg", + # Secrets must be precisely 64 bytes. + "local_secret":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "remote_secret":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "address":"10.0.0.1", + "port":7778 + } +] diff -uNr a/blatta/lib/__init__.py b/blatta/lib/__init__.py --- a/blatta/lib/__init__.py false +++ b/blatta/lib/__init__.py 85df4eea67226c8976c9484f97e06ee93506c5e43982babfe99ae2a075f4e1f43f99442cc80897e3ad2d8a409ae59320410347ca74c4317674b815082de8b240 @@ -0,0 +1 @@ +# This file can't be empty otherwise diff won't see it. diff -uNr a/blatta/lib/channel.py b/blatta/lib/channel.py --- a/blatta/lib/channel.py false +++ b/blatta/lib/channel.py 29051fff4c05169a752059f5102291f981a73ec3c5112cb8135865919a2a8ce0f02db32c7c95639f39b51e2f444af5229febca7fe113d06b7d5c347c3f46bf30 @@ -0,0 +1,60 @@ +class Channel(object): + def __init__(self, server, name): + self.server = server + self.name = name + self.members = set() + self._topic = "" + self._key = None + if self.server.statedir: + self._state_path = "%s/%s" % ( + self.server.statedir, + name.replace("_", "__").replace("/", "_")) + self._read_state() + else: + self._state_path = None + + def add_member(self, client): + self.members.add(client) + + def get_topic(self): + return self._topic + + def set_topic(self, value): + self._topic = value + self._write_state() + + topic = property(get_topic, set_topic) + + def get_key(self): + return self._key + + def set_key(self, value): + self._key = value + self._write_state() + + key = property(get_key, set_key) + + def remove_client(self, client): + self.members.discard(client) + if not self.members: + self.server.remove_channel(self) + + def _read_state(self): + if not (self._state_path and os.path.exists(self._state_path)): + return + data = {} + exec(open(self._state_path), {}, data) + self._topic = data.get("topic", "") + self._key = data.get("key") + + def _write_state(self): + if not self._state_path: + return + (fd, path) = tempfile.mkstemp(dir=os.path.dirname(self._state_path)) + fp = os.fdopen(fd, "w") + fp.write("topic = %r\n" % self.topic) + fp.write("key = %r\n" % self.key) + fp.close() + os.rename(path, self._state_path) + + diff -uNr a/blatta/lib/client.py b/blatta/lib/client.py --- a/blatta/lib/client.py false +++ b/blatta/lib/client.py 804c596288d04455ba5127cc25937f7ac76ca289f046ad31bd71b66264b9db73584a8fc1d4535e882d70a0f5fde10f896dbd3ae51c3fde4018a3f3e49b55f7f2 @@ -0,0 +1,676 @@ +import socket +import time +import sys +import re +import string +import os +import base64 +from lib.server import VERSION +from funcs import * +from lib.commands import BROADCAST +from lib.commands import DIRECT + +class Client(object): + __linesep_regexp = re.compile(r"\r?\n") + # The RFC limit for nicknames is 9 characters, but what the heck. + __valid_nickname_regexp = re.compile( + r"^[][\`_^{|}A-Za-z][][\`_^{|}A-Za-z0-9-]{0,50}$") + __valid_channelname_regexp = re.compile( + r"^[&#+!][^\x00\x07\x0a\x0d ,:]{0,50}$") + + def __init__(self, server, socket): + self.server = server + self.socket = socket + self.channels = {} # irc_lower(Channel name) --> Channel + self.nickname = None + self.user = None + self.realname = None + (self.host, self.port) = socket.getpeername() + self.__timestamp = time.time() + self.__readbuffer = "" + self.__writebuffer = "" + self.__sent_ping = False + if self.server.password: + self.__handle_command = self.__pass_handler + else: + self.__handle_command = self.__registration_handler + + def is_addressed_to_me(self, message): + command = self.__parse_udp_message(message) + if command[0] == 'PRIVMSG': + if command[1][0][0] == '#' or command[1][0] == self.nickname: + return True + else: + return False + else: + return True + + def get_prefix(self): + return "%s!%s@%s" % (self.nickname, self.user, self.host) + prefix = property(get_prefix) + + def check_aliveness(self): + now = time.time() + if self.__timestamp + 180 < now: + self.disconnect("ping timeout") + return + if not self.__sent_ping and self.__timestamp + 90 < now: + if self.__handle_command == self.__command_handler: + # Registered. + self.message("PING :%s" % self.server.name) + self.__sent_ping = True + else: + # Not registered. + self.disconnect("ping timeout") + + def write_queue_size(self): + return len(self.__writebuffer) + + def __parse_udp_message(self, message): + data = " ".join(message.split()[1:]) + "\r\n" + lines = self.__linesep_regexp.split(data) + lines = lines[:-1] + commands = [] + for line in lines: + if not line: + # Empty line. Ignore. + continue + x = line.split(" ", 1) + command = x[0].upper() + if len(x) == 1: + arguments = [] + else: + if len(x[1]) > 0 and x[1][0] == ":": + arguments = [x[1][1:]] + else: + y = string.split(x[1], " :", 1) + arguments = string.split(y[0]) + if len(y) == 2: + arguments.append(y[1]) + commands.append([command, arguments]) + return commands[0] + + def __parse_read_buffer(self): + lines = self.__linesep_regexp.split(self.__readbuffer) + self.__readbuffer = lines[-1] + lines = lines[:-1] + for line in lines: + if not line: + # Empty line. Ignore. + continue + x = line.split(" ", 1) + command = x[0].upper() + if len(x) == 1: + arguments = [] + else: + if len(x[1]) > 0 and x[1][0] == ":": + arguments = [x[1][1:]] + else: + y = string.split(x[1], " :", 1) + arguments = string.split(y[0]) + if len(y) == 2: + arguments.append(y[1]) + self.__handle_command(command, arguments) + + def __pass_handler(self, command, arguments): + server = self.server + if command == "PASS": + if len(arguments) == 0: + self.reply_461("PASS") + else: + if arguments[0].lower() == server.password: + self.__handle_command = self.__registration_handler + else: + self.reply("464 :Password incorrect") + elif command == "QUIT": + self.disconnect("Client quit") + return + + def __registration_handler(self, command, arguments): + server = self.server + if command == "NICK": + if len(arguments) < 1: + self.reply("431 :No nickname given") + return + nick = arguments[0] + if server.get_client(nick): + self.reply("433 * %s :Nickname is already in use" % nick) + elif not self.__valid_nickname_regexp.match(nick): + self.reply("432 * %s :Erroneous nickname" % nick) + else: + self.nickname = nick + server.client_changed_nickname(self, None) + elif command == "USER": + if len(arguments) < 4: + self.reply_461("USER") + return + self.user = arguments[0] + self.realname = arguments[3] + elif command == "QUIT": + self.disconnect("Client quit") + return + if self.nickname and self.user: + self.reply("001 %s :Hi, welcome to IRC" % self.nickname) + self.reply("002 %s :Your host is %s, running version blatta-%s" + % (self.nickname, server.name, VERSION)) + self.reply("003 %s :This server was created sometime" + % self.nickname) + self.reply("004 %s :%s blatta-%s o o" + % (self.nickname, server.name, VERSION)) + self.send_lusers() + self.send_motd() + self.__handle_command = self.__command_handler + + def __command_handler(self, command, arguments): + def away_handler(): + pass + + def ison_handler(): + if len(arguments) < 1: + self.reply_461("ISON") + return + nicks = arguments + online = [n for n in nicks if server.get_client(n)] + self.reply("303 %s :%s" % (self.nickname, " ".join(online))) + + def join_handler(): + if len(arguments) < 1: + self.reply_461("JOIN") + return + if arguments[0] == "0": + for (channelname, channel) in self.channels.items(): + self.message_channel(channel, "PART", channelname, True) + self.channel_log(channel, "left", meta=True) + server.remove_member_from_channel(self, channelname) + self.channels = {} + return + channelnames = arguments[0].split(",") + if len(arguments) > 1: + keys = arguments[1].split(",") + else: + keys = [] + keys.extend((len(channelnames) - len(keys)) * [None]) + for (i, channelname) in enumerate(channelnames): + if irc_lower(channelname) in self.channels: + continue + if not valid_channel_re.match(channelname): + self.reply_403(channelname) + continue + channel = server.get_channel(channelname) + if channel.key is not None and channel.key != keys[i]: + self.reply( + "475 %s %s :Cannot join channel (+k) - bad key" + % (self.nickname, channelname)) + continue + channel.add_member(self) + self.channels[irc_lower(channelname)] = channel + self.message_channel(channel, "JOIN", channelname, True) + self.channel_log(channel, "joined", meta=True) + if channel.topic: + self.reply("332 %s %s :%s" + % (self.nickname, channel.name, channel.topic)) + else: + self.reply("331 %s %s :No topic is set" + % (self.nickname, channel.name)) + self.reply("353 %s = %s :%s" + % (self.nickname, + channelname, + " ".join(sorted(x.nickname + for x in channel.members)))) + self.reply("366 %s %s :End of NAMES list" + % (self.nickname, channelname)) + + def list_handler(): + if len(arguments) < 1: + channels = server.channels.values() + else: + channels = [] + for channelname in arguments[0].split(","): + if server.has_channel(channelname): + channels.append(server.get_channel(channelname)) + channels.sort(key=lambda x: x.name) + for channel in channels: + self.reply("322 %s %s %d :%s" + % (self.nickname, channel.name, + len(channel.members), channel.topic)) + self.reply("323 %s :End of LIST" % self.nickname) + + def lusers_handler(): + self.send_lusers() + + def mode_handler(): + if len(arguments) < 1: + self.reply_461("MODE") + return + targetname = arguments[0] + if server.has_channel(targetname): + channel = server.get_channel(targetname) + if len(arguments) < 2: + if channel.key: + modes = "+k" + if irc_lower(channel.name) in self.channels: + modes += " %s" % channel.key + else: + modes = "+" + self.reply("324 %s %s %s" + % (self.nickname, targetname, modes)) + return + flag = arguments[1] + if flag == "+k": + if len(arguments) < 3: + self.reply_461("MODE") + return + key = arguments[2] + if irc_lower(channel.name) in self.channels: + channel.key = key + self.message_channel( + channel, "MODE", "%s +k %s" % (channel.name, key), + True) + self.channel_log( + channel, "set channel key to %s" % key, meta=True) + else: + self.reply("442 %s :You're not on that channel" + % targetname) + elif flag == "-k": + if irc_lower(channel.name) in self.channels: + channel.key = None + self.message_channel( + channel, "MODE", "%s -k" % channel.name, + True) + self.channel_log( + channel, "removed channel key", meta=True) + else: + self.reply("442 %s :You're not on that channel" + % targetname) + else: + self.reply("472 %s %s :Unknown MODE flag" + % (self.nickname, flag)) + elif targetname == self.nickname: + if len(arguments) == 1: + self.reply("221 %s +" % self.nickname) + else: + self.reply("501 %s :Unknown MODE flag" % self.nickname) + else: + self.reply_403(targetname) + + def motd_handler(): + self.send_motd() + + def nick_handler(): + if len(arguments) < 1: + self.reply("431 :No nickname given") + return + newnick = arguments[0] + client = server.get_client(newnick) + if newnick == self.nickname: + pass + elif client and client is not self: + self.reply("433 %s %s :Nickname is already in use" + % (self.nickname, newnick)) + elif not self.__valid_nickname_regexp.match(newnick): + self.reply("432 %s %s :Erroneous Nickname" + % (self.nickname, newnick)) + else: + for x in self.channels.values(): + self.channel_log( + x, "changed nickname to %s" % newnick, meta=True) + oldnickname = self.nickname + self.nickname = newnick + server.client_changed_nickname(self, oldnickname) + self.message_related( + ":%s!%s@%s NICK %s" + % (oldnickname, self.user, self.host, self.nickname), + True) + + def notice_and_privmsg_handler(): + if len(arguments) == 0: + self.reply("411 %s :No recipient given (%s)" + % (self.nickname, command)) + return + if len(arguments) == 1: + self.reply("412 %s :No text to send" % self.nickname) + return + targetname = arguments[0] + message = arguments[1] + client = server.get_client(targetname) + + if server.has_channel(targetname): + channel = server.get_channel(targetname) + self.message_channel( + channel, command, "%s :%s" % (channel.name, message)) + self.channel_log(channel, message) + else: + formatted_message = ":%s %s %s :%s" % (self.prefix, command, targetname, message) + self.server.peer_message({ + "speaker": self.nickname, + "handle": targetname, + "body": formatted_message, + "bounces": 0, + "command": DIRECT + }) + if(client): + client.message(formatted_message) + + def part_handler(): + if len(arguments) < 1: + self.reply_461("PART") + return + if len(arguments) > 1: + partmsg = arguments[1] + else: + partmsg = self.nickname + for channelname in arguments[0].split(","): + if not valid_channel_re.match(channelname): + self.reply_403(channelname) + elif not irc_lower(channelname) in self.channels: + self.reply("442 %s %s :You're not on that channel" + % (self.nickname, channelname)) + else: + channel = self.channels[irc_lower(channelname)] + self.message_channel( + channel, "PART", "%s :%s" % (channelname, partmsg), + True) + self.channel_log(channel, "left (%s)" % partmsg, meta=True) + del self.channels[irc_lower(channelname)] + server.remove_member_from_channel(self, channelname) + + def ping_handler(): + if len(arguments) < 1: + self.reply("409 %s :No origin specified" % self.nickname) + return + self.reply("PONG %s :%s" % (server.name, arguments[0])) + + def pong_handler(): + pass + + def quit_handler(): + if len(arguments) < 1: + quitmsg = self.nickname + else: + quitmsg = arguments[0] + self.disconnect(quitmsg) + + def topic_handler(): + if len(arguments) < 1: + self.reply_461("TOPIC") + return + channelname = arguments[0] + channel = self.channels.get(irc_lower(channelname)) + if channel: + if len(arguments) > 1: + newtopic = arguments[1] + channel.topic = newtopic + self.message_channel( + channel, "TOPIC", "%s :%s" % (channelname, newtopic), + True) + self.channel_log( + channel, "set topic to %r" % newtopic, meta=True) + else: + if channel.topic: + self.reply("332 %s %s :%s" + % (self.nickname, channel.name, + channel.topic)) + else: + self.reply("331 %s %s :No topic is set" + % (self.nickname, channel.name)) + else: + self.reply("442 %s :You're not on that channel" % channelname) + + def wallops_handler(): + if len(arguments) < 1: + self.reply_461(command) + message = arguments[0] + for client in server.clients.values(): + client.message(":%s NOTICE %s :Global notice: %s" + % (self.prefix, client.nickname, message)) + + def who_handler(): + if len(arguments) < 1: + return + targetname = arguments[0] + if server.has_channel(targetname): + channel = server.get_channel(targetname) + for member in channel.members: + self.reply("352 %s %s %s %s %s %s H :0 %s" + % (self.nickname, targetname, member.user, + member.host, server.name, member.nickname, + member.realname)) + self.reply("315 %s %s :End of WHO list" + % (self.nickname, targetname)) + + def whois_handler(): + if len(arguments) < 1: + return + username = arguments[0] + user = server.get_client(username) + if user: + self.reply("311 %s %s %s %s * :%s" + % (self.nickname, user.nickname, user.user, + user.host, user.realname)) + self.reply("312 %s %s %s :%s" + % (self.nickname, user.nickname, server.name, + server.name)) + self.reply("319 %s %s :%s" + % (self.nickname, user.nickname, + " ".join(user.channels))) + self.reply("318 %s %s :End of WHOIS list" + % (self.nickname, user.nickname)) + else: + self.reply("401 %s %s :No such nick" + % (self.nickname, username)) + + def wot_handler(): + if len(arguments) < 1: + # Display the current WOT + for peer in self.server.state.get_peers(): + self.pest_reply("%s %s:%d" % (string.join(peer.handles, ","), peer.address, peer.port)) + elif len(arguments) == 1: + # Display all WOT data concerning the peer identified by HANDLE, + # including all known keys, starting with the most recently used, for that peer. + handle = arguments[0] + peer = self.server.state.get_peer_by_handle(handle) + self.pest_reply("keys:") + for key in peer.keys: + self.pest_reply("%s" % key) + + else: + pass + + def peer_handler(): + if len(arguments) == 1: + self.server.state.add_peer(arguments[0]) + self.pest_reply("added new peer %s" % arguments[0]) + else: + self.pest_reply("Usage: PEER ") + + def unpeer_handler(): + if len(arguments) == 1: + try: + self.server.state.remove_peer(arguments[0]) + self.pest_reply("removed peer %s" % arguments[0]) + except: + self.pest_reply("Error attempting to remove peer") + else: + self.pest_reply("Usage: UNPEER ") + + def genkey_handler(): + self.pest_reply(base64.b64encode(os.urandom(64))) + + def key_handler(): + if len(arguments) != 2: + self.pest_reply("Usage: KEY ") + else: + handle = arguments[0] + key = arguments[1] + try: + self.server.state.add_key(handle, key) + except: + self.pest_reply("Error attempting to add key") + + def unkey_handler(): + if len(arguments) != 1: + self.pest_reply("Usage: UNKEY ") + else: + try: + self.server.state.remove_key(arguments[0]) + except: + self.pest_reply("Error attempting to remove key") + + def at_handler(): + if len(arguments) == 0: + at = self.server.state.get_at() + elif len(arguments) == 1: + handle = arguments[0] + at = self.server.state.get_at(handle) + elif len(arguments) == 2: + handle, address = arguments + address_ip, port = string.split(address, ":") + self.server.state.update_address_table({"handle": handle, + "address": address_ip, + "port": port}) + return + elif len(arguments) > 2: + self.pest_reply("Usage: AT [] [
]") + return + for address in at: + self.pest_reply("%s %s %s" % (address["handle"], + address["address"], + address["updated_at"])) + + handler_table = { + "AWAY": away_handler, + "AT": at_handler, + "GENKEY": genkey_handler, + "ISON": ison_handler, + "JOIN": join_handler, + "KEY": key_handler, + "LIST": list_handler, + "LUSERS": lusers_handler, + "MODE": mode_handler, + "MOTD": motd_handler, + "NICK": nick_handler, + "NOTICE": notice_and_privmsg_handler, + "PART": part_handler, + "PEER": peer_handler, + "PING": ping_handler, + "PONG": pong_handler, + "PRIVMSG": notice_and_privmsg_handler, + "QUIT": quit_handler, + "TOPIC": topic_handler, + "UNKEY": unkey_handler, + "UNPEER": unpeer_handler, + "WALLOPS": wallops_handler, + "WHO": who_handler, + "WHOIS": whois_handler, + "WOT": wot_handler + } + server = self.server + valid_channel_re = self.__valid_channelname_regexp + try: + handler_table[command]() + except KeyError: + self.reply("421 %s %s :Unknown command" % (self.nickname, command)) + + def socket_readable_notification(self): + try: + data = self.socket.recv(2 ** 10) + self.server.print_debug( + "[%s:%d] -> %r" % (self.host, self.port, data)) + quitmsg = "EOT" + except socket.error as x: + data = "" + quitmsg = x + if data: + self.__readbuffer += data + self.__parse_read_buffer() + self.__timestamp = time.time() + self.__sent_ping = False + else: + self.disconnect(quitmsg) + + def socket_writable_notification(self): + try: + sent = self.socket.send(self.__writebuffer) + self.server.print_debug( + "[%s:%d] <- %r" % ( + self.host, self.port, self.__writebuffer[:sent])) + self.__writebuffer = self.__writebuffer[sent:] + except socket.error as x: + self.disconnect(x) + + def disconnect(self, quitmsg): + self.message("ERROR :%s" % quitmsg) + self.server.print_info( + "Disconnected connection from %s:%s (%s)." % ( + self.host, self.port, quitmsg)) + self.socket.close() + self.server.remove_client(self, quitmsg) + + def message(self, msg): + self.__writebuffer += msg + "\r\n" + + def reply(self, msg): + self.message(":%s %s" % (self.server.name, msg)) + + def pest_reply(self, msg): + self.message("NOTICE %s :%s" % (self.nickname, msg)) + + def reply_403(self, channel): + self.reply("403 %s %s :No such channel" % (self.nickname, channel)) + + def reply_461(self, command): + nickname = self.nickname or "*" + self.reply("461 %s %s :Not enough parameters" % (nickname, command)) + + def message_channel(self, channel, command, message, include_self=False): + line = ":%s %s %s" % (self.prefix, command, message) + for client in channel.members: + if client != self or include_self: + client.message(line) + # send the channel message to peers as well + self.server.peer_message({ + "speaker": self.nickname, + "command": BROADCAST, + "bounces": 0, + "body": line + }) + + def channel_log(self, channel, message, meta=False): + if not self.server.logdir: + return + if meta: + format = "[%s] * %s %s\n" + else: + format = "[%s] <%s> %s\n" + timestamp = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC") + logname = channel.name.replace("_", "__").replace("/", "_") + fp = open("%s/%s.log" % (self.server.logdir, logname), "a") + fp.write(format % (timestamp, self.nickname, message)) + fp.close() + + def message_related(self, msg, include_self=False): + clients = set() + if include_self: + clients.add(self) + for channel in self.channels.values(): + clients |= channel.members + if not include_self: + clients.discard(self) + for client in clients: + client.message(msg) + + def send_lusers(self): + self.reply("251 %s :There are %d users and 0 services on 1 server" + % (self.nickname, len(self.server.clients))) + + def send_motd(self): + server = self.server + motdlines = server.get_motd_lines() + if motdlines: + self.reply("375 %s :- %s Message of the day -" + % (self.nickname, server.name)) + for line in motdlines: + self.reply("372 %s :- %s" % (self.nickname, line.rstrip())) + self.reply("376 %s :End of /MOTD command" % self.nickname) + else: + self.reply("422 %s :MOTD File is missing" % self.nickname) diff -uNr a/blatta/lib/commands.py b/blatta/lib/commands.py --- a/blatta/lib/commands.py false +++ b/blatta/lib/commands.py e4fa49d77ae8627d1b7e68b131dd1e66d03c2fd30904691b1d0179bdf99d2972d8f0a635d4140b6d1e18a4ecbe5c22eddab3505b4caf29673136a372ba4edd0b @@ -0,0 +1,10 @@ +# 0x00 Broadcast The message is to be relayed to the entire net. +# 0x01 Direct The message is strictly for the addressee, and is not intended to be relayed. +# 0x02 Reserved +# ... ... Packet is rejected +# 0xFE Reserved +# 0xFF Ignore A station may transmit garbage messages to its peers, to frustrate traffic analysis by snoops. In such cases, it will consist of arbitrary random bytes. A recipient of such a message may relay it to an arbitrary subset of his WOT. Receipt of a garbage message must not result in any console output. + +BROADCAST = 0x00 +DIRECT = 0x01 +IGNORE = 0xFF diff -uNr a/blatta/lib/funcs.py b/blatta/lib/funcs.py --- a/blatta/lib/funcs.py false +++ b/blatta/lib/funcs.py 26f103d62d35c8d8e94a6537afea06a33b8cf920ebedbf6b2a38fafb9f3be31379386194dc70c0a2e87b01f6725b43d3ad182037f6cd1d9db1b8f36cf8483542 @@ -0,0 +1,11 @@ +import sys +import string + +_maketrans = str.maketrans if sys.version_info[0] == 3 else string.maketrans +_ircstring_translation = _maketrans( + string.ascii_lowercase.upper() + "[]\\^", + string.ascii_lowercase + "{}|~") + +def irc_lower(s): + return string.translate(s, _ircstring_translation) + diff -uNr a/blatta/lib/infosec.py b/blatta/lib/infosec.py --- a/blatta/lib/infosec.py false +++ b/blatta/lib/infosec.py ae8fe58a8f92689212f3ccdb9a30a530cd19b0ce5ad7aeecdf5eee1c6c9505ae56df43a3132ca534d0bdb745d469cdbce7f2a51ef30900259dada9e894288827 @@ -0,0 +1,189 @@ +import hashlib +import lib.serpent +from lib.serpent import Serpent +from lib.serpent import serpent_cbc_encrypt +from lib.serpent import serpent_cbc_decrypt +from commands import BROADCAST +from commands import DIRECT +import base64 +import binascii +import time +import struct +import sys +import hmac +import random +import pprint +pp = pprint.PrettyPrinter(indent=4) + +PACKET_SIZE = 496 +MAX_SPEAKER_SIZE = 32 +TS_ACCEPTABLE_SKEW = 60 * 15 +BLACK_PACKET_FORMAT = "<448s48s" +RED_PACKET_FORMAT = "<16sBBxB428s" +RED_PACKET_LENGTH_WITH_PADDING = 448 +MESSAGE_PACKET_FORMAT = " 13 december 2007. +## +## Copyrights +## ========== +## +## This code is a derived from an implementation by Dr Brian Gladman +## (gladman@seven77.demon.co.uk) which is subject to the following license. +## This Python implementation is not subject to any other license. +## +##/* This is an independent implementation of the encryption algorithm: +## * +## * Serpent by Ross Anderson, Eli Biham and Lars Knudsen +## * +## * which is a candidate algorithm in the Advanced Encryption Standard +## * programme of the US National Institute of Standards and Technology +## * +## * Copyright in this implementation is held by Dr B R Gladman but I +## * hereby give permission for its free direct or derivative use subject +## * to acknowledgment of its origin and compliance with any conditions +## * that the originators of the algorithm place on its exploitation. +## * +## * Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 +## */ +## +## The above copyright notice must not be removed. +## +## Information +## =========== +## +## Anyone thinking of using this code should reconsider. It's slow. +## Try python-mcrypt instead. In case a faster library is not installed +## on the target system, this code can be used as a portable fallback. + +import binascii +import base64 + +block_size = 16 +key_size = 32 + +class Serpent: + + def __init__(self, key=None): + """Serpent.""" + + if key: + self.set_key(key) + + + def set_key(self, key): + """Init.""" + + key_len = len(key) + if key_len % 4: + # XXX: add padding? + raise KeyError, "key not a multiple of 4" + if key_len > 32: + # XXX: prune? + raise KeyError, "key_len > 32" + + self.key_context = [0] * 140 + + key_word32 = [0] * 32 + i = 0 + while key: + key_word32[i] = struct.unpack("> n) | ((x << (32 - n)) & 0xFFFFFFFF) + +def rotl32(x, n): + return ((x << n) & 0xFFFFFFFF) | (x >> (32 - n)) + +def byteswap32(x): + return ((x & 0xff) << 24) | (((x >> 8) & 0xff) << 16) | \ + (((x >> 16) & 0xff) << 8) | ((x >> 24) & 0xff) + +def set_key(l_key, key, key_len): + key_len *= 8 + if key_len > 256: + return False + + i = 0 + lk = (key_len + 31) / 32 + while i < lk: + l_key[i] = key[i] + if WORD_BIGENDIAN: + l_key[i] = byteswap32(key[i]) + i += 1 + + if key_len < 256: + while i < 8: + l_key[i] = 0 + i += 1 + i = key_len / 32 + lk = 1 << (key_len % 32) + l_key[i] = (l_key[i] & (lk - 1)) | lk + for i in xrange(132): + lk = l_key[i] ^ l_key[i + 3] ^ l_key[i + 5] ^ l_key[i + 7] ^ 0x9e3779b9 ^ i + l_key[i + 8] = ((lk << 11) & 0xFFFFFFFF) | (lk >> 21) + + key = l_key + # serpent_generate.py + a = key[4 * 0 + 8] + b = key[4 * 0 + 9] + c = key[4 * 0 + 10] + d = key[4 * 0 + 11] + e = 0 + f = 0 + g = 0 + h = 0 + t1 = 0 + t2 = 0 + t3 = 0 + t4 = 0 + t5 = 0 + t6 = 0 + t7 = 0 + t8 = 0 + t9 = 0 + t10 = 0 + t11 = 0 + t12 = 0 + t13 = 0 + t14 = 0 + t15 = 0 + t16 = 0 + t1 = a ^ c; + t2 = d ^ t1; + t3 = a & t2; + t4 = d ^ t3; + t5 = b & t4; + g = t2 ^ t5; + t7 = a | g; + t8 = b | d; + t11 = a | d; + t9 = t4 & t7; + f = t8 ^ t9; + t12 = b ^ t11; + t13 = g ^ t9; + t15 = t3 ^ t8; + h = t12 ^ t13; + t16 = c & t15; + e = t12 ^ t16 + key[4 * 0 + 8] = e + key[4 * 0 + 9] = f + key[4 * 0 + 10] = g + key[4 * 0 + 11] = h + a = key[4 * 1 + 8] + b = key[4 * 1 + 9] + c = key[4 * 1 + 10] + d = key[4 * 1 + 11] + t1 = (~a) % 0x100000000; + t2 = b ^ d; + t3 = c & t1; + t13 = d | t1; + e = t2 ^ t3; + t5 = c ^ t1; + t6 = c ^ e; + t7 = b & t6; + t10 = e | t5; + h = t5 ^ t7; + t9 = d | t7; + t11 = t9 & t10; + t14 = t2 ^ h; + g = a ^ t11; + t15 = g ^ t13; + f = t14 ^ t15 + key[4 * 1 + 8] = e + key[4 * 1 + 9] = f + key[4 * 1 + 10] = g + key[4 * 1 + 11] = h + a = key[4 * 2 + 8] + b = key[4 * 2 + 9] + c = key[4 * 2 + 10] + d = key[4 * 2 + 11] + t1 = (~a) % 0x100000000; + t2 = b ^ t1; + t3 = a | t2; + t4 = d | t2; + t5 = c ^ t3; + g = d ^ t5; + t7 = b ^ t4; + t8 = t2 ^ g; + t9 = t5 & t7; + h = t8 ^ t9; + t11 = t5 ^ t7; + f = h ^ t11; + t13 = t8 & t11; + e = t5 ^ t13 + key[4 * 2 + 8] = e + key[4 * 2 + 9] = f + key[4 * 2 + 10] = g + key[4 * 2 + 11] = h + a = key[4 * 3 + 8] + b = key[4 * 3 + 9] + c = key[4 * 3 + 10] + d = key[4 * 3 + 11] + t1 = a ^ d; + t2 = a & d; + t3 = c ^ t1; + t6 = b & t1; + t4 = b ^ t3; + t10 = (~t3) % 0x100000000; + h = t2 ^ t4; + t7 = a ^ t6; + t14 = (~t7) % 0x100000000; + t8 = c | t7; + t11 = t3 ^ t7; + g = t4 ^ t8; + t12 = h & t11; + f = t10 ^ t12; + e = t12 ^ t14 + key[4 * 3 + 8] = e + key[4 * 3 + 9] = f + key[4 * 3 + 10] = g + key[4 * 3 + 11] = h + a = key[4 * 4 + 8] + b = key[4 * 4 + 9] + c = key[4 * 4 + 10] + d = key[4 * 4 + 11] + t1 = (~c) % 0x100000000; + t2 = b ^ c; + t3 = b | t1; + t4 = d ^ t3; + t5 = a & t4; + t7 = a ^ d; + h = t2 ^ t5; + t8 = b ^ t5; + t9 = t2 | t8; + t11 = d & t3; + f = t7 ^ t9; + t12 = t5 ^ f; + t15 = t1 | t4; + t13 = h & t12; + g = t11 ^ t13; + t16 = t12 ^ g; + e = t15 ^ t16 + key[4 * 4 + 8] = e + key[4 * 4 + 9] = f + key[4 * 4 + 10] = g + key[4 * 4 + 11] = h + a = key[4 * 5 + 8] + b = key[4 * 5 + 9] + c = key[4 * 5 + 10] + d = key[4 * 5 + 11] + t1 = (~a) % 0x100000000; + t2 = a ^ d; + t3 = b ^ t2; + t4 = t1 | t2; + t5 = c ^ t4; + f = b ^ t5; + t13 = (~t5) % 0x100000000; + t7 = t2 | f; + t8 = d ^ t7; + t9 = t5 & t8; + g = t3 ^ t9; + t11 = t5 ^ t8; + e = g ^ t11; + t14 = t3 & t11; + h = t13 ^ t14 + key[4 * 5 + 8] = e + key[4 * 5 + 9] = f + key[4 * 5 + 10] = g + key[4 * 5 + 11] = h + a = key[4 * 6 + 8] + b = key[4 * 6 + 9] + c = key[4 * 6 + 10] + d = key[4 * 6 + 11] + t1 = (~a) % 0x100000000; + t2 = a ^ b; + t3 = a ^ d; + t4 = c ^ t1; + t5 = t2 | t3; + e = t4 ^ t5; + t7 = d & e; + t8 = t2 ^ e; + t10 = t1 | e; + f = t7 ^ t8; + t11 = t2 | t7; + t12 = t3 ^ t10; + t14 = b ^ t7; + g = t11 ^ t12; + t15 = f & t12; + h = t14 ^ t15 + key[4 * 6 + 8] = e + key[4 * 6 + 9] = f + key[4 * 6 + 10] = g + key[4 * 6 + 11] = h + a = key[4 * 7 + 8] + b = key[4 * 7 + 9] + c = key[4 * 7 + 10] + d = key[4 * 7 + 11] + t1 = a ^ d; + t2 = d & t1; + t3 = c ^ t2; + t4 = b | t3; + h = t1 ^ t4; + t6 = (~b) % 0x100000000; + t7 = t1 | t6; + e = t3 ^ t7; + t9 = a & e; + t10 = t1 ^ t6; + t11 = t4 & t10; + g = t9 ^ t11; + t13 = a ^ t3; + t14 = t10 & g; + f = t13 ^ t14 + key[4 * 7 + 8] = e + key[4 * 7 + 9] = f + key[4 * 7 + 10] = g + key[4 * 7 + 11] = h + a = key[4 * 8 + 8] + b = key[4 * 8 + 9] + c = key[4 * 8 + 10] + d = key[4 * 8 + 11] + t1 = a ^ c; + t2 = d ^ t1; + t3 = a & t2; + t4 = d ^ t3; + t5 = b & t4; + g = t2 ^ t5; + t7 = a | g; + t8 = b | d; + t11 = a | d; + t9 = t4 & t7; + f = t8 ^ t9; + t12 = b ^ t11; + t13 = g ^ t9; + t15 = t3 ^ t8; + h = t12 ^ t13; + t16 = c & t15; + e = t12 ^ t16 + key[4 * 8 + 8] = e + key[4 * 8 + 9] = f + key[4 * 8 + 10] = g + key[4 * 8 + 11] = h + a = key[4 * 9 + 8] + b = key[4 * 9 + 9] + c = key[4 * 9 + 10] + d = key[4 * 9 + 11] + t1 = (~a) % 0x100000000; + t2 = b ^ d; + t3 = c & t1; + t13 = d | t1; + e = t2 ^ t3; + t5 = c ^ t1; + t6 = c ^ e; + t7 = b & t6; + t10 = e | t5; + h = t5 ^ t7; + t9 = d | t7; + t11 = t9 & t10; + t14 = t2 ^ h; + g = a ^ t11; + t15 = g ^ t13; + f = t14 ^ t15 + key[4 * 9 + 8] = e + key[4 * 9 + 9] = f + key[4 * 9 + 10] = g + key[4 * 9 + 11] = h + a = key[4 * 10 + 8] + b = key[4 * 10 + 9] + c = key[4 * 10 + 10] + d = key[4 * 10 + 11] + t1 = (~a) % 0x100000000; + t2 = b ^ t1; + t3 = a | t2; + t4 = d | t2; + t5 = c ^ t3; + g = d ^ t5; + t7 = b ^ t4; + t8 = t2 ^ g; + t9 = t5 & t7; + h = t8 ^ t9; + t11 = t5 ^ t7; + f = h ^ t11; + t13 = t8 & t11; + e = t5 ^ t13 + key[4 * 10 + 8] = e + key[4 * 10 + 9] = f + key[4 * 10 + 10] = g + key[4 * 10 + 11] = h + a = key[4 * 11 + 8] + b = key[4 * 11 + 9] + c = key[4 * 11 + 10] + d = key[4 * 11 + 11] + t1 = a ^ d; + t2 = a & d; + t3 = c ^ t1; + t6 = b & t1; + t4 = b ^ t3; + t10 = (~t3) % 0x100000000; + h = t2 ^ t4; + t7 = a ^ t6; + t14 = (~t7) % 0x100000000; + t8 = c | t7; + t11 = t3 ^ t7; + g = t4 ^ t8; + t12 = h & t11; + f = t10 ^ t12; + e = t12 ^ t14 + key[4 * 11 + 8] = e + key[4 * 11 + 9] = f + key[4 * 11 + 10] = g + key[4 * 11 + 11] = h + a = key[4 * 12 + 8] + b = key[4 * 12 + 9] + c = key[4 * 12 + 10] + d = key[4 * 12 + 11] + t1 = (~c) % 0x100000000; + t2 = b ^ c; + t3 = b | t1; + t4 = d ^ t3; + t5 = a & t4; + t7 = a ^ d; + h = t2 ^ t5; + t8 = b ^ t5; + t9 = t2 | t8; + t11 = d & t3; + f = t7 ^ t9; + t12 = t5 ^ f; + t15 = t1 | t4; + t13 = h & t12; + g = t11 ^ t13; + t16 = t12 ^ g; + e = t15 ^ t16 + key[4 * 12 + 8] = e + key[4 * 12 + 9] = f + key[4 * 12 + 10] = g + key[4 * 12 + 11] = h + a = key[4 * 13 + 8] + b = key[4 * 13 + 9] + c = key[4 * 13 + 10] + d = key[4 * 13 + 11] + t1 = (~a) % 0x100000000; + t2 = a ^ d; + t3 = b ^ t2; + t4 = t1 | t2; + t5 = c ^ t4; + f = b ^ t5; + t13 = (~t5) % 0x100000000; + t7 = t2 | f; + t8 = d ^ t7; + t9 = t5 & t8; + g = t3 ^ t9; + t11 = t5 ^ t8; + e = g ^ t11; + t14 = t3 & t11; + h = t13 ^ t14 + key[4 * 13 + 8] = e + key[4 * 13 + 9] = f + key[4 * 13 + 10] = g + key[4 * 13 + 11] = h + a = key[4 * 14 + 8] + b = key[4 * 14 + 9] + c = key[4 * 14 + 10] + d = key[4 * 14 + 11] + t1 = (~a) % 0x100000000; + t2 = a ^ b; + t3 = a ^ d; + t4 = c ^ t1; + t5 = t2 | t3; + e = t4 ^ t5; + t7 = d & e; + t8 = t2 ^ e; + t10 = t1 | e; + f = t7 ^ t8; + t11 = t2 | t7; + t12 = t3 ^ t10; + t14 = b ^ t7; + g = t11 ^ t12; + t15 = f & t12; + h = t14 ^ t15 + key[4 * 14 + 8] = e + key[4 * 14 + 9] = f + key[4 * 14 + 10] = g + key[4 * 14 + 11] = h + a = key[4 * 15 + 8] + b = key[4 * 15 + 9] + c = key[4 * 15 + 10] + d = key[4 * 15 + 11] + t1 = a ^ d; + t2 = d & t1; + t3 = c ^ t2; + t4 = b | t3; + h = t1 ^ t4; + t6 = (~b) % 0x100000000; + t7 = t1 | t6; + e = t3 ^ t7; + t9 = a & e; + t10 = t1 ^ t6; + t11 = t4 & t10; + g = t9 ^ t11; + t13 = a ^ t3; + t14 = t10 & g; + f = t13 ^ t14 + key[4 * 15 + 8] = e + key[4 * 15 + 9] = f + key[4 * 15 + 10] = g + key[4 * 15 + 11] = h + a = key[4 * 16 + 8] + b = key[4 * 16 + 9] + c = key[4 * 16 + 10] + d = key[4 * 16 + 11] + t1 = a ^ c; + t2 = d ^ t1; + t3 = a & t2; + t4 = d ^ t3; + t5 = b & t4; + g = t2 ^ t5; + t7 = a | g; + t8 = b | d; + t11 = a | d; + t9 = t4 & t7; + f = t8 ^ t9; + t12 = b ^ t11; + t13 = g ^ t9; + t15 = t3 ^ t8; + h = t12 ^ t13; + t16 = c & t15; + e = t12 ^ t16 + key[4 * 16 + 8] = e + key[4 * 16 + 9] = f + key[4 * 16 + 10] = g + key[4 * 16 + 11] = h + a = key[4 * 17 + 8] + b = key[4 * 17 + 9] + c = key[4 * 17 + 10] + d = key[4 * 17 + 11] + t1 = (~a) % 0x100000000; + t2 = b ^ d; + t3 = c & t1; + t13 = d | t1; + e = t2 ^ t3; + t5 = c ^ t1; + t6 = c ^ e; + t7 = b & t6; + t10 = e | t5; + h = t5 ^ t7; + t9 = d | t7; + t11 = t9 & t10; + t14 = t2 ^ h; + g = a ^ t11; + t15 = g ^ t13; + f = t14 ^ t15 + key[4 * 17 + 8] = e + key[4 * 17 + 9] = f + key[4 * 17 + 10] = g + key[4 * 17 + 11] = h + a = key[4 * 18 + 8] + b = key[4 * 18 + 9] + c = key[4 * 18 + 10] + d = key[4 * 18 + 11] + t1 = (~a) % 0x100000000; + t2 = b ^ t1; + t3 = a | t2; + t4 = d | t2; + t5 = c ^ t3; + g = d ^ t5; + t7 = b ^ t4; + t8 = t2 ^ g; + t9 = t5 & t7; + h = t8 ^ t9; + t11 = t5 ^ t7; + f = h ^ t11; + t13 = t8 & t11; + e = t5 ^ t13 + key[4 * 18 + 8] = e + key[4 * 18 + 9] = f + key[4 * 18 + 10] = g + key[4 * 18 + 11] = h + a = key[4 * 19 + 8] + b = key[4 * 19 + 9] + c = key[4 * 19 + 10] + d = key[4 * 19 + 11] + t1 = a ^ d; + t2 = a & d; + t3 = c ^ t1; + t6 = b & t1; + t4 = b ^ t3; + t10 = (~t3) % 0x100000000; + h = t2 ^ t4; + t7 = a ^ t6; + t14 = (~t7) % 0x100000000; + t8 = c | t7; + t11 = t3 ^ t7; + g = t4 ^ t8; + t12 = h & t11; + f = t10 ^ t12; + e = t12 ^ t14 + key[4 * 19 + 8] = e + key[4 * 19 + 9] = f + key[4 * 19 + 10] = g + key[4 * 19 + 11] = h + a = key[4 * 20 + 8] + b = key[4 * 20 + 9] + c = key[4 * 20 + 10] + d = key[4 * 20 + 11] + t1 = (~c) % 0x100000000; + t2 = b ^ c; + t3 = b | t1; + t4 = d ^ t3; + t5 = a & t4; + t7 = a ^ d; + h = t2 ^ t5; + t8 = b ^ t5; + t9 = t2 | t8; + t11 = d & t3; + f = t7 ^ t9; + t12 = t5 ^ f; + t15 = t1 | t4; + t13 = h & t12; + g = t11 ^ t13; + t16 = t12 ^ g; + e = t15 ^ t16 + key[4 * 20 + 8] = e + key[4 * 20 + 9] = f + key[4 * 20 + 10] = g + key[4 * 20 + 11] = h + a = key[4 * 21 + 8] + b = key[4 * 21 + 9] + c = key[4 * 21 + 10] + d = key[4 * 21 + 11] + t1 = (~a) % 0x100000000; + t2 = a ^ d; + t3 = b ^ t2; + t4 = t1 | t2; + t5 = c ^ t4; + f = b ^ t5; + t13 = (~t5) % 0x100000000; + t7 = t2 | f; + t8 = d ^ t7; + t9 = t5 & t8; + g = t3 ^ t9; + t11 = t5 ^ t8; + e = g ^ t11; + t14 = t3 & t11; + h = t13 ^ t14 + key[4 * 21 + 8] = e + key[4 * 21 + 9] = f + key[4 * 21 + 10] = g + key[4 * 21 + 11] = h + a = key[4 * 22 + 8] + b = key[4 * 22 + 9] + c = key[4 * 22 + 10] + d = key[4 * 22 + 11] + t1 = (~a) % 0x100000000; + t2 = a ^ b; + t3 = a ^ d; + t4 = c ^ t1; + t5 = t2 | t3; + e = t4 ^ t5; + t7 = d & e; + t8 = t2 ^ e; + t10 = t1 | e; + f = t7 ^ t8; + t11 = t2 | t7; + t12 = t3 ^ t10; + t14 = b ^ t7; + g = t11 ^ t12; + t15 = f & t12; + h = t14 ^ t15 + key[4 * 22 + 8] = e + key[4 * 22 + 9] = f + key[4 * 22 + 10] = g + key[4 * 22 + 11] = h + a = key[4 * 23 + 8] + b = key[4 * 23 + 9] + c = key[4 * 23 + 10] + d = key[4 * 23 + 11] + t1 = a ^ d; + t2 = d & t1; + t3 = c ^ t2; + t4 = b | t3; + h = t1 ^ t4; + t6 = (~b) % 0x100000000; + t7 = t1 | t6; + e = t3 ^ t7; + t9 = a & e; + t10 = t1 ^ t6; + t11 = t4 & t10; + g = t9 ^ t11; + t13 = a ^ t3; + t14 = t10 & g; + f = t13 ^ t14 + key[4 * 23 + 8] = e + key[4 * 23 + 9] = f + key[4 * 23 + 10] = g + key[4 * 23 + 11] = h + a = key[4 * 24 + 8] + b = key[4 * 24 + 9] + c = key[4 * 24 + 10] + d = key[4 * 24 + 11] + t1 = a ^ c; + t2 = d ^ t1; + t3 = a & t2; + t4 = d ^ t3; + t5 = b & t4; + g = t2 ^ t5; + t7 = a | g; + t8 = b | d; + t11 = a | d; + t9 = t4 & t7; + f = t8 ^ t9; + t12 = b ^ t11; + t13 = g ^ t9; + t15 = t3 ^ t8; + h = t12 ^ t13; + t16 = c & t15; + e = t12 ^ t16 + key[4 * 24 + 8] = e + key[4 * 24 + 9] = f + key[4 * 24 + 10] = g + key[4 * 24 + 11] = h + a = key[4 * 25 + 8] + b = key[4 * 25 + 9] + c = key[4 * 25 + 10] + d = key[4 * 25 + 11] + t1 = (~a) % 0x100000000; + t2 = b ^ d; + t3 = c & t1; + t13 = d | t1; + e = t2 ^ t3; + t5 = c ^ t1; + t6 = c ^ e; + t7 = b & t6; + t10 = e | t5; + h = t5 ^ t7; + t9 = d | t7; + t11 = t9 & t10; + t14 = t2 ^ h; + g = a ^ t11; + t15 = g ^ t13; + f = t14 ^ t15 + key[4 * 25 + 8] = e + key[4 * 25 + 9] = f + key[4 * 25 + 10] = g + key[4 * 25 + 11] = h + a = key[4 * 26 + 8] + b = key[4 * 26 + 9] + c = key[4 * 26 + 10] + d = key[4 * 26 + 11] + t1 = (~a) % 0x100000000; + t2 = b ^ t1; + t3 = a | t2; + t4 = d | t2; + t5 = c ^ t3; + g = d ^ t5; + t7 = b ^ t4; + t8 = t2 ^ g; + t9 = t5 & t7; + h = t8 ^ t9; + t11 = t5 ^ t7; + f = h ^ t11; + t13 = t8 & t11; + e = t5 ^ t13 + key[4 * 26 + 8] = e + key[4 * 26 + 9] = f + key[4 * 26 + 10] = g + key[4 * 26 + 11] = h + a = key[4 * 27 + 8] + b = key[4 * 27 + 9] + c = key[4 * 27 + 10] + d = key[4 * 27 + 11] + t1 = a ^ d; + t2 = a & d; + t3 = c ^ t1; + t6 = b & t1; + t4 = b ^ t3; + t10 = (~t3) % 0x100000000; + h = t2 ^ t4; + t7 = a ^ t6; + t14 = (~t7) % 0x100000000; + t8 = c | t7; + t11 = t3 ^ t7; + g = t4 ^ t8; + t12 = h & t11; + f = t10 ^ t12; + e = t12 ^ t14 + key[4 * 27 + 8] = e + key[4 * 27 + 9] = f + key[4 * 27 + 10] = g + key[4 * 27 + 11] = h + a = key[4 * 28 + 8] + b = key[4 * 28 + 9] + c = key[4 * 28 + 10] + d = key[4 * 28 + 11] + t1 = (~c) % 0x100000000; + t2 = b ^ c; + t3 = b | t1; + t4 = d ^ t3; + t5 = a & t4; + t7 = a ^ d; + h = t2 ^ t5; + t8 = b ^ t5; + t9 = t2 | t8; + t11 = d & t3; + f = t7 ^ t9; + t12 = t5 ^ f; + t15 = t1 | t4; + t13 = h & t12; + g = t11 ^ t13; + t16 = t12 ^ g; + e = t15 ^ t16 + key[4 * 28 + 8] = e + key[4 * 28 + 9] = f + key[4 * 28 + 10] = g + key[4 * 28 + 11] = h + a = key[4 * 29 + 8] + b = key[4 * 29 + 9] + c = key[4 * 29 + 10] + d = key[4 * 29 + 11] + t1 = (~a) % 0x100000000; + t2 = a ^ d; + t3 = b ^ t2; + t4 = t1 | t2; + t5 = c ^ t4; + f = b ^ t5; + t13 = (~t5) % 0x100000000; + t7 = t2 | f; + t8 = d ^ t7; + t9 = t5 & t8; + g = t3 ^ t9; + t11 = t5 ^ t8; + e = g ^ t11; + t14 = t3 & t11; + h = t13 ^ t14 + key[4 * 29 + 8] = e + key[4 * 29 + 9] = f + key[4 * 29 + 10] = g + key[4 * 29 + 11] = h + a = key[4 * 30 + 8] + b = key[4 * 30 + 9] + c = key[4 * 30 + 10] + d = key[4 * 30 + 11] + t1 = (~a) % 0x100000000; + t2 = a ^ b; + t3 = a ^ d; + t4 = c ^ t1; + t5 = t2 | t3; + e = t4 ^ t5; + t7 = d & e; + t8 = t2 ^ e; + t10 = t1 | e; + f = t7 ^ t8; + t11 = t2 | t7; + t12 = t3 ^ t10; + t14 = b ^ t7; + g = t11 ^ t12; + t15 = f & t12; + h = t14 ^ t15 + key[4 * 30 + 8] = e + key[4 * 30 + 9] = f + key[4 * 30 + 10] = g + key[4 * 30 + 11] = h + a = key[4 * 31 + 8] + b = key[4 * 31 + 9] + c = key[4 * 31 + 10] + d = key[4 * 31 + 11] + t1 = a ^ d; + t2 = d & t1; + t3 = c ^ t2; + t4 = b | t3; + h = t1 ^ t4; + t6 = (~b) % 0x100000000; + t7 = t1 | t6; + e = t3 ^ t7; + t9 = a & e; + t10 = t1 ^ t6; + t11 = t4 & t10; + g = t9 ^ t11; + t13 = a ^ t3; + t14 = t10 & g; + f = t13 ^ t14 + key[4 * 31 + 8] = e + key[4 * 31 + 9] = f + key[4 * 31 + 10] = g + key[4 * 31 + 11] = h + a = key[4 * 32 + 8] + b = key[4 * 32 + 9] + c = key[4 * 32 + 10] + d = key[4 * 32 + 11] + t1 = a ^ c; + t2 = d ^ t1; + t3 = a & t2; + t4 = d ^ t3; + t5 = b & t4; + g = t2 ^ t5; + t7 = a | g; + t8 = b | d; + t11 = a | d; + t9 = t4 & t7; + f = t8 ^ t9; + t12 = b ^ t11; + t13 = g ^ t9; + t15 = t3 ^ t8; + h = t12 ^ t13; + t16 = c & t15; + e = t12 ^ t16 + key[4 * 32 + 8] = e + key[4 * 32 + 9] = f + key[4 * 32 + 10] = g + key[4 * 32 + 11] = h + +def encrypt(key, in_blk): + # serpent_generate.py + a = in_blk[0] + b = in_blk[1] + c = in_blk[2] + d = in_blk[3] + if WORD_BIGENDIAN: + a = byteswap32(a) + b = byteswap32(b) + c = byteswap32(c) + d = byteswap32(d) + e = 0 + f = 0 + g = 0 + h = 0 + t1 = 0 + t2 = 0 + t3 = 0 + t4 = 0 + t5 = 0 + t6 = 0 + t7 = 0 + t8 = 0 + t9 = 0 + t10 = 0 + t11 = 0 + t12 = 0 + t13 = 0 + t14 = 0 + t15 = 0 + t16 = 0 + a ^= key[4 * 0 + 8] + b ^= key[4 * 0 + 9] + c ^= key[4 * 0 + 10] + d ^= key[4 * 0 + 11] + t1 = a ^ d; + t2 = a & d; + t3 = c ^ t1; + t6 = b & t1; + t4 = b ^ t3; + t10 = (~t3) % 0x100000000; + h = t2 ^ t4; + t7 = a ^ t6; + t14 = (~t7) % 0x100000000; + t8 = c | t7; + t11 = t3 ^ t7; + g = t4 ^ t8; + t12 = h & t11; + f = t10 ^ t12; + e = t12 ^ t14 + e = rotl32(e, 13) + g = rotl32(g, 3) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + h = rotl32(h, 7) + f = rotl32(f, 1) + e ^= f ^ h + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e = rotl32(e, 5) + g = rotl32(g, 22) + e ^= key[4 * 1 + 8] + f ^= key[4 * 1 + 9] + g ^= key[4 * 1 + 10] + h ^= key[4 * 1 + 11] + t1 = (~e) % 0x100000000; + t2 = f ^ t1; + t3 = e | t2; + t4 = h | t2; + t5 = g ^ t3; + c = h ^ t5; + t7 = f ^ t4; + t8 = t2 ^ c; + t9 = t5 & t7; + d = t8 ^ t9; + t11 = t5 ^ t7; + b = d ^ t11; + t13 = t8 & t11; + a = t5 ^ t13 + a = rotl32(a, 13) + c = rotl32(c, 3) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + d = rotl32(d, 7) + b = rotl32(b, 1) + a ^= b ^ d + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a = rotl32(a, 5) + c = rotl32(c, 22) + a ^= key[4 * 2 + 8] + b ^= key[4 * 2 + 9] + c ^= key[4 * 2 + 10] + d ^= key[4 * 2 + 11] + t1 = (~a) % 0x100000000; + t2 = b ^ d; + t3 = c & t1; + t13 = d | t1; + e = t2 ^ t3; + t5 = c ^ t1; + t6 = c ^ e; + t7 = b & t6; + t10 = e | t5; + h = t5 ^ t7; + t9 = d | t7; + t11 = t9 & t10; + t14 = t2 ^ h; + g = a ^ t11; + t15 = g ^ t13; + f = t14 ^ t15 + e = rotl32(e, 13) + g = rotl32(g, 3) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + h = rotl32(h, 7) + f = rotl32(f, 1) + e ^= f ^ h + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e = rotl32(e, 5) + g = rotl32(g, 22) + e ^= key[4 * 3 + 8] + f ^= key[4 * 3 + 9] + g ^= key[4 * 3 + 10] + h ^= key[4 * 3 + 11] + t1 = e ^ g; + t2 = h ^ t1; + t3 = e & t2; + t4 = h ^ t3; + t5 = f & t4; + c = t2 ^ t5; + t7 = e | c; + t8 = f | h; + t11 = e | h; + t9 = t4 & t7; + b = t8 ^ t9; + t12 = f ^ t11; + t13 = c ^ t9; + t15 = t3 ^ t8; + d = t12 ^ t13; + t16 = g & t15; + a = t12 ^ t16 + a = rotl32(a, 13) + c = rotl32(c, 3) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + d = rotl32(d, 7) + b = rotl32(b, 1) + a ^= b ^ d + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a = rotl32(a, 5) + c = rotl32(c, 22) + a ^= key[4 * 4 + 8] + b ^= key[4 * 4 + 9] + c ^= key[4 * 4 + 10] + d ^= key[4 * 4 + 11] + t1 = a ^ d; + t2 = d & t1; + t3 = c ^ t2; + t4 = b | t3; + h = t1 ^ t4; + t6 = (~b) % 0x100000000; + t7 = t1 | t6; + e = t3 ^ t7; + t9 = a & e; + t10 = t1 ^ t6; + t11 = t4 & t10; + g = t9 ^ t11; + t13 = a ^ t3; + t14 = t10 & g; + f = t13 ^ t14 + e = rotl32(e, 13) + g = rotl32(g, 3) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + h = rotl32(h, 7) + f = rotl32(f, 1) + e ^= f ^ h + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e = rotl32(e, 5) + g = rotl32(g, 22) + e ^= key[4 * 5 + 8] + f ^= key[4 * 5 + 9] + g ^= key[4 * 5 + 10] + h ^= key[4 * 5 + 11] + t1 = (~e) % 0x100000000; + t2 = e ^ f; + t3 = e ^ h; + t4 = g ^ t1; + t5 = t2 | t3; + a = t4 ^ t5; + t7 = h & a; + t8 = t2 ^ a; + t10 = t1 | a; + b = t7 ^ t8; + t11 = t2 | t7; + t12 = t3 ^ t10; + t14 = f ^ t7; + c = t11 ^ t12; + t15 = b & t12; + d = t14 ^ t15 + a = rotl32(a, 13) + c = rotl32(c, 3) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + d = rotl32(d, 7) + b = rotl32(b, 1) + a ^= b ^ d + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a = rotl32(a, 5) + c = rotl32(c, 22) + a ^= key[4 * 6 + 8] + b ^= key[4 * 6 + 9] + c ^= key[4 * 6 + 10] + d ^= key[4 * 6 + 11] + t1 = (~a) % 0x100000000; + t2 = a ^ d; + t3 = b ^ t2; + t4 = t1 | t2; + t5 = c ^ t4; + f = b ^ t5; + t13 = (~t5) % 0x100000000; + t7 = t2 | f; + t8 = d ^ t7; + t9 = t5 & t8; + g = t3 ^ t9; + t11 = t5 ^ t8; + e = g ^ t11; + t14 = t3 & t11; + h = t13 ^ t14 + e = rotl32(e, 13) + g = rotl32(g, 3) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + h = rotl32(h, 7) + f = rotl32(f, 1) + e ^= f ^ h + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e = rotl32(e, 5) + g = rotl32(g, 22) + e ^= key[4 * 7 + 8] + f ^= key[4 * 7 + 9] + g ^= key[4 * 7 + 10] + h ^= key[4 * 7 + 11] + t1 = (~g) % 0x100000000; + t2 = f ^ g; + t3 = f | t1; + t4 = h ^ t3; + t5 = e & t4; + t7 = e ^ h; + d = t2 ^ t5; + t8 = f ^ t5; + t9 = t2 | t8; + t11 = h & t3; + b = t7 ^ t9; + t12 = t5 ^ b; + t15 = t1 | t4; + t13 = d & t12; + c = t11 ^ t13; + t16 = t12 ^ c; + a = t15 ^ t16 + a = rotl32(a, 13) + c = rotl32(c, 3) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + d = rotl32(d, 7) + b = rotl32(b, 1) + a ^= b ^ d + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a = rotl32(a, 5) + c = rotl32(c, 22) + a ^= key[4 * 8 + 8] + b ^= key[4 * 8 + 9] + c ^= key[4 * 8 + 10] + d ^= key[4 * 8 + 11] + t1 = a ^ d; + t2 = a & d; + t3 = c ^ t1; + t6 = b & t1; + t4 = b ^ t3; + t10 = (~t3) % 0x100000000; + h = t2 ^ t4; + t7 = a ^ t6; + t14 = (~t7) % 0x100000000; + t8 = c | t7; + t11 = t3 ^ t7; + g = t4 ^ t8; + t12 = h & t11; + f = t10 ^ t12; + e = t12 ^ t14 + e = rotl32(e, 13) + g = rotl32(g, 3) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + h = rotl32(h, 7) + f = rotl32(f, 1) + e ^= f ^ h + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e = rotl32(e, 5) + g = rotl32(g, 22) + e ^= key[4 * 9 + 8] + f ^= key[4 * 9 + 9] + g ^= key[4 * 9 + 10] + h ^= key[4 * 9 + 11] + t1 = (~e) % 0x100000000; + t2 = f ^ t1; + t3 = e | t2; + t4 = h | t2; + t5 = g ^ t3; + c = h ^ t5; + t7 = f ^ t4; + t8 = t2 ^ c; + t9 = t5 & t7; + d = t8 ^ t9; + t11 = t5 ^ t7; + b = d ^ t11; + t13 = t8 & t11; + a = t5 ^ t13 + a = rotl32(a, 13) + c = rotl32(c, 3) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + d = rotl32(d, 7) + b = rotl32(b, 1) + a ^= b ^ d + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a = rotl32(a, 5) + c = rotl32(c, 22) + a ^= key[4 * 10 + 8] + b ^= key[4 * 10 + 9] + c ^= key[4 * 10 + 10] + d ^= key[4 * 10 + 11] + t1 = (~a) % 0x100000000; + t2 = b ^ d; + t3 = c & t1; + t13 = d | t1; + e = t2 ^ t3; + t5 = c ^ t1; + t6 = c ^ e; + t7 = b & t6; + t10 = e | t5; + h = t5 ^ t7; + t9 = d | t7; + t11 = t9 & t10; + t14 = t2 ^ h; + g = a ^ t11; + t15 = g ^ t13; + f = t14 ^ t15 + e = rotl32(e, 13) + g = rotl32(g, 3) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + h = rotl32(h, 7) + f = rotl32(f, 1) + e ^= f ^ h + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e = rotl32(e, 5) + g = rotl32(g, 22) + e ^= key[4 * 11 + 8] + f ^= key[4 * 11 + 9] + g ^= key[4 * 11 + 10] + h ^= key[4 * 11 + 11] + t1 = e ^ g; + t2 = h ^ t1; + t3 = e & t2; + t4 = h ^ t3; + t5 = f & t4; + c = t2 ^ t5; + t7 = e | c; + t8 = f | h; + t11 = e | h; + t9 = t4 & t7; + b = t8 ^ t9; + t12 = f ^ t11; + t13 = c ^ t9; + t15 = t3 ^ t8; + d = t12 ^ t13; + t16 = g & t15; + a = t12 ^ t16 + a = rotl32(a, 13) + c = rotl32(c, 3) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + d = rotl32(d, 7) + b = rotl32(b, 1) + a ^= b ^ d + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a = rotl32(a, 5) + c = rotl32(c, 22) + a ^= key[4 * 12 + 8] + b ^= key[4 * 12 + 9] + c ^= key[4 * 12 + 10] + d ^= key[4 * 12 + 11] + t1 = a ^ d; + t2 = d & t1; + t3 = c ^ t2; + t4 = b | t3; + h = t1 ^ t4; + t6 = (~b) % 0x100000000; + t7 = t1 | t6; + e = t3 ^ t7; + t9 = a & e; + t10 = t1 ^ t6; + t11 = t4 & t10; + g = t9 ^ t11; + t13 = a ^ t3; + t14 = t10 & g; + f = t13 ^ t14 + e = rotl32(e, 13) + g = rotl32(g, 3) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + h = rotl32(h, 7) + f = rotl32(f, 1) + e ^= f ^ h + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e = rotl32(e, 5) + g = rotl32(g, 22) + e ^= key[4 * 13 + 8] + f ^= key[4 * 13 + 9] + g ^= key[4 * 13 + 10] + h ^= key[4 * 13 + 11] + t1 = (~e) % 0x100000000; + t2 = e ^ f; + t3 = e ^ h; + t4 = g ^ t1; + t5 = t2 | t3; + a = t4 ^ t5; + t7 = h & a; + t8 = t2 ^ a; + t10 = t1 | a; + b = t7 ^ t8; + t11 = t2 | t7; + t12 = t3 ^ t10; + t14 = f ^ t7; + c = t11 ^ t12; + t15 = b & t12; + d = t14 ^ t15 + a = rotl32(a, 13) + c = rotl32(c, 3) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + d = rotl32(d, 7) + b = rotl32(b, 1) + a ^= b ^ d + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a = rotl32(a, 5) + c = rotl32(c, 22) + a ^= key[4 * 14 + 8] + b ^= key[4 * 14 + 9] + c ^= key[4 * 14 + 10] + d ^= key[4 * 14 + 11] + t1 = (~a) % 0x100000000; + t2 = a ^ d; + t3 = b ^ t2; + t4 = t1 | t2; + t5 = c ^ t4; + f = b ^ t5; + t13 = (~t5) % 0x100000000; + t7 = t2 | f; + t8 = d ^ t7; + t9 = t5 & t8; + g = t3 ^ t9; + t11 = t5 ^ t8; + e = g ^ t11; + t14 = t3 & t11; + h = t13 ^ t14 + e = rotl32(e, 13) + g = rotl32(g, 3) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + h = rotl32(h, 7) + f = rotl32(f, 1) + e ^= f ^ h + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e = rotl32(e, 5) + g = rotl32(g, 22) + e ^= key[4 * 15 + 8] + f ^= key[4 * 15 + 9] + g ^= key[4 * 15 + 10] + h ^= key[4 * 15 + 11] + t1 = (~g) % 0x100000000; + t2 = f ^ g; + t3 = f | t1; + t4 = h ^ t3; + t5 = e & t4; + t7 = e ^ h; + d = t2 ^ t5; + t8 = f ^ t5; + t9 = t2 | t8; + t11 = h & t3; + b = t7 ^ t9; + t12 = t5 ^ b; + t15 = t1 | t4; + t13 = d & t12; + c = t11 ^ t13; + t16 = t12 ^ c; + a = t15 ^ t16 + a = rotl32(a, 13) + c = rotl32(c, 3) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + d = rotl32(d, 7) + b = rotl32(b, 1) + a ^= b ^ d + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a = rotl32(a, 5) + c = rotl32(c, 22) + a ^= key[4 * 16 + 8] + b ^= key[4 * 16 + 9] + c ^= key[4 * 16 + 10] + d ^= key[4 * 16 + 11] + t1 = a ^ d; + t2 = a & d; + t3 = c ^ t1; + t6 = b & t1; + t4 = b ^ t3; + t10 = (~t3) % 0x100000000; + h = t2 ^ t4; + t7 = a ^ t6; + t14 = (~t7) % 0x100000000; + t8 = c | t7; + t11 = t3 ^ t7; + g = t4 ^ t8; + t12 = h & t11; + f = t10 ^ t12; + e = t12 ^ t14 + e = rotl32(e, 13) + g = rotl32(g, 3) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + h = rotl32(h, 7) + f = rotl32(f, 1) + e ^= f ^ h + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e = rotl32(e, 5) + g = rotl32(g, 22) + e ^= key[4 * 17 + 8] + f ^= key[4 * 17 + 9] + g ^= key[4 * 17 + 10] + h ^= key[4 * 17 + 11] + t1 = (~e) % 0x100000000; + t2 = f ^ t1; + t3 = e | t2; + t4 = h | t2; + t5 = g ^ t3; + c = h ^ t5; + t7 = f ^ t4; + t8 = t2 ^ c; + t9 = t5 & t7; + d = t8 ^ t9; + t11 = t5 ^ t7; + b = d ^ t11; + t13 = t8 & t11; + a = t5 ^ t13 + a = rotl32(a, 13) + c = rotl32(c, 3) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + d = rotl32(d, 7) + b = rotl32(b, 1) + a ^= b ^ d + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a = rotl32(a, 5) + c = rotl32(c, 22) + a ^= key[4 * 18 + 8] + b ^= key[4 * 18 + 9] + c ^= key[4 * 18 + 10] + d ^= key[4 * 18 + 11] + t1 = (~a) % 0x100000000; + t2 = b ^ d; + t3 = c & t1; + t13 = d | t1; + e = t2 ^ t3; + t5 = c ^ t1; + t6 = c ^ e; + t7 = b & t6; + t10 = e | t5; + h = t5 ^ t7; + t9 = d | t7; + t11 = t9 & t10; + t14 = t2 ^ h; + g = a ^ t11; + t15 = g ^ t13; + f = t14 ^ t15 + e = rotl32(e, 13) + g = rotl32(g, 3) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + h = rotl32(h, 7) + f = rotl32(f, 1) + e ^= f ^ h + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e = rotl32(e, 5) + g = rotl32(g, 22) + e ^= key[4 * 19 + 8] + f ^= key[4 * 19 + 9] + g ^= key[4 * 19 + 10] + h ^= key[4 * 19 + 11] + t1 = e ^ g; + t2 = h ^ t1; + t3 = e & t2; + t4 = h ^ t3; + t5 = f & t4; + c = t2 ^ t5; + t7 = e | c; + t8 = f | h; + t11 = e | h; + t9 = t4 & t7; + b = t8 ^ t9; + t12 = f ^ t11; + t13 = c ^ t9; + t15 = t3 ^ t8; + d = t12 ^ t13; + t16 = g & t15; + a = t12 ^ t16 + a = rotl32(a, 13) + c = rotl32(c, 3) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + d = rotl32(d, 7) + b = rotl32(b, 1) + a ^= b ^ d + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a = rotl32(a, 5) + c = rotl32(c, 22) + a ^= key[4 * 20 + 8] + b ^= key[4 * 20 + 9] + c ^= key[4 * 20 + 10] + d ^= key[4 * 20 + 11] + t1 = a ^ d; + t2 = d & t1; + t3 = c ^ t2; + t4 = b | t3; + h = t1 ^ t4; + t6 = (~b) % 0x100000000; + t7 = t1 | t6; + e = t3 ^ t7; + t9 = a & e; + t10 = t1 ^ t6; + t11 = t4 & t10; + g = t9 ^ t11; + t13 = a ^ t3; + t14 = t10 & g; + f = t13 ^ t14 + e = rotl32(e, 13) + g = rotl32(g, 3) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + h = rotl32(h, 7) + f = rotl32(f, 1) + e ^= f ^ h + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e = rotl32(e, 5) + g = rotl32(g, 22) + e ^= key[4 * 21 + 8] + f ^= key[4 * 21 + 9] + g ^= key[4 * 21 + 10] + h ^= key[4 * 21 + 11] + t1 = (~e) % 0x100000000; + t2 = e ^ f; + t3 = e ^ h; + t4 = g ^ t1; + t5 = t2 | t3; + a = t4 ^ t5; + t7 = h & a; + t8 = t2 ^ a; + t10 = t1 | a; + b = t7 ^ t8; + t11 = t2 | t7; + t12 = t3 ^ t10; + t14 = f ^ t7; + c = t11 ^ t12; + t15 = b & t12; + d = t14 ^ t15 + a = rotl32(a, 13) + c = rotl32(c, 3) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + d = rotl32(d, 7) + b = rotl32(b, 1) + a ^= b ^ d + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a = rotl32(a, 5) + c = rotl32(c, 22) + a ^= key[4 * 22 + 8] + b ^= key[4 * 22 + 9] + c ^= key[4 * 22 + 10] + d ^= key[4 * 22 + 11] + t1 = (~a) % 0x100000000; + t2 = a ^ d; + t3 = b ^ t2; + t4 = t1 | t2; + t5 = c ^ t4; + f = b ^ t5; + t13 = (~t5) % 0x100000000; + t7 = t2 | f; + t8 = d ^ t7; + t9 = t5 & t8; + g = t3 ^ t9; + t11 = t5 ^ t8; + e = g ^ t11; + t14 = t3 & t11; + h = t13 ^ t14 + e = rotl32(e, 13) + g = rotl32(g, 3) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + h = rotl32(h, 7) + f = rotl32(f, 1) + e ^= f ^ h + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e = rotl32(e, 5) + g = rotl32(g, 22) + e ^= key[4 * 23 + 8] + f ^= key[4 * 23 + 9] + g ^= key[4 * 23 + 10] + h ^= key[4 * 23 + 11] + t1 = (~g) % 0x100000000; + t2 = f ^ g; + t3 = f | t1; + t4 = h ^ t3; + t5 = e & t4; + t7 = e ^ h; + d = t2 ^ t5; + t8 = f ^ t5; + t9 = t2 | t8; + t11 = h & t3; + b = t7 ^ t9; + t12 = t5 ^ b; + t15 = t1 | t4; + t13 = d & t12; + c = t11 ^ t13; + t16 = t12 ^ c; + a = t15 ^ t16 + a = rotl32(a, 13) + c = rotl32(c, 3) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + d = rotl32(d, 7) + b = rotl32(b, 1) + a ^= b ^ d + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a = rotl32(a, 5) + c = rotl32(c, 22) + a ^= key[4 * 24 + 8] + b ^= key[4 * 24 + 9] + c ^= key[4 * 24 + 10] + d ^= key[4 * 24 + 11] + t1 = a ^ d; + t2 = a & d; + t3 = c ^ t1; + t6 = b & t1; + t4 = b ^ t3; + t10 = (~t3) % 0x100000000; + h = t2 ^ t4; + t7 = a ^ t6; + t14 = (~t7) % 0x100000000; + t8 = c | t7; + t11 = t3 ^ t7; + g = t4 ^ t8; + t12 = h & t11; + f = t10 ^ t12; + e = t12 ^ t14 + e = rotl32(e, 13) + g = rotl32(g, 3) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + h = rotl32(h, 7) + f = rotl32(f, 1) + e ^= f ^ h + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e = rotl32(e, 5) + g = rotl32(g, 22) + e ^= key[4 * 25 + 8] + f ^= key[4 * 25 + 9] + g ^= key[4 * 25 + 10] + h ^= key[4 * 25 + 11] + t1 = (~e) % 0x100000000; + t2 = f ^ t1; + t3 = e | t2; + t4 = h | t2; + t5 = g ^ t3; + c = h ^ t5; + t7 = f ^ t4; + t8 = t2 ^ c; + t9 = t5 & t7; + d = t8 ^ t9; + t11 = t5 ^ t7; + b = d ^ t11; + t13 = t8 & t11; + a = t5 ^ t13 + a = rotl32(a, 13) + c = rotl32(c, 3) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + d = rotl32(d, 7) + b = rotl32(b, 1) + a ^= b ^ d + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a = rotl32(a, 5) + c = rotl32(c, 22) + a ^= key[4 * 26 + 8] + b ^= key[4 * 26 + 9] + c ^= key[4 * 26 + 10] + d ^= key[4 * 26 + 11] + t1 = (~a) % 0x100000000; + t2 = b ^ d; + t3 = c & t1; + t13 = d | t1; + e = t2 ^ t3; + t5 = c ^ t1; + t6 = c ^ e; + t7 = b & t6; + t10 = e | t5; + h = t5 ^ t7; + t9 = d | t7; + t11 = t9 & t10; + t14 = t2 ^ h; + g = a ^ t11; + t15 = g ^ t13; + f = t14 ^ t15 + e = rotl32(e, 13) + g = rotl32(g, 3) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + h = rotl32(h, 7) + f = rotl32(f, 1) + e ^= f ^ h + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e = rotl32(e, 5) + g = rotl32(g, 22) + e ^= key[4 * 27 + 8] + f ^= key[4 * 27 + 9] + g ^= key[4 * 27 + 10] + h ^= key[4 * 27 + 11] + t1 = e ^ g; + t2 = h ^ t1; + t3 = e & t2; + t4 = h ^ t3; + t5 = f & t4; + c = t2 ^ t5; + t7 = e | c; + t8 = f | h; + t11 = e | h; + t9 = t4 & t7; + b = t8 ^ t9; + t12 = f ^ t11; + t13 = c ^ t9; + t15 = t3 ^ t8; + d = t12 ^ t13; + t16 = g & t15; + a = t12 ^ t16 + a = rotl32(a, 13) + c = rotl32(c, 3) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + d = rotl32(d, 7) + b = rotl32(b, 1) + a ^= b ^ d + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a = rotl32(a, 5) + c = rotl32(c, 22) + a ^= key[4 * 28 + 8] + b ^= key[4 * 28 + 9] + c ^= key[4 * 28 + 10] + d ^= key[4 * 28 + 11] + t1 = a ^ d; + t2 = d & t1; + t3 = c ^ t2; + t4 = b | t3; + h = t1 ^ t4; + t6 = (~b) % 0x100000000; + t7 = t1 | t6; + e = t3 ^ t7; + t9 = a & e; + t10 = t1 ^ t6; + t11 = t4 & t10; + g = t9 ^ t11; + t13 = a ^ t3; + t14 = t10 & g; + f = t13 ^ t14 + e = rotl32(e, 13) + g = rotl32(g, 3) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + h = rotl32(h, 7) + f = rotl32(f, 1) + e ^= f ^ h + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e = rotl32(e, 5) + g = rotl32(g, 22) + e ^= key[4 * 29 + 8] + f ^= key[4 * 29 + 9] + g ^= key[4 * 29 + 10] + h ^= key[4 * 29 + 11] + t1 = (~e) % 0x100000000; + t2 = e ^ f; + t3 = e ^ h; + t4 = g ^ t1; + t5 = t2 | t3; + a = t4 ^ t5; + t7 = h & a; + t8 = t2 ^ a; + t10 = t1 | a; + b = t7 ^ t8; + t11 = t2 | t7; + t12 = t3 ^ t10; + t14 = f ^ t7; + c = t11 ^ t12; + t15 = b & t12; + d = t14 ^ t15 + a = rotl32(a, 13) + c = rotl32(c, 3) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + d = rotl32(d, 7) + b = rotl32(b, 1) + a ^= b ^ d + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a = rotl32(a, 5) + c = rotl32(c, 22) + a ^= key[4 * 30 + 8] + b ^= key[4 * 30 + 9] + c ^= key[4 * 30 + 10] + d ^= key[4 * 30 + 11] + t1 = (~a) % 0x100000000; + t2 = a ^ d; + t3 = b ^ t2; + t4 = t1 | t2; + t5 = c ^ t4; + f = b ^ t5; + t13 = (~t5) % 0x100000000; + t7 = t2 | f; + t8 = d ^ t7; + t9 = t5 & t8; + g = t3 ^ t9; + t11 = t5 ^ t8; + e = g ^ t11; + t14 = t3 & t11; + h = t13 ^ t14 + e = rotl32(e, 13) + g = rotl32(g, 3) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + h = rotl32(h, 7) + f = rotl32(f, 1) + e ^= f ^ h + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e = rotl32(e, 5) + g = rotl32(g, 22) + e ^= key[4 * 31 + 8] + f ^= key[4 * 31 + 9] + g ^= key[4 * 31 + 10] + h ^= key[4 * 31 + 11] + t1 = (~g) % 0x100000000; + t2 = f ^ g; + t3 = f | t1; + t4 = h ^ t3; + t5 = e & t4; + t7 = e ^ h; + d = t2 ^ t5; + t8 = f ^ t5; + t9 = t2 | t8; + t11 = h & t3; + b = t7 ^ t9; + t12 = t5 ^ b; + t15 = t1 | t4; + t13 = d & t12; + c = t11 ^ t13; + t16 = t12 ^ c; + a = t15 ^ t16 + a ^= key[4 * 32 + 8] + b ^= key[4 * 32 + 9] + c ^= key[4 * 32 + 10] + d ^= key[4 * 32 + 11] + if WORD_BIGENDIAN: + a = byteswap32(a) + b = byteswap32(b) + c = byteswap32(c) + d = byteswap32(d) + in_blk[0] = a + in_blk[1] = b + in_blk[2] = c + in_blk[3] = d + +def decrypt(key, in_blk): + # serpent_generate.py + a = in_blk[0] + b = in_blk[1] + c = in_blk[2] + d = in_blk[3] + if WORD_BIGENDIAN: + a = byteswap32(a) + b = byteswap32(b) + c = byteswap32(c) + d = byteswap32(d) + e = 0 + f = 0 + g = 0 + h = 0 + t1 = 0 + t2 = 0 + t3 = 0 + t4 = 0 + t5 = 0 + t6 = 0 + t7 = 0 + t8 = 0 + t9 = 0 + t10 = 0 + t11 = 0 + t12 = 0 + t13 = 0 + t14 = 0 + t15 = 0 + t16 = 0 + a ^= key[4 * 32 + 8] + b ^= key[4 * 32 + 9] + c ^= key[4 * 32 + 10] + d ^= key[4 * 32 + 11] + t1 = a & b; + t2 = a | b; + t3 = c | t1; + t4 = d & t2; + h = t3 ^ t4; + t6 = (~d) % 0x100000000; + t7 = b ^ t4; + t8 = h ^ t6; + t11 = c ^ t7; + t9 = t7 | t8; + f = a ^ t9; + t12 = d | f; + e = t11 ^ t12; + t14 = a & h; + t15 = t3 ^ f; + t16 = e ^ t14; + g = t15 ^ t16 + e ^= key[4 * 31 + 8] + f ^= key[4 * 31 + 9] + g ^= key[4 * 31 + 10] + h ^= key[4 * 31 + 11] + g = rotr32(g, 22) + e = rotr32(e, 5) + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e ^= f ^ h + h = rotr32(h, 7) + f = rotr32(f, 1) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + g = rotr32(g, 3) + e = rotr32(e, 13) + t1 = (~e) % 0x100000000; + t2 = e ^ f; + t3 = g ^ t2; + t4 = g | t1; + t5 = h ^ t4; + t13 = h & t1; + b = t3 ^ t5; + t7 = t3 & t5; + t8 = t2 ^ t7; + t9 = f | t8; + d = t5 ^ t9; + t11 = f | d; + a = t8 ^ t11; + t14 = t3 ^ t11; + c = t13 ^ t14 + a ^= key[4 * 30 + 8] + b ^= key[4 * 30 + 9] + c ^= key[4 * 30 + 10] + d ^= key[4 * 30 + 11] + c = rotr32(c, 22) + a = rotr32(a, 5) + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a ^= b ^ d + d = rotr32(d, 7) + b = rotr32(b, 1) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + c = rotr32(c, 3) + a = rotr32(a, 13) + t1 = (~c) % 0x100000000; + t2 = b & t1; + t3 = d ^ t2; + t4 = a & t3; + t5 = b ^ t1; + h = t4 ^ t5; + t7 = b | h; + t8 = a & t7; + f = t3 ^ t8; + t10 = a | d; + t11 = t1 ^ t7; + e = t10 ^ t11; + t13 = a ^ c; + t14 = b & t10; + t15 = t4 | t13; + g = t14 ^ t15 + e ^= key[4 * 29 + 8] + f ^= key[4 * 29 + 9] + g ^= key[4 * 29 + 10] + h ^= key[4 * 29 + 11] + g = rotr32(g, 22) + e = rotr32(e, 5) + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e ^= f ^ h + h = rotr32(h, 7) + f = rotr32(f, 1) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + g = rotr32(g, 3) + e = rotr32(e, 13) + t1 = g ^ h; + t2 = g | h; + t3 = f ^ t2; + t4 = e & t3; + b = t1 ^ t4; + t6 = e ^ h; + t7 = f | h; + t8 = t6 & t7; + d = t3 ^ t8; + t10 = (~e) % 0x100000000; + t11 = g ^ d; + t12 = t10 | t11; + a = t3 ^ t12; + t14 = g | t4; + t15 = t7 ^ t14; + t16 = d | t10; + c = t15 ^ t16 + a ^= key[4 * 28 + 8] + b ^= key[4 * 28 + 9] + c ^= key[4 * 28 + 10] + d ^= key[4 * 28 + 11] + c = rotr32(c, 22) + a = rotr32(a, 5) + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a ^= b ^ d + d = rotr32(d, 7) + b = rotr32(b, 1) + + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + c = rotr32(c, 3) + a = rotr32(a, 13) + t1 = b ^ c; + t2 = b | c; + t3 = a ^ c; + t7 = a ^ d; + t4 = t2 ^ t3; + t5 = d | t4; + t9 = t2 ^ t7; + e = t1 ^ t5; + t8 = t1 | t5; + t11 = a & t4; + g = t8 ^ t9; + t12 = e | t9; + f = t11 ^ t12; + t14 = a & g; + t15 = t2 ^ t14; + t16 = e & t15; + h = t4 ^ t16 + e ^= key[4 * 27 + 8] + f ^= key[4 * 27 + 9] + g ^= key[4 * 27 + 10] + h ^= key[4 * 27 + 11] + g = rotr32(g, 22) + e = rotr32(e, 5) + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e ^= f ^ h + h = rotr32(h, 7) + f = rotr32(f, 1) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + g = rotr32(g, 3) + e = rotr32(e, 13) + t1 = f ^ h; + t2 = (~t1) % 0x100000000; + t3 = e ^ g; + t4 = g ^ t1; + t7 = e | t2; + t5 = f & t4; + t8 = h ^ t7; + t11 = (~t4) % 0x100000000; + a = t3 ^ t5; + t9 = t3 | t8; + t14 = h & t11; + d = t1 ^ t9; + t12 = a | d; + b = t11 ^ t12; + t15 = t3 ^ t12; + c = t14 ^ t15 + a ^= key[4 * 26 + 8] + b ^= key[4 * 26 + 9] + c ^= key[4 * 26 + 10] + d ^= key[4 * 26 + 11] + c = rotr32(c, 22) + a = rotr32(a, 5) + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a ^= b ^ d + d = rotr32(d, 7) + b = rotr32(b, 1) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + c = rotr32(c, 3) + a = rotr32(a, 13) + t1 = a ^ d; + t2 = a & b; + t3 = b ^ c; + t4 = a ^ t3; + t5 = b | d; + t7 = c | t1; + h = t4 ^ t5; + t8 = b ^ t7; + t11 = (~t2) % 0x100000000; + t9 = t4 & t8; + f = t1 ^ t9; + t13 = t9 ^ t11; + t12 = h & f; + g = t12 ^ t13; + t15 = a & d; + t16 = c ^ t13; + e = t15 ^ t16 + e ^= key[4 * 25 + 8] + f ^= key[4 * 25 + 9] + g ^= key[4 * 25 + 10] + h ^= key[4 * 25 + 11] + g = rotr32(g, 22) + e = rotr32(e, 5) + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e ^= f ^ h + h = rotr32(h, 7) + f = rotr32(f, 1) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + g = rotr32(g, 3) + e = rotr32(e, 13) + t1 = (~e) % 0x100000000 + t2 = e ^ f + t3 = t1 | t2 + t4 = h ^ t3 + t7 = h & t2 + t5 = g ^ t4 + t8 = t1 ^ t7 + c = t2 ^ t5 + t11 = e & t4 + t9 = c & t8 + t14 = t5 ^ t8 + b = t4 ^ t9 + t12 = t5 | b + d = t11 ^ t12 + a = d ^ t14 + a ^= key[4 * 24 + 8] + b ^= key[4 * 24 + 9] + c ^= key[4 * 24 + 10] + d ^= key[4 * 24 + 11] + c = rotr32(c, 22) + a = rotr32(a, 5) + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a ^= b ^ d + d = rotr32(d, 7) + b = rotr32(b, 1) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + c = rotr32(c, 3) + a = rotr32(a, 13) + t1 = a & b; + t2 = a | b; + t3 = c | t1; + t4 = d & t2; + h = t3 ^ t4; + t6 = (~d) % 0x100000000; + t7 = b ^ t4; + t8 = h ^ t6; + t11 = c ^ t7; + t9 = t7 | t8; + f = a ^ t9; + t12 = d | f; + e = t11 ^ t12; + t14 = a & h; + t15 = t3 ^ f; + t16 = e ^ t14; + g = t15 ^ t16 + e ^= key[4 * 23 + 8] + f ^= key[4 * 23 + 9] + g ^= key[4 * 23 + 10] + h ^= key[4 * 23 + 11] + g = rotr32(g, 22) + e = rotr32(e, 5) + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e ^= f ^ h + h = rotr32(h, 7) + f = rotr32(f, 1) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + g = rotr32(g, 3) + e = rotr32(e, 13) + t1 = (~e) % 0x100000000; + t2 = e ^ f; + t3 = g ^ t2; + t4 = g | t1; + t5 = h ^ t4; + t13 = h & t1; + b = t3 ^ t5; + t7 = t3 & t5; + t8 = t2 ^ t7; + t9 = f | t8; + d = t5 ^ t9; + t11 = f | d; + a = t8 ^ t11; + t14 = t3 ^ t11; + c = t13 ^ t14 + a ^= key[4 * 22 + 8] + b ^= key[4 * 22 + 9] + c ^= key[4 * 22 + 10] + d ^= key[4 * 22 + 11] + c = rotr32(c, 22) + a = rotr32(a, 5) + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a ^= b ^ d + d = rotr32(d, 7) + b = rotr32(b, 1) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + c = rotr32(c, 3) + a = rotr32(a, 13) + t1 = (~c) % 0x100000000; + t2 = b & t1; + t3 = d ^ t2; + t4 = a & t3; + t5 = b ^ t1; + h = t4 ^ t5; + t7 = b | h; + t8 = a & t7; + f = t3 ^ t8; + t10 = a | d; + t11 = t1 ^ t7; + e = t10 ^ t11; + t13 = a ^ c; + t14 = b & t10; + t15 = t4 | t13; + g = t14 ^ t15 + e ^= key[4 * 21 + 8] + f ^= key[4 * 21 + 9] + g ^= key[4 * 21 + 10] + h ^= key[4 * 21 + 11] + g = rotr32(g, 22) + e = rotr32(e, 5) + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e ^= f ^ h + h = rotr32(h, 7) + f = rotr32(f, 1) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + g = rotr32(g, 3) + e = rotr32(e, 13) + t1 = g ^ h; + t2 = g | h; + t3 = f ^ t2; + t4 = e & t3; + b = t1 ^ t4; + t6 = e ^ h; + t7 = f | h; + t8 = t6 & t7; + d = t3 ^ t8; + t10 = (~e) % 0x100000000; + t11 = g ^ d; + t12 = t10 | t11; + a = t3 ^ t12; + t14 = g | t4; + t15 = t7 ^ t14; + t16 = d | t10; + c = t15 ^ t16 + a ^= key[4 * 20 + 8] + b ^= key[4 * 20 + 9] + c ^= key[4 * 20 + 10] + d ^= key[4 * 20 + 11] + c = rotr32(c, 22) + a = rotr32(a, 5) + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a ^= b ^ d + d = rotr32(d, 7) + b = rotr32(b, 1) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + c = rotr32(c, 3) + a = rotr32(a, 13) + t1 = b ^ c; + t2 = b | c; + t3 = a ^ c; + t7 = a ^ d; + t4 = t2 ^ t3; + t5 = d | t4; + t9 = t2 ^ t7; + e = t1 ^ t5; + t8 = t1 | t5; + t11 = a & t4; + g = t8 ^ t9; + t12 = e | t9; + f = t11 ^ t12; + t14 = a & g; + t15 = t2 ^ t14; + t16 = e & t15; + h = t4 ^ t16 + e ^= key[4 * 19 + 8] + f ^= key[4 * 19 + 9] + g ^= key[4 * 19 + 10] + h ^= key[4 * 19 + 11] + g = rotr32(g, 22) + e = rotr32(e, 5) + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e ^= f ^ h + h = rotr32(h, 7) + f = rotr32(f, 1) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + g = rotr32(g, 3) + e = rotr32(e, 13) + t1 = f ^ h; + t2 = (~t1) % 0x100000000; + t3 = e ^ g; + t4 = g ^ t1; + t7 = e | t2; + t5 = f & t4; + t8 = h ^ t7; + t11 = (~t4) % 0x100000000; + a = t3 ^ t5; + t9 = t3 | t8; + t14 = h & t11; + d = t1 ^ t9; + t12 = a | d; + b = t11 ^ t12; + t15 = t3 ^ t12; + c = t14 ^ t15 + a ^= key[4 * 18 + 8] + b ^= key[4 * 18 + 9] + c ^= key[4 * 18 + 10] + d ^= key[4 * 18 + 11] + c = rotr32(c, 22) + a = rotr32(a, 5) + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a ^= b ^ d + d = rotr32(d, 7) + b = rotr32(b, 1) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + c = rotr32(c, 3) + a = rotr32(a, 13) + t1 = a ^ d; + t2 = a & b; + t3 = b ^ c; + t4 = a ^ t3; + t5 = b | d; + t7 = c | t1; + h = t4 ^ t5; + t8 = b ^ t7; + t11 = (~t2) % 0x100000000; + t9 = t4 & t8; + f = t1 ^ t9; + t13 = t9 ^ t11; + t12 = h & f; + g = t12 ^ t13; + t15 = a & d; + t16 = c ^ t13; + e = t15 ^ t16 + e ^= key[4 * 17 + 8] + f ^= key[4 * 17 + 9] + g ^= key[4 * 17 + 10] + h ^= key[4 * 17 + 11] + g = rotr32(g, 22) + e = rotr32(e, 5) + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e ^= f ^ h + h = rotr32(h, 7) + f = rotr32(f, 1) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + g = rotr32(g, 3) + e = rotr32(e, 13) + t1 = (~e) % 0x100000000 + t2 = e ^ f + t3 = t1 | t2 + t4 = h ^ t3 + t7 = h & t2 + t5 = g ^ t4 + t8 = t1 ^ t7 + c = t2 ^ t5 + t11 = e & t4 + t9 = c & t8 + t14 = t5 ^ t8 + b = t4 ^ t9 + t12 = t5 | b + d = t11 ^ t12 + a = d ^ t14 + a ^= key[4 * 16 + 8] + b ^= key[4 * 16 + 9] + c ^= key[4 * 16 + 10] + d ^= key[4 * 16 + 11] + c = rotr32(c, 22) + a = rotr32(a, 5) + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a ^= b ^ d + d = rotr32(d, 7) + b = rotr32(b, 1) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + c = rotr32(c, 3) + a = rotr32(a, 13) + t1 = a & b; + t2 = a | b; + t3 = c | t1; + t4 = d & t2; + h = t3 ^ t4; + t6 = (~d) % 0x100000000; + t7 = b ^ t4; + t8 = h ^ t6; + t11 = c ^ t7; + t9 = t7 | t8; + f = a ^ t9; + t12 = d | f; + e = t11 ^ t12; + t14 = a & h; + t15 = t3 ^ f; + t16 = e ^ t14; + g = t15 ^ t16 + e ^= key[4 * 15 + 8] + f ^= key[4 * 15 + 9] + g ^= key[4 * 15 + 10] + h ^= key[4 * 15 + 11] + g = rotr32(g, 22) + e = rotr32(e, 5) + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e ^= f ^ h + h = rotr32(h, 7) + f = rotr32(f, 1) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + g = rotr32(g, 3) + e = rotr32(e, 13) + t1 = (~e) % 0x100000000; + t2 = e ^ f; + t3 = g ^ t2; + t4 = g | t1; + t5 = h ^ t4; + t13 = h & t1; + b = t3 ^ t5; + t7 = t3 & t5; + t8 = t2 ^ t7; + t9 = f | t8; + d = t5 ^ t9; + t11 = f | d; + a = t8 ^ t11; + t14 = t3 ^ t11; + c = t13 ^ t14 + a ^= key[4 * 14 + 8] + b ^= key[4 * 14 + 9] + c ^= key[4 * 14 + 10] + d ^= key[4 * 14 + 11] + c = rotr32(c, 22) + a = rotr32(a, 5) + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a ^= b ^ d + d = rotr32(d, 7) + b = rotr32(b, 1) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + c = rotr32(c, 3) + a = rotr32(a, 13) + t1 = (~c) % 0x100000000; + t2 = b & t1; + t3 = d ^ t2; + t4 = a & t3; + t5 = b ^ t1; + h = t4 ^ t5; + t7 = b | h; + t8 = a & t7; + f = t3 ^ t8; + t10 = a | d; + t11 = t1 ^ t7; + e = t10 ^ t11; + t13 = a ^ c; + t14 = b & t10; + t15 = t4 | t13; + g = t14 ^ t15 + e ^= key[4 * 13 + 8] + f ^= key[4 * 13 + 9] + g ^= key[4 * 13 + 10] + h ^= key[4 * 13 + 11] + g = rotr32(g, 22) + e = rotr32(e, 5) + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e ^= f ^ h + h = rotr32(h, 7) + f = rotr32(f, 1) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + g = rotr32(g, 3) + e = rotr32(e, 13) + t1 = g ^ h; + t2 = g | h; + t3 = f ^ t2; + t4 = e & t3; + b = t1 ^ t4; + t6 = e ^ h; + t7 = f | h; + t8 = t6 & t7; + d = t3 ^ t8; + t10 = (~e) % 0x100000000; + t11 = g ^ d; + t12 = t10 | t11; + a = t3 ^ t12; + t14 = g | t4; + t15 = t7 ^ t14; + t16 = d | t10; + c = t15 ^ t16 + a ^= key[4 * 12 + 8] + b ^= key[4 * 12 + 9] + c ^= key[4 * 12 + 10] + d ^= key[4 * 12 + 11] + c = rotr32(c, 22) + a = rotr32(a, 5) + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a ^= b ^ d + d = rotr32(d, 7) + b = rotr32(b, 1) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + c = rotr32(c, 3) + a = rotr32(a, 13) + t1 = b ^ c; + t2 = b | c; + t3 = a ^ c; + t7 = a ^ d; + t4 = t2 ^ t3; + t5 = d | t4; + t9 = t2 ^ t7; + e = t1 ^ t5; + t8 = t1 | t5; + t11 = a & t4; + g = t8 ^ t9; + t12 = e | t9; + f = t11 ^ t12; + t14 = a & g; + t15 = t2 ^ t14; + t16 = e & t15; + h = t4 ^ t16 + e ^= key[4 * 11 + 8] + f ^= key[4 * 11 + 9] + g ^= key[4 * 11 + 10] + h ^= key[4 * 11 + 11] + g = rotr32(g, 22) + e = rotr32(e, 5) + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e ^= f ^ h + h = rotr32(h, 7) + f = rotr32(f, 1) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + g = rotr32(g, 3) + e = rotr32(e, 13) + t1 = f ^ h; + t2 = (~t1) % 0x100000000; + t3 = e ^ g; + t4 = g ^ t1; + t7 = e | t2; + t5 = f & t4; + t8 = h ^ t7; + t11 = (~t4) % 0x100000000; + a = t3 ^ t5; + t9 = t3 | t8; + t14 = h & t11; + d = t1 ^ t9; + t12 = a | d; + b = t11 ^ t12; + t15 = t3 ^ t12; + c = t14 ^ t15 + a ^= key[4 * 10 + 8] + b ^= key[4 * 10 + 9] + c ^= key[4 * 10 + 10] + d ^= key[4 * 10 + 11] + c = rotr32(c, 22) + a = rotr32(a, 5) + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a ^= b ^ d + d = rotr32(d, 7) + b = rotr32(b, 1) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + c = rotr32(c, 3) + a = rotr32(a, 13) + t1 = a ^ d; + t2 = a & b; + t3 = b ^ c; + t4 = a ^ t3; + t5 = b | d; + t7 = c | t1; + h = t4 ^ t5; + t8 = b ^ t7; + t11 = (~t2) % 0x100000000; + t9 = t4 & t8; + f = t1 ^ t9; + t13 = t9 ^ t11; + t12 = h & f; + g = t12 ^ t13; + t15 = a & d; + t16 = c ^ t13; + e = t15 ^ t16 + e ^= key[4 * 9 + 8] + f ^= key[4 * 9 + 9] + g ^= key[4 * 9 + 10] + h ^= key[4 * 9 + 11] + g = rotr32(g, 22) + e = rotr32(e, 5) + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e ^= f ^ h + h = rotr32(h, 7) + f = rotr32(f, 1) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + g = rotr32(g, 3) + e = rotr32(e, 13) + t1 = (~e) % 0x100000000 + t2 = e ^ f + t3 = t1 | t2 + t4 = h ^ t3 + t7 = h & t2 + t5 = g ^ t4 + t8 = t1 ^ t7 + c = t2 ^ t5 + t11 = e & t4 + t9 = c & t8 + t14 = t5 ^ t8 + b = t4 ^ t9 + t12 = t5 | b + d = t11 ^ t12 + a = d ^ t14 + a ^= key[4 * 8 + 8] + b ^= key[4 * 8 + 9] + c ^= key[4 * 8 + 10] + d ^= key[4 * 8 + 11] + c = rotr32(c, 22) + a = rotr32(a, 5) + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a ^= b ^ d + d = rotr32(d, 7) + b = rotr32(b, 1) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + c = rotr32(c, 3) + a = rotr32(a, 13) + t1 = a & b; + t2 = a | b; + t3 = c | t1; + t4 = d & t2; + h = t3 ^ t4; + t6 = (~d) % 0x100000000; + t7 = b ^ t4; + t8 = h ^ t6; + t11 = c ^ t7; + t9 = t7 | t8; + f = a ^ t9; + t12 = d | f; + e = t11 ^ t12; + t14 = a & h; + t15 = t3 ^ f; + t16 = e ^ t14; + g = t15 ^ t16 + e ^= key[4 * 7 + 8] + f ^= key[4 * 7 + 9] + g ^= key[4 * 7 + 10] + h ^= key[4 * 7 + 11] + g = rotr32(g, 22) + e = rotr32(e, 5) + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e ^= f ^ h + h = rotr32(h, 7) + f = rotr32(f, 1) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + g = rotr32(g, 3) + e = rotr32(e, 13) + t1 = (~e) % 0x100000000; + t2 = e ^ f; + t3 = g ^ t2; + t4 = g | t1; + t5 = h ^ t4; + t13 = h & t1; + b = t3 ^ t5; + t7 = t3 & t5; + t8 = t2 ^ t7; + t9 = f | t8; + d = t5 ^ t9; + t11 = f | d; + a = t8 ^ t11; + t14 = t3 ^ t11; + c = t13 ^ t14 + a ^= key[4 * 6 + 8] + b ^= key[4 * 6 + 9] + c ^= key[4 * 6 + 10] + d ^= key[4 * 6 + 11] + c = rotr32(c, 22) + a = rotr32(a, 5) + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a ^= b ^ d + d = rotr32(d, 7) + b = rotr32(b, 1) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + c = rotr32(c, 3) + a = rotr32(a, 13) + t1 = (~c) % 0x100000000; + t2 = b & t1; + t3 = d ^ t2; + t4 = a & t3; + t5 = b ^ t1; + h = t4 ^ t5; + t7 = b | h; + t8 = a & t7; + f = t3 ^ t8; + t10 = a | d; + t11 = t1 ^ t7; + e = t10 ^ t11; + t13 = a ^ c; + t14 = b & t10; + t15 = t4 | t13; + g = t14 ^ t15 + e ^= key[4 * 5 + 8] + f ^= key[4 * 5 + 9] + g ^= key[4 * 5 + 10] + h ^= key[4 * 5 + 11] + g = rotr32(g, 22) + e = rotr32(e, 5) + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e ^= f ^ h + h = rotr32(h, 7) + f = rotr32(f, 1) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + g = rotr32(g, 3) + e = rotr32(e, 13) + t1 = g ^ h; + t2 = g | h; + t3 = f ^ t2; + t4 = e & t3; + b = t1 ^ t4; + t6 = e ^ h; + t7 = f | h; + t8 = t6 & t7; + d = t3 ^ t8; + t10 = (~e) % 0x100000000; + t11 = g ^ d; + t12 = t10 | t11; + a = t3 ^ t12; + t14 = g | t4; + t15 = t7 ^ t14; + t16 = d | t10; + c = t15 ^ t16 + a ^= key[4 * 4 + 8] + b ^= key[4 * 4 + 9] + c ^= key[4 * 4 + 10] + d ^= key[4 * 4 + 11] + c = rotr32(c, 22) + a = rotr32(a, 5) + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a ^= b ^ d + d = rotr32(d, 7) + b = rotr32(b, 1) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + c = rotr32(c, 3) + a = rotr32(a, 13) + t1 = b ^ c; + t2 = b | c; + t3 = a ^ c; + t7 = a ^ d; + t4 = t2 ^ t3; + t5 = d | t4; + t9 = t2 ^ t7; + e = t1 ^ t5; + t8 = t1 | t5; + t11 = a & t4; + g = t8 ^ t9; + t12 = e | t9; + f = t11 ^ t12; + t14 = a & g; + t15 = t2 ^ t14; + t16 = e & t15; + h = t4 ^ t16 + e ^= key[4 * 3 + 8] + f ^= key[4 * 3 + 9] + g ^= key[4 * 3 + 10] + h ^= key[4 * 3 + 11] + g = rotr32(g, 22) + e = rotr32(e, 5) + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e ^= f ^ h + h = rotr32(h, 7) + f = rotr32(f, 1) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + g = rotr32(g, 3) + e = rotr32(e, 13) + t1 = f ^ h; + t2 = (~t1) % 0x100000000; + t3 = e ^ g; + t4 = g ^ t1; + t7 = e | t2; + t5 = f & t4; + t8 = h ^ t7; + t11 = (~t4) % 0x100000000; + a = t3 ^ t5; + t9 = t3 | t8; + t14 = h & t11; + d = t1 ^ t9; + t12 = a | d; + b = t11 ^ t12; + t15 = t3 ^ t12; + c = t14 ^ t15 + a ^= key[4 * 2 + 8] + b ^= key[4 * 2 + 9] + c ^= key[4 * 2 + 10] + d ^= key[4 * 2 + 11] + c = rotr32(c, 22) + a = rotr32(a, 5) + c ^= d ^ ((b << 7) & 0xFFFFFFFF) + a ^= b ^ d + d = rotr32(d, 7) + b = rotr32(b, 1) + d ^= c ^ ((a << 3) & 0xFFFFFFFF) + b ^= a ^ c + c = rotr32(c, 3) + a = rotr32(a, 13) + t1 = a ^ d; + t2 = a & b; + t3 = b ^ c; + t4 = a ^ t3; + t5 = b | d; + t7 = c | t1; + h = t4 ^ t5; + t8 = b ^ t7; + t11 = (~t2) % 0x100000000; + t9 = t4 & t8; + f = t1 ^ t9; + t13 = t9 ^ t11; + t12 = h & f; + g = t12 ^ t13; + t15 = a & d; + t16 = c ^ t13; + e = t15 ^ t16 + e ^= key[4 * 1 + 8] + f ^= key[4 * 1 + 9] + g ^= key[4 * 1 + 10] + h ^= key[4 * 1 + 11] + g = rotr32(g, 22) + e = rotr32(e, 5) + g ^= h ^ ((f << 7) & 0xFFFFFFFF) + e ^= f ^ h + h = rotr32(h, 7) + f = rotr32(f, 1) + h ^= g ^ ((e << 3) & 0xFFFFFFFF) + f ^= e ^ g + g = rotr32(g, 3) + e = rotr32(e, 13) + t1 = (~e) % 0x100000000 + t2 = e ^ f + t3 = t1 | t2 + t4 = h ^ t3 + t7 = h & t2 + t5 = g ^ t4 + t8 = t1 ^ t7 + c = t2 ^ t5 + t11 = e & t4 + t9 = c & t8 + t14 = t5 ^ t8 + b = t4 ^ t9 + t12 = t5 | b + d = t11 ^ t12 + a = d ^ t14 + a ^= key[4 * 0 + 8] + b ^= key[4 * 0 + 9] + c ^= key[4 * 0 + 10] + d ^= key[4 * 0 + 11] + if WORD_BIGENDIAN: + a = byteswap32(a) + b = byteswap32(b) + c = byteswap32(c) + d = byteswap32(d) + in_blk[0] = a + in_blk[1] = b + in_blk[2] = c + in_blk[3] = d + +__testkey = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f' +__testdat = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f' +assert '\xde&\x9f\xf83\xe42\xb8[.\x88\xd2p\x1c\xe7\\' == Serpent(__testkey).encrypt(__testdat) +assert __testdat == Serpent(__testkey).decrypt('\xde&\x9f\xf83\xe42\xb8[.\x88\xd2p\x1c\xe7\\') + +#CBC Encrypt - Jason Reaves +def serpent_cbc_encrypt(key, data, iv='\x00'*16): + out = "" + last = iv + for i in range((len(data)/16)): + temp = data[i*16:(i+1)*16] + to_encode = "" + for j in range(4): + temp1 = struct.unpack_from(' Channel instance. + self.clients = {} # Socket --> Client instance..peers = "" + self.nicknames = {} # irc_lower(Nickname) --> Client instance. + self.recent = Ringbuffer(100) + if self.logdir: + create_directory(self.logdir) + if self.statedir: + create_directory(self.statedir) + + def daemonize(self): + try: + pid = os.fork() + if pid > 0: + sys.exit(0) + except OSError: + sys.exit(1) + os.setsid() + try: + pid = os.fork() + if pid > 0: + self.print_info("PID: %d" % pid) + sys.exit(0) + except OSError: + sys.exit(1) + os.chdir("/") + os.umask(0) + dev_null = open("/dev/null", "r+") + os.dup2(dev_null.fileno(), sys.stdout.fileno()) + os.dup2(dev_null.fileno(), sys.stderr.fileno()) + os.dup2(dev_null.fileno(), sys.stdin.fileno()) + + def get_client(self, nickname): + return self.nicknames.get(irc_lower(nickname)) + + def has_channel(self, name): + return irc_lower(name) in self.channels + + def get_channel(self, channelname): + if irc_lower(channelname) in self.channels: + channel = self.channels[irc_lower(channelname)] + else: + channel = Channel(self, channelname) + self.channels[irc_lower(channelname)] = channel + return channel + + def get_motd_lines(self): + if self.motdfile: + try: + return open(self.motdfile).readlines() + except IOError: + return ["Could not read MOTD file %r." % self.motdfile] + else: + return [] + + def print_info(self, msg): + if self.verbose: + print(msg) + sys.stdout.flush() + + def print_debug(self, msg): + if self.debug: + print(msg) + sys.stdout.flush() + + def print_error(self, msg): + sys.stderr.write("%s\n" % msg) + + def client_changed_nickname(self, client, oldnickname): + if oldnickname: + del self.nicknames[irc_lower(oldnickname)] + self.nicknames[irc_lower(client.nickname)] = client + + def remove_member_from_channel(self, client, channelname): + if irc_lower(channelname) in self.channels: + channel = self.channels[irc_lower(channelname)] + channel.remove_client(client) + + def remove_client(self, client, quitmsg): + client.message_related(":%s QUIT :%s" % (client.prefix, quitmsg)) + for x in client.channels.values(): + client.channel_log(x, "quit (%s)" % quitmsg, meta=True) + x.remove_client(client) + if client.nickname \ + and irc_lower(client.nickname) in self.nicknames: + del self.nicknames[irc_lower(client.nickname)] + del self.clients[client.socket] + + def remove_channel(self, channel): + del self.channels[irc_lower(channel.name)] + + def handle_udp_data(self, bytes_address_pair): + for peer in self.state.get_peers(): + data = bytes_address_pair[0] + address = bytes_address_pair[1] + message = self.infosec.unpack(peer, data) + if(message != None): + self.print_debug("valid message from peer: %s" % peer.handles[0]) + + # we only update the address table if the speaker is same as peer + + try: + idx = peer.handles.index(message["speaker"]) + except: + idx = None + + if idx != None: + self.state.update_address_table({"handle": message["speaker"], + "address": address[0], + "port": address[1] + }) + # send the message to all clients + for c in self.clients: + # self.clients[c].udp_socket_readable_notification(message) + if (self.clients[c].is_addressed_to_me(message["body"])): + self.clients[c].message(message["body"]) + # send the message to all other peers if it should be propagated + if(message["command"] == BROADCAST) and message["bounces"] < MAX_BOUNCES: + self.rebroadcast(peer, message) + return + self.print_debug("Unknown peer: %s %d" % (address[0], address[1])) + + def peer_message(self, message): + message["original"] = True + if message["command"] == DIRECT: + peer = self.state.get_peer_by_handle(message["handle"]) + if peer: + peer.send(message) + else: + self.print_debug("Discarding message to unknown handle: %s" % message["handle"]) + else: + for peer in self.state.get_peers(): + peer.send(message) + + def rebroadcast(self, source_peer, message): + message["original"] = False + for peer in self.state.get_peers(): + if(peer.peer_id != source_peer.peer_id): + message["command"] = BROADCAST + message["bounces"] = message["bounces"] + 1 + peer.send(message) + + + def start(self): + # Setup UDP first + self.udp_server_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) + self.udp_server_socket.bind((self.address, self.udp_port)) + + serversockets = [] + for port in self.ports: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + try: + s.bind((self.address, port)) + except socket.error as e: + self.print_error("Could not bind port %s: %s." % (port, e)) + sys.exit(1) + s.listen(5) + serversockets.append(s) + del s + self.print_info("Listening on port %d." % port) + if self.chroot: + os.chdir(self.chroot) + os.chroot(self.chroot) + self.print_info("Changed root directory to %s" % self.chroot) + if self.setuid: + os.setgid(self.setuid[1]) + os.setuid(self.setuid[0]) + self.print_info("Setting uid:gid to %s:%s" + % (self.setuid[0], self.setuid[1])) + last_aliveness_check = time.time() + while True: + (inputready,outputready,exceptready) = select.select([self.udp_server_socket],[],[],0) + (iwtd, owtd, ewtd) = select.select( + serversockets + [x.socket for x in self.clients.values()], + [x.socket for x in self.clients.values() + if x.write_queue_size() > 0], + [], + 0) + for x in inputready: + if x == self.udp_server_socket: + bytes_address_pair = self.udp_server_socket.recvfrom(PACKET_SIZE) + self.handle_udp_data(bytes_address_pair) + for x in iwtd: + if x in self.clients: + self.clients[x].socket_readable_notification() + else: + (conn, addr) = x.accept() + if self.ssl_pem_file: + import ssl + try: + conn = ssl.wrap_socket( + conn, + server_side=True, + certfile=self.ssl_pem_file, + keyfile=self.ssl_pem_file) + except ssl.SSLError as e: + self.print_error( + "SSL error for connection from %s:%s: %s" % ( + addr[0], addr[1], e)) + continue + self.clients[conn] = Client(self, conn) + self.print_info("Accepted connection from %s:%s." % ( + addr[0], addr[1])) + for x in owtd: + if x in self.clients: # client may have been disconnected + self.clients[x].socket_writable_notification() + now = time.time() + if last_aliveness_check + 10 < now: + for client in self.clients.values(): + client.check_aliveness() + last_aliveness_check = now + + +def create_directory(path): + if not os.path.isdir(path): + os.makedirs(path) + diff -uNr a/blatta/lib/state.py b/blatta/lib/state.py --- a/blatta/lib/state.py false +++ b/blatta/lib/state.py 4f6467d323b0e8cfe531ddeed0b604438bbc15b6ffb050f0da9ba0509174c6bb42d633c94f1cd46acba1fa7b7d2b74b8c5bdd896080c663b8f9c8bf893a174d6 @@ -0,0 +1,207 @@ +from lib.peer import Peer +import sqlite3 +import imp +import hashlib +from itertools import chain + +class State(object): + + def __init__(self, server, db_path): + self.server = server + self.conn = sqlite3.connect(db_path) + self.cursor = self.conn.cursor() + self.cursor.execute("create table if not exists at(handle_id integer,\ + address text not null,\ + port integer not null,\ + updated_at datetime default current_timestamp,\ + unique(handle_id, address, port))") + + self.cursor.execute("create table if not exists wot(peer_id integer primary key)") + + self.cursor.execute("create table if not exists handles(handle_id integer primary key,\ + peer_id integer,\ + handle text,\ + unique(handle))") + + self.cursor.execute("create table if not exists keys(peer_id intenger,\ + key text,\ + used_at datetime default current_timestamp,\ + unique(key))") + + self.cursor.execute("create table if not exists logs(\ + handle text not null,\ + peer_id integer,\ + message_bytes blob not null,\ + created_at datetime default current_timestamp)") + + def get_at(self, handle=None): + at = [] + if handle == None: + results = self.cursor.execute("select handle_id,address,port,updated_at from at\ + order by updated_at desc").fetchall() + else: + handle_id = self.cursor.execute("select handle_id from handles where handle=?", + (handle,)).fetchone()[0] + if None != handle_id: + results = self.cursor.execute("select handle_id,address,port,updated_at from at \ + where handle_id=? order by updated_at desc", + (handle_id,)).fetchall() + else: + return [] + for result in results: + handle_id, address, port, updated_at = result + h = self.cursor.execute("select handle from handles where handle_id=?", + (handle_id,)).fetchone()[0] + at.append({"handle": h, + "address": "%s:%s" % (address, port), + "updated_at": updated_at}) + return at + + + def get_last_message_hash(self, handle, peer_id=None): + if peer_id: + message_bytes = self.cursor.execute("select message_bytes from logs\ + where handle=? and peer_id=?\ + order by created_at desc limit 1", + (handle, peer_id)).fetchone() + + else: + message_bytes = self.cursor.execute("select message_bytes from logs\ + where handle=? and peer_id is null\ + order by created_at desc limit 1", + (handle,)).fetchone() + + if message_bytes: + return hashlib.sha256(message_bytes[0][:]).digest() + else: + return "0" * 32 + + def log(self, handle, message_bytes, peer_id=None): + self.cursor.execute("insert into logs(handle, peer_id, message_bytes)\ + values(?, ?, ?)", + (handle, peer_id, buffer(message_bytes))) + + def import_at_and_wot(self, at_path): + wot = imp.load_source('wot', at_path) + for peer in wot.peers: + results = self.cursor.execute("select * from handles where handle=? limit 1", + (peer["name"],)).fetchall() + if len(results) == 0: + key = peer["key"] + port = peer["port"] + address = peer["address"] + self.cursor.execute("insert into wot(peer_id) values(null)") + peer_id = self.cursor.lastrowid + self.cursor.execute("insert into handles(peer_id, handle) values(?, ?)", + (peer_id, peer["name"])) + handle_id = self.cursor.lastrowid + self.cursor.execute("insert into at(handle_id, address, port) values(?, ?, ?)", + (handle_id, peer["address"], peer["port"])) + self.cursor.execute("insert into keys(peer_id, key) values(?, ?)", + (peer_id, key)) + + self.conn.commit() + + def update_address_table(self, peer): + row = self.cursor.execute("select handle_id from handles where handle=?", + (peer["handle"],)).fetchone() + if row != None: + handle_id = row[0] + else: + return + + try: + self.cursor.execute("insert into at(handle_id, address, port) values(?, ?, ?)", + (handle_id, peer["address"], peer["port"])) + self.conn.commit() + except sqlite3.IntegrityError as ex: + self.cursor.execute("update at set updated_at = current_timestamp\ + where handle_id=? and address=? and port=?", + (handle_id, peer["address"], peer["port"])) + self.conn.commit() + + def add_peer(self, handle): + self.cursor.execute("insert into wot(peer_id) values(null)") + peer_id = self.cursor.lastrowid + self.cursor.execute("insert into handles(peer_id, handle) values(?, ?)", + (peer_id, handle)) + self.conn.commit() + + def remove_peer(self, handle): + # get peer id + + peer_id = self.cursor.execute("select peer_id from handles where handle=?", (handle,)).fetchone()[0] + if peer_id == None: + return + else: + # get all aliases + + handle_ids = self.get_handle_ids_for_peer(peer_id) + for handle_id in handle_ids: + # delete at entries for each alias + + self.cursor.execute("delete from at where handle_id=?", (handle_id,)) + + self.cursor.execute("delete from handles where peer_id=?", (peer_id,)) + + # delete all keys for peer id + + self.cursor.execute("delete from keys where peer_id=?", (handle_id,)) + + # delete peer from wot + + self.cursor.execute("delete from wot where peer_id=?", (peer_id,)) + self.conn.commit() + + + def add_key(self, handle, key): + peer_id = self.cursor.execute("select peer_id from handles where handle=?", (handle,)).fetchone()[0] + if peer_id != None: + self.cursor.execute("insert into keys(peer_id, key) values(?, ?)", (peer_id, key)) + self.conn.commit() + + def remove_key(self, key): + self.cursor.execute("delete from keys where key=?", (key,)) + self.conn.commit() + + def get_handle_ids_for_peer(self, peer_id): + return list(chain.from_iterable(self.cursor.execute("select handle_id from handles where peer_id=?", + (peer_id,)).fetchall())) + + def get_peers(self): + peers = [] + handles = self.cursor.execute("select handle from handles").fetchall() + + for handle in handles: + peer = self.get_peer_by_handle(handle[0]) + if not self.is_duplicate(peers, peer): + peers.append(peer) + return peers + + def get_peer_by_handle(self, handle): + handle_info = self.cursor.execute("select handle_id, peer_id from handles where handle=?", + (handle,)).fetchone() + + if handle_info == None: + return None + + address = self.cursor.execute("select address, port from at where handle_id=?\ + order by updated_at desc limit 1", + (handle_info[0],)).fetchone() + handles = list(chain.from_iterable(self.cursor.execute("select handle from handles where peer_id=?", + (handle_info[1],)).fetchall())) + keys = list(chain.from_iterable(self.cursor.execute("select key from keys where peer_id=?\ + order by used_at desc", + (handle_info[1],)).fetchall())) + return Peer(self.server, { + "handles": handles, + "peer_id": handle_info[1], + "address": address[0] if address else "", + "port": address[1] if address else "", + "keys": keys + }) + def is_duplicate(self, peers, peer): + for existing_peer in peers: + if existing_peer.address == peer.address and existing_peer.port == peer.port: + return True + return False diff -uNr a/blatta/scripts/gen_key_pair.py b/blatta/scripts/gen_key_pair.py --- a/blatta/scripts/gen_key_pair.py false +++ b/blatta/scripts/gen_key_pair.py c617e723ef3a1360c343ca635d0e4aa7f77aed515557644fce41dab0319057193ee75cff2258f69486037a025353672c6e81418d8cd9dc0c1fa6c64b66da8ed9 @@ -0,0 +1,63 @@ +#! /usr/bin/env python +# This is a TOY. Do not fire in anger. + +import os +import sys +import base64 +import pprint +from optparse import OptionParser + + +def main(argv): + pp = pprint.PrettyPrinter(indent=4) + op = OptionParser( + description="gen_key_pair generates pseudo-random 64 byte key pairs for use in testing alcuin") + op.add_option( + "-r", "--remote-name", + help="Name of remote station to include with key pair") + op.add_option( + "-l", "--local-name", + help="Name of local station to include with key pair") + op.add_option( + "-p", "--remote-port", + help="Remote station port number to include with key pair") + op.add_option( + "-q", "--local-port", + help="Local station port number to include with key pair") + op.add_option( + "-a", "--remote-address", + help="Remote station IP address to include with key pair") + op.add_option( + "-b", "--local-address", + help="Local station IP address to include with key pair") + + (options, args) = op.parse_args(argv[1:]) + + if options.local_port is None: + options.local_port = 7778 + if options.remote_port is None: + options.remote_port = 7778 + if options.local_address is None: + options.local_address = "" + if options.remote_address is None: + options.remote_address = "" + key = generate_key() + my_config = { + "name": options.local_name, + "key": key, + "address": options.local_address, + "port": options.local_port + } + their_config = { + "name": options.remote_name, + "key": key, + "address": options.remote_address, + "port": options.remote_port + } + pp.pprint(my_config) + pp.pprint(their_config) + +def generate_key(): + return base64.b64encode(os.urandom(64)) + +main(sys.argv) diff -uNr a/blatta/start_test_net.sh b/blatta/start_test_net.sh --- a/blatta/start_test_net.sh false +++ b/blatta/start_test_net.sh 158ee3120edaf743c2990baddea12d89e0626521ba45034b0c92cd182d75cea88f19758460c4758439ed866f902749b3217333613ec1f4668e9257a95c71c138 @@ -0,0 +1,6 @@ +#!/bin/bash + +# start 3 servers on different ports +./blatta --debug --port 6668 --udp-port 7778 --db-path a.db --address-table-path test_net_configs/a.py > logs/a & +./blatta --debug --port 6669 --udp-port 7779 --db-path b.db --address-table-path test_net_configs/b.py > logs/b & +./blatta --debug --port 6670 --udp-port 7780 --db-path c.db --address-table-path test_net_configs/c.py > logs/c & diff -uNr a/blatta/test_net_configs/a.py b/blatta/test_net_configs/a.py --- a/blatta/test_net_configs/a.py false +++ b/blatta/test_net_configs/a.py 3276661a7529957fb3d7aac616f26be8de21d436ae5092c40662bc2fca472a6be7e460a2d8c76286a8d84bac1e8a8bf94b98e086c9df5a8a9389ff8c9efec8b9 @@ -0,0 +1,12 @@ +peers = [ + { 'address': 'localhost', + 'key': '58bc4NyvMjasIXvsOvPxugaMpFS6tme+xJleOEwVn4iv2IuLUNAfHrkFCeL/Q4m/13Q5gfZxDbVEOtjQe+zW6Q==', + 'name': 'awt_b', + 'port': 7779 + }, + { 'address': 'localhost', + 'key': 'lT8/fYe/rQdReyavsTrVqInnLFCaU38o2ZAn5+r8uoFSSWgJelafikFELR9t6SJHMpFQvLmlAbF14nL2PfOAyA==', + 'name': 'awt_c', + 'port': 7780 + } +] diff -uNr a/blatta/test_net_configs/b.py b/blatta/test_net_configs/b.py --- a/blatta/test_net_configs/b.py false +++ b/blatta/test_net_configs/b.py 8869517ffced618bb8197669aa4124f29e450ca8f2e6451db8c7cb62d09f6ee4b6724dbd0a511851bcca1d392a4ab6c6a5a1fc1feb3f61e6f637a33becd6e251 @@ -0,0 +1,12 @@ +peers = [ + { 'address': 'localhost', + 'name': 'awt_a', + 'port': 7778, + 'key': '58bc4NyvMjasIXvsOvPxugaMpFS6tme+xJleOEwVn4iv2IuLUNAfHrkFCeL/Q4m/13Q5gfZxDbVEOtjQe+zW6Q==' + }, + { 'address': 'localhost', + 'key': '8ugkh+G1NC45DhPPtvPCI/78+fvV8K3v2XaQXvLGpJzeXy2IEA5ZnIo3PGU30+25JxAr0KV+InoqBa0VpY+zCA==', + 'name': 'awt_c', + 'port': 7780 + } +] diff -uNr a/blatta/test_net_configs/c.py b/blatta/test_net_configs/c.py --- a/blatta/test_net_configs/c.py false +++ b/blatta/test_net_configs/c.py 12569fc74a9742f8d4ce31de62c222d1f0010afcbe863ed471eb95384cd06c6e86605bcabc04a9d6e1c53106fa46655ab9e6cae2ec935c64be5156186d7488c3 @@ -0,0 +1,12 @@ +peers = [ + { 'address': 'localhost', + 'name': 'awt_b', + 'port': 7779, + 'key': '8ugkh+G1NC45DhPPtvPCI/78+fvV8K3v2XaQXvLGpJzeXy2IEA5ZnIo3PGU30+25JxAr0KV+InoqBa0VpY+zCA==' + }, + { 'address': 'localhost', + 'key': 'lT8/fYe/rQdReyavsTrVqInnLFCaU38o2ZAn5+r8uoFSSWgJelafikFELR9t6SJHMpFQvLmlAbF14nL2PfOAyA==', + 'name': 'awt_a', + 'port': 7778 + } +]