Version 9992 consists entirely of bugfixes related to poor user feedback and poor handling of command input edge cases (errors when the wot is empty, there is no key for a handle, etc.)
Archive for the ‘blatta’ Category
Blatta 9992: Better feedback and user input edge case handling
Saturday, November 6th, 2021New Alcuin Release and Rename to Blatta
Monday, November 1st, 2021As you may know, "blatta" is Latin for "cockroach." This name seems more aligned with the Pest theme, so I'm going with that.
I'm attempting to release this as a signed genesis. I haven't been able to figure out how to press it myself yet using vk.pl, but it *should* work for those who know how to use their v implementation.
This version implements several Pest-specific commands: AT, WOT, KEY, UNKEY, PEER, UNPEER, and GENKEY. In addition, this version requires only one key to be shared between a pair of peers, and also uses base64 format to store and display keys.
This is the first version that doesn't require a station to be restarted to add new peers, so it may be a bit easier at this point to stand up a longer running test net.
Alcuin 9994
Monday, October 11th, 2021From the updated README:
Alcuin 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, Alcuin *should* be able to interact with another Pest client successfully. Notably missing: - Pest specific client commands - Pest specific warning/informational output for incoming/outgoing messages - GetData message support - Key Offer message support - Key Slice message support Under the hood there is a dynamic AT and WOT, but there is no way to update them via the client. For the moment the client must still be configured via the config.py file, although this is now passed in via the --address-table-path command line option. For now, the config file is really a combination WOT/AT.
I am unable to provide a genesis using vdiff at this time because I can't get vdiff to exclude certain ephemeral files and directories.
Alcuin 9995: propagate field
Wednesday, August 25th, 2021- add propagate field
- don't propagate PMs
- filter commands sent to client via udp by nick/channel
alcuin-9995.diff alcuin-9995.tar.gz
1 | |
2 | diff --git a/Makefile b/Makefile |
3 | index 7ab6ef1..5b21c74 100644 |
4 | |
5 | |
6 | |
7 | rm -rf alcuin-$(VERSION) |
8 | |
9 | clean: |
10 | - rm -rf genesis.diff alcuin-$(VERSION).diff.escaped alcuin-$(VERSION) |
11 | + rm -rf alcuin-$(VERSION).diff alcuin-$(VERSION).diff.escaped alcuin-$(VERSION) |
12 | rm *.tar.gz |
13 | - rm *.diff.escaped |
14 | find . -name "*.swp" -delete |
15 | find . -name "*.pyc" -delete |
16 | |
17 | diff --git a/lib/client.py b/lib/client.py |
18 | index f3dc6ab..25ec4ab 100644 |
19 | |
20 | |
21 | |
22 | else: |
23 | self.__handle_command = self.__registration_handler |
24 | |
25 | + def is_addressed_to_me(self, message): |
26 | + command = self.__parse_udp_message(message) |
27 | + if command[0] == 'PRIVMSG': |
28 | + if command[1][0][0] == '#' or command[1][0] == self.nickname: |
29 | + return True |
30 | + else: |
31 | + return False |
32 | + else: |
33 | + return True |
34 | + |
35 | def get_prefix(self): |
36 | return "%s!%s@%s" % (self.nickname, self.user, self.host) |
37 | prefix = property(get_prefix) |
38 | |
39 | def write_queue_size(self): |
40 | return len(self.__writebuffer) |
41 | |
42 | + def __parse_udp_message(self, message): |
43 | + data = " ".join(message.split()[1:]) + "\r\n" |
44 | + lines = self.__linesep_regexp.split(data) |
45 | + lines = lines[:-1] |
46 | + commands = [] |
47 | + for line in lines: |
48 | + if not line: |
49 | + # Empty line. Ignore. |
50 | + continue |
51 | + x = line.split(" ", 1) |
52 | + command = x[0].upper() |
53 | + if len(x) == 1: |
54 | + arguments = [] |
55 | + else: |
56 | + if len(x[1]) > 0 and x[1][0] == ":": |
57 | + arguments = [x[1][1:]] |
58 | + else: |
59 | + y = string.split(x[1], " :", 1) |
60 | + arguments = string.split(y[0]) |
61 | + if len(y) == 2: |
62 | + arguments.append(y[1]) |
63 | + commands.append([command, arguments]) |
64 | + return commands[0] |
65 | + |
66 | def __parse_read_buffer(self): |
67 | lines = self.__linesep_regexp.split(self.__readbuffer) |
68 | self.__readbuffer = lines[-1] |
69 | |
70 | targetname = arguments[0] |
71 | message = arguments[1] |
72 | client = server.get_client(targetname) |
73 | + self.server.print_debug(self.server.nicknames) |
74 | |
75 | - if client: |
76 | - formatted_message = ":%s %s %s :%s" % (self.prefix, command, targetname, message) |
77 | - client.message(formatted_message) |
78 | - self.server.peer_broadcast(formatted_message) |
79 | - elif server.has_channel(targetname): |
80 | + if server.has_channel(targetname): |
81 | channel = server.get_channel(targetname) |
82 | self.message_channel( |
83 | channel, command, "%s :%s" % (channel.name, message)) |
84 | self.channel_log(channel, message) |
85 | else: |
86 | - # this isn't reliably true so let's not send the error |
87 | - return |
88 | - self.reply("401 %s %s :No such nick/channel" |
89 | - % (self.nickname, targetname)) |
90 | + formatted_message = ":%s %s %s :%s" % (self.prefix, command, targetname, message) |
91 | + if(client): |
92 | + client.message(formatted_message) |
93 | + self.server.peer_broadcast(formatted_message, False) |
94 | |
95 | def part_handler(): |
96 | if len(arguments) < 1: |
97 | diff --git a/lib/infosec.py b/lib/infosec.py |
98 | index a431c2f..b0c9c86 100644 |
99 | |
100 | |
101 | |
102 | import struct |
103 | import sys |
104 | |
105 | -PACKET_SIZE = 580 |
106 | +PACKET_SIZE = 581 |
107 | MAX_MESSAGE_SIZE = 512 |
108 | MAX_SECRET_SIZE = 24 |
109 | TS_ACCEPTABLE_SKEW = 60 * 15 |
110 | |
111 | def __init__(self, server=None): |
112 | self.server = server |
113 | |
114 | - def pack(self, peer, message, timestamp=None): |
115 | + def pack(self, peer, message, propagate, timestamp=None): |
116 | # if we are rebroadcasting we need to use the original timestamp |
117 | if(timestamp == None): |
118 | int_ts = int(time.time()) |
119 | |
120 | self.server.print_debug("added %d to recent" % int_ts) |
121 | |
122 | # build the packet and return it |
123 | - packet = struct.pack("!L64s512s", int_ts, digest_bytes, ciphertext_bytes) |
124 | + packet = struct.pack("!L64s?512s", int_ts, digest_bytes, propagate, ciphertext_bytes) |
125 | return packet |
126 | |
127 | def unpack(self, peer, packet): |
128 | try: |
129 | - int_ts, digest, ciphertext_bytes = struct.unpack("!L64s512s", packet) |
130 | + int_ts, digest, propagate, ciphertext_bytes = struct.unpack("!L64s?512s", packet) |
131 | except: |
132 | self.server.print_error("Discarding malformed packet?") |
133 | - return None, None |
134 | + return None, None, None |
135 | |
136 | # Check the timestamp and digest |
137 | digest_check = hashlib.sha512(peer.remote_secret + ciphertext_bytes).digest() |
138 | |
139 | if(int_ts not in self._ts_range()): |
140 | self.server.print_debug("rejected message with timestamp out of range") |
141 | - return None, None |
142 | + return None, None, None |
143 | elif(self.server.recent.has(int_ts)): |
144 | self.server.print_debug("rejected known message: %d" % int_ts) |
145 | - return None, None |
146 | + return None, None, None |
147 | elif(digest_check != digest): |
148 | self.server.print_debug("name: %s" % peer.name) |
149 | self.server.print_debug("remote_secret: %s" % peer.remote_secret) |
150 | self.server.print_debug("ciphertext_bytes: %s" % binascii.hexlify(ciphertext_bytes)) |
151 | self.server.print_debug("digest_check: %s" % binascii.hexlify(digest_check)) |
152 | self.server.print_debug("rejected bad digest: %s" % binascii.hexlify(digest)) |
153 | - return None, None |
154 | + return None, None, None |
155 | else: |
156 | # Return the cleartext |
157 | serpent = Serpent(self._pad(peer.remote_secret, MAX_SECRET_SIZE)) |
158 | cleartext = serpent.decrypt(ciphertext_bytes).rstrip() |
159 | self.server.print_debug("received, validated, and decrypted udp packet: %s" % cleartext) |
160 | self.server.recent.insert(int_ts) |
161 | - return cleartext, int_ts |
162 | + # self.server.print_debug("%s %d %s") % cleartext, int_ts, propagate |
163 | + return cleartext, int_ts, propagate |
164 | |
165 | def _pad(self, text, size): |
166 | return text.ljust(size) |
167 | diff --git a/lib/peer.py b/lib/peer.py |
168 | index e108328..5c25d25 100644 |
169 | |
170 | |
171 | |
172 | self.socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) |
173 | self.infosec = Infosec(server) |
174 | |
175 | - def send(self, msg, timestamp=None): |
176 | + def send(self, msg, propagate, timestamp=None): |
177 | try: |
178 | full_message = str.encode(msg) |
179 | self.server.print_debug("sending message: %s" % full_message) |
180 | - self.socket.sendto(self.infosec.pack(self, full_message, timestamp), (self.address, self.port)) |
181 | + self.socket.sendto(self.infosec.pack(self, full_message, propagate, timestamp), (self.address, self.port)) |
182 | except Exception as ex: |
183 | print("Exception while attempting to encode message: %s" % ex) |
184 | diff --git a/lib/server.py b/lib/server.py |
185 | index 9e8cbe5..bdd44d5 100644 |
186 | |
187 | |
188 | |
189 | -VERSION = "9996" |
190 | +VERSION = "9995" |
191 | |
192 | import os |
193 | import select |
194 | |
195 | |
196 | def handle_udp_data(self, data): |
197 | for peer in self.peers: |
198 | - message, timestamp = self.infosec.unpack(peer, data) |
199 | + message, timestamp, propagate = self.infosec.unpack(peer, data) |
200 | if(message != None): |
201 | self.print_debug("valid message from peer: %s" % peer.name) |
202 | # send the message to all clients |
203 | for c in self.clients: |
204 | - self.clients[c].message(message) |
205 | - # send the message to all other peers |
206 | - self.rebroadcast(peer, message, timestamp) |
207 | + # self.clients[c].udp_socket_readable_notification(message) |
208 | + if (self.clients[c].is_addressed_to_me(message)): |
209 | + self.clients[c].message(message) |
210 | + # send the message to all other peers if it should be propagated |
211 | + if(propagate == True): |
212 | + self.rebroadcast(peer, message, timestamp) |
213 | else: |
214 | self.print_debug("Unknown peer address: %s" % peer.address) |
215 | |
216 | - def peer_broadcast(self, message): |
217 | + def peer_broadcast(self, message, propagate=True): |
218 | for peer in self.peers: |
219 | - peer.send(message) |
220 | + peer.send(message, propagate) |
221 | |
222 | def rebroadcast(self, source_peer, message, timestamp): |
223 | for peer in self.peers: |
224 |
Alcuin 9996: Testnet and Bugfixes
Sunday, August 22nd, 2021
- add config file location command line option
- add script and config for running local testnet
- fix timestamp range bug
- force endianness for packets
- explicitly send certain commands instead of all commands
- clean up logging somewhat
- don't use misleading .vpatch extension for patches
- add patch script to Makefile for generating a patch from the latest
commit
alcuin-9996.diff alcuin-9996.tar.gz
1 | |
2 | diff --git a/Makefile b/Makefile |
3 | index a548f62..7ab6ef1 100644 |
4 | |
5 | |
6 | |
7 | rm -rf alcuin-$(VERSION) |
8 | |
9 | clean: |
10 | - rm -rf genesis.vdiff genesis.vdiff.escaped alcuin-$(VERSION) |
11 | + rm -rf genesis.diff alcuin-$(VERSION).diff.escaped alcuin-$(VERSION) |
12 | rm *.tar.gz |
13 | + rm *.diff.escaped |
14 | find . -name "*.swp" -delete |
15 | find . -name "*.pyc" -delete |
16 | |
17 | genesis: |
18 | - git show --pretty="format:" -1 94c3ce55693f > genesis.vdiff |
19 | + git show --pretty="format:" -1 94c3ce55693f > genesis.diff |
20 | |
21 | -escaped-genesis: |
22 | - git show --pretty="format:" -1 HEAD | sed 's/&/\&/g; s/</\</g; s/>/\>/g; s/"/\"/g; s/'"'"'/\'/g; s/((/\(\(/g; s/))/\)\)/g; s/\[([0-9])\[/\[$1\[/g; s/]]/\]\]/g' > genesis.vdiff.escaped |
23 | +patch: |
24 | + git show --pretty="format:" -1 HEAD > alcuin-$(VERSION).diff |
25 | + |
26 | +escaped-patch: |
27 | + git show --pretty="format:" -1 HEAD | sed 's/&/\&/g; s/</\</g; s/>/\>/g; s/"/\"/g; s/'"'"'/\'/g; s/((/\(\(/g; s/))/\)\)/g; s/\[([0-9])\[/\[$1\[/g; s/]]/\]\]/g' > alcuin-$(VERSION).diff.escaped |
28 | diff --git a/alcuin b/alcuin |
29 | index 44efc5d..a46c007 100755 |
30 | |
31 | |
32 | |
33 | version=VERSION, |
34 | description="alcuin is a small and limited IRC server emulator for gossip networks.") |
35 | op.add_option( |
36 | + "-c", "--config-file-path", |
37 | + metavar="X", |
38 | + help="load the configfile from X") |
39 | + op.add_option( |
40 | "-d", "--daemon", |
41 | action="store_true", |
42 | help="fork and become a daemon") |
43 | |
44 | options.udp_port = 7778 |
45 | else: |
46 | options.udp_port = int(options.udp_port) |
47 | + if options.config_file_path is None: |
48 | + options.config_file_path = "config.py" |
49 | if options.chroot: |
50 | if os.getuid() != 0: |
51 | op.error("Must be root to use --chroot") |
52 | diff --git a/lib/client.py b/lib/client.py |
53 | index 0ce0d4c..f3dc6ab 100644 |
54 | |
55 | |
56 | |
57 | import re |
58 | import string |
59 | from lib.server import VERSION |
60 | -from lib.infosec import Infosec |
61 | from funcs import * |
62 | |
63 | class Client(object): |
64 | |
65 | self.__readbuffer = "" |
66 | self.__writebuffer = "" |
67 | self.__sent_ping = False |
68 | - self.infosec = Infosec(self.server) |
69 | if self.server.password: |
70 | self.__handle_command = self.__pass_handler |
71 | else: |
72 | |
73 | client = server.get_client(targetname) |
74 | |
75 | if client: |
76 | - client.message(":%s %s %s :%s" |
77 | - % (self.prefix, command, targetname, message)) |
78 | + formatted_message = ":%s %s %s :%s" % (self.prefix, command, targetname, message) |
79 | + client.message(formatted_message) |
80 | + self.server.peer_broadcast(formatted_message) |
81 | elif server.has_channel(targetname): |
82 | channel = server.get_channel(targetname) |
83 | self.message_channel( |
84 | channel, command, "%s :%s" % (channel.name, message)) |
85 | self.channel_log(channel, message) |
86 | else: |
87 | + # this isn't reliably true so let's not send the error |
88 | + return |
89 | self.reply("401 %s %s :No such nick/channel" |
90 | % (self.nickname, targetname)) |
91 | |
92 | |
93 | except KeyError: |
94 | self.reply("421 %s %s :Unknown command" % (self.nickname, command)) |
95 | |
96 | - def udp_data_received(self, address, data): |
97 | - if data: |
98 | - for peer in self.server.peers: |
99 | - self.server.print_debug("trying peer: %s" % peer.name) |
100 | - message, timestamp = self.infosec.unpack(peer, data) |
101 | - if(message != None): |
102 | - self.message(message) |
103 | - self.server.rebroadcast(self, peer, message, timestamp) |
104 | - return |
105 | - self.server.print_debug("Unknown peer address: %s" % address) |
106 | - |
107 | def socket_readable_notification(self): |
108 | try: |
109 | data = self.socket.recv(2 ** 10) |
110 | |
111 | self.__parse_read_buffer() |
112 | self.__timestamp = time.time() |
113 | self.__sent_ping = False |
114 | - for peer in self.server.peers: |
115 | - peer.send(self, data) |
116 | else: |
117 | self.disconnect(quitmsg) |
118 | |
119 | def socket_writable_notification(self): |
120 | try: |
121 | - self.server.print_debug("socket_writable_notification: %s" % self.__writebuffer) |
122 | sent = self.socket.send(self.__writebuffer) |
123 | self.server.print_debug( |
124 | "[%s:%d] <- %r" % ( |
125 | |
126 | for client in channel.members: |
127 | if client != self or include_self: |
128 | client.message(line) |
129 | + # send the channel message to peers as well |
130 | + self.server.peer_broadcast(line) |
131 | |
132 | def channel_log(self, channel, message, meta=False): |
133 | if not self.server.logdir: |
134 | diff --git a/lib/infosec.py b/lib/infosec.py |
135 | index 00aa6c1..a431c2f 100644 |
136 | |
137 | |
138 | |
139 | import struct |
140 | import sys |
141 | |
142 | -PACKET_SIZE = 584 |
143 | +PACKET_SIZE = 580 |
144 | MAX_MESSAGE_SIZE = 512 |
145 | MAX_SECRET_SIZE = 24 |
146 | +TS_ACCEPTABLE_SKEW = 60 * 15 |
147 | |
148 | class Infosec(object): |
149 | def __init__(self, server=None): |
150 | |
151 | |
152 | # we want to ignore this ts if it is sent back to us |
153 | self.server.recent.insert(int_ts) |
154 | + self.server.print_debug("added %d to recent" % int_ts) |
155 | |
156 | # build the packet and return it |
157 | - packet = struct.pack("L64s512s", int_ts, digest_bytes, ciphertext_bytes) |
158 | + packet = struct.pack("!L64s512s", int_ts, digest_bytes, ciphertext_bytes) |
159 | return packet |
160 | |
161 | def unpack(self, peer, packet): |
162 | - int_ts, digest, ciphertext_bytes = struct.unpack("L64s512s", packet) |
163 | + try: |
164 | + int_ts, digest, ciphertext_bytes = struct.unpack("!L64s512s", packet) |
165 | + except: |
166 | + self.server.print_error("Discarding malformed packet?") |
167 | + return None, None |
168 | |
169 | # Check the timestamp and digest |
170 | - current_ts = int(time.time()) |
171 | digest_check = hashlib.sha512(peer.remote_secret + ciphertext_bytes).digest() |
172 | - if((current_ts - int_ts) > 60 * 15): |
173 | - self.server.print_debug("rejected old message") |
174 | + |
175 | + if(int_ts not in self._ts_range()): |
176 | + self.server.print_debug("rejected message with timestamp out of range") |
177 | return None, None |
178 | elif(self.server.recent.has(int_ts)): |
179 | - self.server.print_debug("rejected known message") |
180 | + self.server.print_debug("rejected known message: %d" % int_ts) |
181 | return None, None |
182 | elif(digest_check != digest): |
183 | self.server.print_debug("name: %s" % peer.name) |
184 | |
185 | |
186 | def _pad(self, text, size): |
187 | return text.ljust(size) |
188 | + |
189 | + def _ts_range(self): |
190 | + current_ts = int(time.time()) |
191 | + return range(current_ts - TS_ACCEPTABLE_SKEW, current_ts + TS_ACCEPTABLE_SKEW) |
192 | diff --git a/lib/peer.py b/lib/peer.py |
193 | index 34b8c60..e108328 100644 |
194 | |
195 | |
196 | |
197 | -import socket |
198 | -from infosec import Infosec |
199 | +import socket |
200 | +from infosec import Infosec |
201 | +import sys |
202 | |
203 | class Peer(object): |
204 | def __init__(self, server, peer_entry): |
205 | |
206 | self.socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) |
207 | self.infosec = Infosec(server) |
208 | |
209 | - def send(self, client, msg, timestamp=None): |
210 | - if(timestamp == None): |
211 | - full_message = str.encode(":%s %s" % (client.nickname, msg)) |
212 | - else: |
213 | + def send(self, msg, timestamp=None): |
214 | + try: |
215 | full_message = str.encode(msg) |
216 | - self.server.print_debug("sending formatted_msg: %s" % full_message) |
217 | - self.socket.sendto(self.infosec.pack(self, full_message, timestamp), (self.address, self.port)) |
218 | + self.server.print_debug("sending message: %s" % full_message) |
219 | + self.socket.sendto(self.infosec.pack(self, full_message, timestamp), (self.address, self.port)) |
220 | + except Exception as ex: |
221 | + print("Exception while attempting to encode message: %s" % ex) |
222 | diff --git a/lib/server.py b/lib/server.py |
223 | index ad595f7..9e8cbe5 100644 |
224 | |
225 | |
226 | |
227 | -VERSION = "9997" |
228 | +VERSION = "9996" |
229 | |
230 | import os |
231 | import select |
232 | |
233 | from lib.client import Client |
234 | from lib.channel import Channel |
235 | from lib.infosec import PACKET_SIZE |
236 | +from lib.infosec import Infosec |
237 | from lib.peer import Peer |
238 | from lib.ringbuffer import Ringbuffer |
239 | from funcs import * |
240 | -import config as cfg |
241 | +import imp |
242 | |
243 | class Server(object): |
244 | def __init__(self, options): |
245 | |
246 | self.chroot = options.chroot |
247 | self.setuid = options.setuid |
248 | self.statedir = options.statedir |
249 | + self.infosec = Infosec(self) |
250 | + self.config_file_path = options.config_file_path |
251 | |
252 | if options.listen: |
253 | self.address = socket.gethostbyname(options.listen) |
254 | |
255 | self.clients = {} # Socket --> Client instance..peers = "" |
256 | self.nicknames = {} # irc_lower(Nickname) --> Client instance. |
257 | self.peers = [] |
258 | + if self.config_file_path: |
259 | + cfg = imp.load_source('config', self.config_file_path) |
260 | + else: |
261 | + cfg = imp.load_source('config', "./config.py") |
262 | + |
263 | for peer_entry in cfg.peers: |
264 | self.peers.append(Peer(self, peer_entry)) |
265 | self.recent = Ringbuffer(100) |
266 | |
267 | if self.statedir: |
268 | create_directory(self.statedir) |
269 | |
270 | - def rebroadcast(self, target_client, source_peer, message, timestamp): |
271 | - for peer in self.peers: |
272 | - if(peer != source_peer): |
273 | - peer.send(target_client, message, timestamp) |
274 | - |
275 | def daemonize(self): |
276 | try: |
277 | pid = os.fork() |
278 | |
279 | def remove_channel(self, channel): |
280 | del self.channels[irc_lower(channel.name)] |
281 | |
282 | + def handle_udp_data(self, data): |
283 | + for peer in self.peers: |
284 | + message, timestamp = self.infosec.unpack(peer, data) |
285 | + if(message != None): |
286 | + self.print_debug("valid message from peer: %s" % peer.name) |
287 | + # send the message to all clients |
288 | + for c in self.clients: |
289 | + self.clients[c].message(message) |
290 | + # send the message to all other peers |
291 | + self.rebroadcast(peer, message, timestamp) |
292 | + else: |
293 | + self.print_debug("Unknown peer address: %s" % peer.address) |
294 | + |
295 | + def peer_broadcast(self, message): |
296 | + for peer in self.peers: |
297 | + peer.send(message) |
298 | + |
299 | + def rebroadcast(self, source_peer, message, timestamp): |
300 | + for peer in self.peers: |
301 | + if(peer != source_peer): |
302 | + peer.send(message, timestamp) |
303 | + |
304 | + |
305 | def start(self): |
306 | # Setup UDP first |
307 | udp_server_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) |
308 | |
309 | for x in inputready: |
310 | if x == udp_server_socket: |
311 | bytes_address_pair = udp_server_socket.recvfrom(PACKET_SIZE) |
312 | - message = bytes_address_pair[0] |
313 | - address = bytes_address_pair[1][0] |
314 | - for c in self.clients: |
315 | - self.clients[c].udp_data_received(address, message) |
316 | + data = bytes_address_pair[0] |
317 | + self.handle_udp_data(data) |
318 | for x in iwtd: |
319 | if x in self.clients: |
320 | self.clients[x].socket_readable_notification() |
321 | diff --git a/start_test_net.sh b/start_test_net.sh |
322 | new file mode 100755 |
323 | index 0000000..9930708 |
324 | |
325 | |
326 | |
327 | +#!/bin/bash |
328 | + |
329 | +# start 3 servers on different ports |
330 | +./alcuin --debug --port 6668 --udp-port 7778 --config-file test_net_configs/a.py > logs/a & |
331 | +./alcuin --debug --port 6669 --udp-port 7779 --config-file test_net_configs/b.py > logs/b & |
332 | +./alcuin --debug --port 6670 --udp-port 7780 --config-file test_net_configs/c.py > logs/c & |
333 | diff --git a/test_net_configs/a.py b/test_net_configs/a.py |
334 | new file mode 100644 |
335 | index 0000000..143bbd1 |
336 | |
337 | |
338 | |
339 | +peers = [ |
340 | + { |
341 | + "name":"b", |
342 | + "local_secret":"bik7TwuenAj,", |
343 | + "remote_secret":"5olfobNanov~", |
344 | + "address":"localhost", |
345 | + "port":7779 |
346 | + }, |
347 | +# { |
348 | +# "name":"c", |
349 | +# "local_secret":"bik7TwuenAj,", |
350 | +# "remote_secret":"Ceat]GrucEm4", |
351 | +# "address":"localhost", |
352 | +# "port":7780 |
353 | +# } |
354 | +] |
355 | diff --git a/test_net_configs/b.py b/test_net_configs/b.py |
356 | new file mode 100644 |
357 | index 0000000..5666cd8 |
358 | |
359 | |
360 | |
361 | +peers = [ |
362 | + { |
363 | + "name":"a", |
364 | + "local_secret":"5olfobNanov~", |
365 | + "remote_secret":"bik7TwuenAj,", |
366 | + "address":"localhost", |
367 | + "port":7778 |
368 | + }, |
369 | + { |
370 | + "name":"c", |
371 | + "local_secret":"5olfobNanov~", |
372 | + "remote_secret":"Ceat]GrucEm4", |
373 | + "address":"localhost", |
374 | + "port":7780 |
375 | + } |
376 | +] |
377 | diff --git a/test_net_configs/c.py b/test_net_configs/c.py |
378 | new file mode 100644 |
379 | index 0000000..5887bf0 |
380 | |
381 | |
382 | |
383 | +peers = [ |
384 | +# { |
385 | +# "name":"a", |
386 | +# "local_secret":"Ceat]GrucEm4", |
387 | +# "remote_secret":"bik7TwuenAj,", |
388 | +# "address":"localhost", |
389 | +# "port":7778 |
390 | +# }, |
391 | + { |
392 | + "name":"b", |
393 | + "local_secret":"Ceat]GrucEm4", |
394 | + "remote_secret":"5olfobNanov~", |
395 | + "address":"localhost", |
396 | + "port":7779 |
397 | + } |
398 | +] |
399 |
Alcuin 9997: Gossip Support
Tuesday, August 10th, 2021Alcuin 9997 now uses a gossip protocol to send messages between network nodes. Additionally, the config file has been restructured to allow for using a separate local secret for each peer. Packet sizes have been significantly reduced through usage of the struct.pack/unpack functions to directly write bytes to the packet. Thanks to PeterL for a snippet I used to detect duplicate timestamps.
I don't foresee making any further major releases until asciilifeform publishes his standard.
Encryption for alcuin
Sunday, August 1st, 2021Alcuin 9998 is available as a patch to the genesis, or as a tarball.
This release includes the following changes:
- Packet encryption using a pure Python implementation of Serpent1
- Digest now includes the peer secret in order to allow easy dropping of garbage packets
- Updated config file format - all peer information including port number is now specified in the config file. The --peers command line option has been removed.
1 | diff --git a/README.txt b/README.txt |
2 | index 2d5ff88..5228ab4 100644 |
3 | |
4 | |
5 | |
6 | |
7 | - gossip style message forwarding |
8 | - message deduplication |
9 | -- symmetric encryption of messages |
10 | -- support for broadcasting several important IRC commands |
11 | - over the gossip net. |
12 | - mitigation of hash length extension attacks |
13 | |
14 | GETTING STARTED |
15 | |
16 | -1. Copy config.py.example to config.py (nothing in the config file is |
17 | -used yet, but alcuin will crash if it doesn't exist). |
18 | +1. Copy config.py.example to config.py and update it appropriately. |
19 | 2. Launch alcuin with something like the following command: |
20 | -./alcuin --verbose --port=6668 --peers=206.189.163.145 |
21 | +./alcuin --port=6668 |
22 | |
23 | NOTES FOR DIFF/PATCH N00B5 |
24 | |
25 | diff --git a/lib/server.py b/lib/server.py |
26 | index f2c6206..a609aaf 100644 |
27 | |
28 | |
29 | |
30 | -VERSION = "9999" |
31 | +VERSION = "9998" |
32 | |
33 | import os |
34 | import select |
35 | |
36 | diff --git a/lib/infosec.py b/lib/infosec.py |
37 | index 0807633..255d201 100644 |
38 | |
39 | |
40 | |
41 | serpent = Serpent(self._pad(config.secret, MAX_SECRET_SIZE)) |
42 | padded_message = self._pad(message, MAX_MESSAGE_SIZE) |
43 | ciphertext = binascii.hexlify(serpent.encrypt(padded_message.encode("ascii"))) |
44 | - digest = hashlib.sha512(ciphertext).hexdigest() |
45 | + digest = hashlib.sha512(config.secret + ciphertext).hexdigest() |
46 | print("packing message: %s" % message) |
47 | print("pack digest: %s" % digest) |
48 | print("pack digest length: %d" % len(digest)) |
49 | |
50 | print("received package: %s" % package) |
51 | received_digest = package[0:128] |
52 | ciphertext = package[128:1152] |
53 | - digest = hashlib.sha512(ciphertext).hexdigest() |
54 | + digest = hashlib.sha512(peer_secret + ciphertext).hexdigest() |
55 | print("unpack package length: %d" % len(package)) |
56 | print("unpack sender digest: %s" % received_digest) |
57 | print("unpack sender digest length: %d" % len(received_digest)) |
58 | |
59 | diff --git a/alcuin b/alcuin |
60 | index bbf9ed4..44efc5d 100755 |
61 | |
62 | |
63 | |
64 | from lib.peer import Peer |
65 | from datetime import datetime |
66 | from optparse import OptionParser |
67 | -import config as cfg |
68 | |
69 | |
70 | def main(argv): |
71 | |
72 | help="listen for UDP packets on X;" |
73 | " default: 7778") |
74 | op.add_option( |
75 | - "--peers", |
76 | - metavar="X", |
77 | - help="Broadcast to X (a list of IP addresses separated by comma or whitespace)") |
78 | - op.add_option( |
79 | "--statedir", |
80 | metavar="X", |
81 | help="save persistent channel state (topic, key) in directory X") |
82 | |
83 | options.ports = "6667" |
84 | else: |
85 | options.ports = "6697" |
86 | - if options.peers is None: |
87 | - options.peers = "" |
88 | if options.udp_port is None: |
89 | options.udp_port = 7778 |
90 | else: |
91 | |
92 | except ValueError: |
93 | op.error("bad port: %r" % port) |
94 | options.ports = ports |
95 | - peers = [] |
96 | - for peer in re.split(r"[,\s]+", options.peers): |
97 | - try: |
98 | - peers.append(Peer(peer)) |
99 | - except ValueError: |
100 | - op.error("bad peer ip: %r" % peer) |
101 | - options.peers = peers |
102 | server = Server(options) |
103 | if options.daemon: |
104 | server.daemonize() |
105 | diff --git a/config.py.example b/config.py.example |
106 | index f9adc62..611913e 100644 |
107 | |
108 | |
109 | |
110 | secret = "SEEKRIT" |
111 | -peer_secrets = { |
112 | - "10.0.0.1":"K33P-0U7!" |
113 | -} |
114 | +peers = [ |
115 | + { |
116 | + "name":"schellenberg", |
117 | + "secret":"K33P-0U7!", |
118 | + "address":"10.0.0.1", |
119 | + "port":7778 |
120 | + } |
121 | +] |
122 | diff --git a/lib/client.py b/lib/client.py |
123 | index 97d8a7f..30eb5ed 100644 |
124 | |
125 | |
126 | |
127 | |
128 | def udp_data_received(self, address, data): |
129 | if data: |
130 | - message = self.infosec.unpack(address, data) |
131 | - if(message != None): |
132 | - self.message(message) |
133 | + for peer in self.server.peers: |
134 | + if(address == peer.address): |
135 | + message = self.infosec.unpack(peer, data) |
136 | + if(message != None): |
137 | + self.message(message) |
138 | + return |
139 | + print("Unknown peer address: " % address) |
140 | |
141 | def socket_readable_notification(self): |
142 | try: |
143 | diff --git a/lib/infosec.py b/lib/infosec.py |
144 | index f11b992..0807633 100644 |
145 | |
146 | |
147 | |
148 | print("pack package length: %d" % len(package)) |
149 | return package |
150 | |
151 | - def unpack(self, address, package): |
152 | - peer_secret = config.peer_secrets[address] |
153 | - if(None != peer_secret): |
154 | - serpent = Serpent(self._pad(peer_secret, MAX_SECRET_SIZE)) |
155 | - print("received package: %s" % package) |
156 | - received_digest = package[0:128] |
157 | - ciphertext = package[128:1152] |
158 | - digest = hashlib.sha512(ciphertext).hexdigest() |
159 | - print("unpack package length: %d" % len(package)) |
160 | - print("unpack sender digest: %s" % received_digest) |
161 | - print("unpack sender digest length: %d" % len(received_digest)) |
162 | - print("unpack local digest: %s" % digest) |
163 | - print("unpack local digest length: %d" % len(digest)) |
164 | - print("unpack ciphertext: %s") % ciphertext |
165 | - print("unpack ciphertext length: %d") % len(ciphertext) |
166 | - if(received_digest == digest): |
167 | - return serpent.decrypt(binascii.unhexlify(ciphertext)) |
168 | - else: |
169 | - print("unable to validate package: %s" % package) |
170 | - return None |
171 | + def unpack(self, peer, package): |
172 | + peer_secret = peer.secret |
173 | + serpent = Serpent(self._pad(peer_secret, MAX_SECRET_SIZE)) |
174 | + print("received package: %s" % package) |
175 | + received_digest = package[0:128] |
176 | + ciphertext = package[128:1152] |
177 | + digest = hashlib.sha512(ciphertext).hexdigest() |
178 | + print("unpack package length: %d" % len(package)) |
179 | + print("unpack sender digest: %s" % received_digest) |
180 | + print("unpack sender digest length: %d" % len(received_digest)) |
181 | + print("unpack local digest: %s" % digest) |
182 | + print("unpack local digest length: %d" % len(digest)) |
183 | + print("unpack ciphertext: %s") % ciphertext |
184 | + print("unpack ciphertext length: %d") % len(ciphertext) |
185 | + if(received_digest == digest): |
186 | + return serpent.decrypt(binascii.unhexlify(ciphertext)) |
187 | else: |
188 | - print("received message from unknown peer: %s" % address) |
189 | + print("unable to validate package: %s" % package) |
190 | + return None |
191 | |
192 | def _pad(self, text, size): |
193 | return text.ljust(size) |
194 | diff --git a/lib/peer.py b/lib/peer.py |
195 | index 4a64ed7..fcb0f0c 100644 |
196 | |
197 | |
198 | |
199 | import socket |
200 | from infosec import Infosec |
201 | |
202 | -class Peer(object): |
203 | - def __init__(self, address): |
204 | - self.address = address |
205 | - self.socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) |
206 | - self.infosec = Infosec() |
207 | +class Peer(object): |
208 | + def __init__(self, peer_entry): |
209 | + self.name = peer_entry["name"] |
210 | + self.address = peer_entry["address"] |
211 | + self.secret = peer_entry["secret"] |
212 | + self.port = peer_entry["port"] |
213 | + self.socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) |
214 | + self.infosec = Infosec() |
215 | |
216 | - def send(self, client, msg): |
217 | - full_message = str.encode(":%s %s" % (client.nickname, msg)) |
218 | - print("sending formatted_msg: %s" % full_message) |
219 | - self.socket.sendto(self.infosec.pack(full_message), (self.address, 7778)) |
220 | + def send(self, client, msg): |
221 | + full_message = str.encode(":%s %s" % (client.nickname, msg)) |
222 | + print("sending formatted_msg: %s" % full_message) |
223 | + self.socket.sendto(self.infosec.pack(full_message), (self.address, self.port)) |
224 | diff --git a/lib/server.py b/lib/server.py |
225 | index a248f1a..f2c6206 100644 |
226 | |
227 | |
228 | |
229 | from lib.infosec import Infosec |
230 | from lib.peer import Peer |
231 | from funcs import * |
232 | +import config as cfg |
233 | |
234 | class Server(object): |
235 | def __init__(self, options): |
236 | self.ports = options.ports |
237 | - self.peers = options.peers |
238 | self.udp_port = options.udp_port |
239 | self.password = options.password |
240 | self.ssl_pem_file = options.ssl_pem_file |
241 | |
242 | self.channels = {} # irc_lower(Channel name) --> Channel instance. |
243 | self.clients = {} # Socket --> Client instance..peers = "" |
244 | self.nicknames = {} # irc_lower(Nickname) --> Client instance. |
245 | + self.peers = [] |
246 | + for peer_entry in cfg.peers: |
247 | + self.peers.append(Peer(peer_entry)) |
248 | if self.logdir: |
249 | create_directory(self.logdir) |
250 | if self.statedir: |
251 | |
252 | diff --git a/lib/client.py b/lib/client.py |
253 | index cfc5331..97d8a7f 100644 |
254 | |
255 | |
256 | |
257 | except KeyError: |
258 | self.reply("421 %s %s :Unknown command" % (self.nickname, command)) |
259 | |
260 | - def udp_data_received(self, data): |
261 | + def udp_data_received(self, address, data): |
262 | if data: |
263 | - message = self.infosec.unpack(data) |
264 | + message = self.infosec.unpack(address, data) |
265 | if(message != None): |
266 | self.message(message) |
267 | |
268 | diff --git a/lib/infosec.py b/lib/infosec.py |
269 | index 6e87ca6..f11b992 100644 |
270 | |
271 | |
272 | |
273 | import hashlib |
274 | -PACKET_SIZE = 1024 |
275 | +import lib.serpent |
276 | + |
277 | +from lib.serpent import Serpent |
278 | +import config |
279 | +import binascii |
280 | +PACKET_SIZE = 1152 |
281 | MAX_MESSAGE_SIZE = 512 |
282 | +MAX_SECRET_SIZE = 24 |
283 | |
284 | class Infosec(object): |
285 | #def __init__(self): |
286 | # do nothing |
287 | |
288 | def pack(self, message): |
289 | - digest = hashlib.sha512(self._pad(message)).hexdigest() |
290 | - return digest + message |
291 | + serpent = Serpent(self._pad(config.secret, MAX_SECRET_SIZE)) |
292 | + padded_message = self._pad(message, MAX_MESSAGE_SIZE) |
293 | + ciphertext = binascii.hexlify(serpent.encrypt(padded_message.encode("ascii"))) |
294 | + digest = hashlib.sha512(ciphertext).hexdigest() |
295 | + print("packing message: %s" % message) |
296 | + print("pack digest: %s" % digest) |
297 | + print("pack digest length: %d" % len(digest)) |
298 | + print("pack ciphertext: %s" % ciphertext) |
299 | + print("pack ciphertext length: %d" % len(ciphertext)) |
300 | + package = digest + ciphertext |
301 | + print("pack package length: %d" % len(package)) |
302 | + return package |
303 | |
304 | - def unpack(self, package): |
305 | - print("received package: %s" % package) |
306 | - received_digest = package[0:128] |
307 | - message = package[128:1023] |
308 | - digest = hashlib.sha512(self._pad(message)).hexdigest() |
309 | - print("received_digest: %s" % received_digest) |
310 | - print("digest: %s" % digest) |
311 | - print("message: %s") % message |
312 | - if(received_digest == digest): |
313 | - return message |
314 | + def unpack(self, address, package): |
315 | + peer_secret = config.peer_secrets[address] |
316 | + if(None != peer_secret): |
317 | + serpent = Serpent(self._pad(peer_secret, MAX_SECRET_SIZE)) |
318 | + print("received package: %s" % package) |
319 | + received_digest = package[0:128] |
320 | + ciphertext = package[128:1152] |
321 | + digest = hashlib.sha512(ciphertext).hexdigest() |
322 | + print("unpack package length: %d" % len(package)) |
323 | + print("unpack sender digest: %s" % received_digest) |
324 | + print("unpack sender digest length: %d" % len(received_digest)) |
325 | + print("unpack local digest: %s" % digest) |
326 | + print("unpack local digest length: %d" % len(digest)) |
327 | + print("unpack ciphertext: %s") % ciphertext |
328 | + print("unpack ciphertext length: %d") % len(ciphertext) |
329 | + if(received_digest == digest): |
330 | + return serpent.decrypt(binascii.unhexlify(ciphertext)) |
331 | + else: |
332 | + print("unable to validate package: %s" % package) |
333 | + return None |
334 | else: |
335 | - print("unable to validate package: %s" % package) |
336 | - return None |
337 | + print("received message from unknown peer: %s" % address) |
338 | |
339 | - def _pad(self, text): |
340 | - return str(text.ljust(MAX_MESSAGE_SIZE)).encode("ascii") |
341 | + def _pad(self, text, size): |
342 | + return text.ljust(size) |
343 | |
344 | diff --git a/lib/serpent.py b/lib/serpent.py |
345 | new file mode 100644 |
346 | index 0000000..c7c9f83 |
347 | |
348 | |
349 | |
350 | +## serpent.py - pure Python implementation of the Serpent algorithm. |
351 | +## Bjorn Edstrom <be@bjrn.se> 13 december 2007. |
352 | +## |
353 | +## Copyrights |
354 | +## ========== |
355 | +## |
356 | +## This code is a derived from an implementation by Dr Brian Gladman |
357 | +## (gladman@seven77.demon.co.uk) which is subject to the following license. |
358 | +## This Python implementation is not subject to any other license. |
359 | +## |
360 | +##/* This is an independent implementation of the encryption algorithm: |
361 | +## * |
362 | +## * Serpent by Ross Anderson, Eli Biham and Lars Knudsen |
363 | +## * |
364 | +## * which is a candidate algorithm in the Advanced Encryption Standard |
365 | +## * programme of the US National Institute of Standards and Technology |
366 | +## * |
367 | +## * Copyright in this implementation is held by Dr B R Gladman but I |
368 | +## * hereby give permission for its free direct or derivative use subject |
369 | +## * to acknowledgment of its origin and compliance with any conditions |
370 | +## * that the originators of the algorithm place on its exploitation. |
371 | +## * |
372 | +## * Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 |
373 | +## */ |
374 | +## |
375 | +## The above copyright notice must not be removed. |
376 | +## |
377 | +## Information |
378 | +## =========== |
379 | +## |
380 | +## Anyone thinking of using this code should reconsider. It's slow. |
381 | +## Try python-mcrypt instead. In case a faster library is not installed |
382 | +## on the target system, this code can be used as a portable fallback. |
383 | + |
384 | +import binascii |
385 | +import base64 |
386 | + |
387 | +block_size = 16 |
388 | +key_size = 32 |
389 | + |
390 | +class Serpent: |
391 | + |
392 | + def __init__(self, key=None): |
393 | + """Serpent.""" |
394 | + |
395 | + if key: |
396 | + self.set_key(key) |
397 | + |
398 | + |
399 | + def set_key(self, key): |
400 | + """Init.""" |
401 | + |
402 | + key_len = len(key) |
403 | + if key_len % 4: |
404 | + # XXX: add padding? |
405 | + raise KeyError, "key not a multiple of 4" |
406 | + if key_len > 32: |
407 | + # XXX: prune? |
408 | + raise KeyError, "key_len > 32" |
409 | + |
410 | + self.key_context = [0] * 140 |
411 | + |
412 | + key_word32 = [0] * 32 |
413 | + i = 0 |
414 | + while key: |
415 | + key_word32[i] = struct.unpack("<L", key[0:4])[0] |
416 | + key = key[4:] |
417 | + i += 1 |
418 | + |
419 | + set_key(self.key_context, key_word32, key_len) |
420 | + #print(map(hex,self.key_context)) |
421 | + |
422 | + |
423 | + def decrypt(self, block): |
424 | + """Decrypt blocks.""" |
425 | + |
426 | + if len(block) % 16: |
427 | + raise ValueError, "block size must be a multiple of 16" |
428 | + |
429 | + plaintext = '' |
430 | + |
431 | + while block: |
432 | + a, b, c, d = struct.unpack("<4L", block[:16]) |
433 | + temp = [a, b, c, d] |
434 | + decrypt(self.key_context, temp) |
435 | + plaintext += struct.pack("<4L", *temp) |
436 | + block = block[16:] |
437 | + |
438 | + return plaintext |
439 | + |
440 | + |
441 | + def encrypt(self, block): |
442 | + """Encrypt blocks.""" |
443 | + |
444 | + if len(block) % 16: |
445 | + raise ValueError, "block size must be a multiple of 16" |
446 | + |
447 | + ciphertext = '' |
448 | + |
449 | + while block: |
450 | + a, b, c, d = struct.unpack("<4L", block[0:16]) |
451 | + temp = [a, b, c, d] |
452 | + encrypt(self.key_context, temp) |
453 | + ciphertext += struct.pack("<4L", *temp) |
454 | + block = block[16:] |
455 | + |
456 | + return ciphertext |
457 | + |
458 | + |
459 | + def get_name(self): |
460 | + """Return the name of the cipher.""" |
461 | + |
462 | + return "Serpent" |
463 | + |
464 | + |
465 | + def get_block_size(self): |
466 | + """Get cipher block size in bytes.""" |
467 | + |
468 | + return 16 |
469 | + |
470 | + |
471 | + def get_key_size(self): |
472 | + """Get cipher key size in bytes.""" |
473 | + |
474 | + return 32 |
475 | + |
476 | + |
477 | +# |
478 | +# Private. |
479 | +# |
480 | + |
481 | +import struct |
482 | +import sys |
483 | + |
484 | +WORD_BIGENDIAN = 0 |
485 | +if sys.byteorder == 'big': |
486 | + WORD_BIGENDIAN = 1 |
487 | + |
488 | +def rotr32(x, n): |
489 | + return (x >> n) | ((x << (32 - n)) & 0xFFFFFFFF) |
490 | + |
491 | +def rotl32(x, n): |
492 | + return ((x << n) & 0xFFFFFFFF) | (x >> (32 - n)) |
493 | + |
494 | +def byteswap32(x): |
495 | + return ((x & 0xff) << 24) | (((x >> & 0xff) << 16) | \ |
496 | + (((x >> 16) & 0xff) << | ((x >> 24) & 0xff) |
497 | + |
498 | +def set_key(l_key, key, key_len): |
499 | + key_len *= 8 |
500 | + if key_len > 256: |
501 | + return False |
502 | + |
503 | + i = 0 |
504 | + lk = (key_len + 31) / 32 |
505 | + while i < lk: |
506 | + l_key[i] = key[i] |
507 | + if WORD_BIGENDIAN: |
508 | + l_key[i] = byteswap32(key[i]) |
509 | + i += 1 |
510 | + |
511 | + if key_len < 256: |
512 | + while i < 8: |
513 | + l_key[i] = 0 |
514 | + i += 1 |
515 | + i = key_len / 32 |
516 | + lk = 1 << (key_len % 32) |
517 | + l_key[i] = (l_key[i] & (lk - 1)) | lk |
518 | + for i in xrange(132): |
519 | + lk = l_key[i] ^ l_key[i + 3] ^ l_key[i + 5] ^ l_key[i + 7] ^ 0x9e3779b9 ^ i |
520 | + l_key[i + 8] = ((lk << 11) & 0xFFFFFFFF) | (lk >> 21) |
521 | + |
522 | + key = l_key |
523 | + # serpent_generate.py |
524 | + a = key[4 * 0 + 8] |
525 | + b = key[4 * 0 + 9] |
526 | + c = key[4 * 0 + 10] |
527 | + d = key[4 * 0 + 11] |
528 | + e = 0 |
529 | + f = 0 |
530 | + g = 0 |
531 | + h = 0 |
532 | + t1 = 0 |
533 | + t2 = 0 |
534 | + t3 = 0 |
535 | + t4 = 0 |
536 | + t5 = 0 |
537 | + t6 = 0 |
538 | + t7 = 0 |
539 | + t8 = 0 |
540 | + t9 = 0 |
541 | + t10 = 0 |
542 | + t11 = 0 |
543 | + t12 = 0 |
544 | + t13 = 0 |
545 | + t14 = 0 |
546 | + t15 = 0 |
547 | + t16 = 0 |
548 | + t1 = a ^ c; |
549 | + t2 = d ^ t1; |
550 | + t3 = a & t2; |
551 | + t4 = d ^ t3; |
552 | + t5 = b & t4; |
553 | + g = t2 ^ t5; |
554 | + t7 = a | g; |
555 | + t8 = b | d; |
556 | + t11 = a | d; |
557 | + t9 = t4 & t7; |
558 | + f = t8 ^ t9; |
559 | + t12 = b ^ t11; |
560 | + t13 = g ^ t9; |
561 | + t15 = t3 ^ t8; |
562 | + h = t12 ^ t13; |
563 | + t16 = c & t15; |
564 | + e = t12 ^ t16 |
565 | + key[4 * 0 + 8] = e |
566 | + key[4 * 0 + 9] = f |
567 | + key[4 * 0 + 10] = g |
568 | + key[4 * 0 + 11] = h |
569 | + a = key[4 * 1 + 8] |
570 | + b = key[4 * 1 + 9] |
571 | + c = key[4 * 1 + 10] |
572 | + d = key[4 * 1 + 11] |
573 | + t1 = (~a) % 0x100000000; |
574 | + t2 = b ^ d; |
575 | + t3 = c & t1; |
576 | + t13 = d | t1; |
577 | + e = t2 ^ t3; |
578 | + t5 = c ^ t1; |
579 | + t6 = c ^ e; |
580 | + t7 = b & t6; |
581 | + t10 = e | t5; |
582 | + h = t5 ^ t7; |
583 | + t9 = d | t7; |
584 | + t11 = t9 & t10; |
585 | + t14 = t2 ^ h; |
586 | + g = a ^ t11; |
587 | + t15 = g ^ t13; |
588 | + f = t14 ^ t15 |
589 | + key[4 * 1 + 8] = e |
590 | + key[4 * 1 + 9] = f |
591 | + key[4 * 1 + 10] = g |
592 | + key[4 * 1 + 11] = h |
593 | + a = key[4 * 2 + 8] |
594 | + b = key[4 * 2 + 9] |
595 | + c = key[4 * 2 + 10] |
596 | + d = key[4 * 2 + 11] |
597 | + t1 = (~a) % 0x100000000; |
598 | + t2 = b ^ t1; |
599 | + t3 = a | t2; |
600 | + t4 = d | t2; |
601 | + t5 = c ^ t3; |
602 | + g = d ^ t5; |
603 | + t7 = b ^ t4; |
604 | + t8 = t2 ^ g; |
605 | + t9 = t5 & t7; |
606 | + h = t8 ^ t9; |
607 | + t11 = t5 ^ t7; |
608 | + f = h ^ t11; |
609 | + t13 = t8 & t11; |
610 | + e = t5 ^ t13 |
611 | + key[4 * 2 + 8] = e |
612 | + key[4 * 2 + 9] = f |
613 | + key[4 * 2 + 10] = g |
614 | + key[4 * 2 + 11] = h |
615 | + a = key[4 * 3 + 8] |
616 | + b = key[4 * 3 + 9] |
617 | + c = key[4 * 3 + 10] |
618 | + d = key[4 * 3 + 11] |
619 | + t1 = a ^ d; |
620 | + t2 = a & d; |
621 | + t3 = c ^ t1; |
622 | + t6 = b & t1; |
623 | + t4 = b ^ t3; |
624 | + t10 = (~t3) % 0x100000000; |
625 | + h = t2 ^ t4; |
626 | + t7 = a ^ t6; |
627 | + t14 = (~t7) % 0x100000000; |
628 | + t8 = c | t7; |
629 | + t11 = t3 ^ t7; |
630 | + g = t4 ^ t8; |
631 | + t12 = h & t11; |
632 | + f = t10 ^ t12; |
633 | + e = t12 ^ t14 |
634 | + key[4 * 3 + 8] = e |
635 | + key[4 * 3 + 9] = f |
636 | + key[4 * 3 + 10] = g |
637 | + key[4 * 3 + 11] = h |
638 | + a = key[4 * 4 + 8] |
639 | + b = key[4 * 4 + 9] |
640 | + c = key[4 * 4 + 10] |
641 | + d = key[4 * 4 + 11] |
642 | + t1 = (~c) % 0x100000000; |
643 | + t2 = b ^ c; |
644 | + t3 = b | t1; |
645 | + t4 = d ^ t3; |
646 | + t5 = a & t4; |
647 | + t7 = a ^ d; |
648 | + h = t2 ^ t5; |
649 | + t8 = b ^ t5; |
650 | + t9 = t2 | t8; |
651 | + t11 = d & t3; |
652 | + f = t7 ^ t9; |
653 | + t12 = t5 ^ f; |
654 | + t15 = t1 | t4; |
655 | + t13 = h & t12; |
656 | + g = t11 ^ t13; |
657 | + t16 = t12 ^ g; |
658 | + e = t15 ^ t16 |
659 | + key[4 * 4 + 8] = e |
660 | + key[4 * 4 + 9] = f |
661 | + key[4 * 4 + 10] = g |
662 | + key[4 * 4 + 11] = h |
663 | + a = key[4 * 5 + 8] |
664 | + b = key[4 * 5 + 9] |
665 | + c = key[4 * 5 + 10] |
666 | + d = key[4 * 5 + 11] |
667 | + t1 = (~a) % 0x100000000; |
668 | + t2 = a ^ d; |
669 | + t3 = b ^ t2; |
670 | + t4 = t1 | t2; |
671 | + t5 = c ^ t4; |
672 | + f = b ^ t5; |
673 | + t13 = (~t5) % 0x100000000; |
674 | + t7 = t2 | f; |
675 | + t8 = d ^ t7; |
676 | + t9 = t5 & t8; |
677 | + g = t3 ^ t9; |
678 | + t11 = t5 ^ t8; |
679 | + e = g ^ t11; |
680 | + t14 = t3 & t11; |
681 | + h = t13 ^ t14 |
682 | + key[4 * 5 + 8] = e |
683 | + key[4 * 5 + 9] = f |
684 | + key[4 * 5 + 10] = g |
685 | + key[4 * 5 + 11] = h |
686 | + a = key[4 * 6 + 8] |
687 | + b = key[4 * 6 + 9] |
688 | + c = key[4 * 6 + 10] |
689 | + d = key[4 * 6 + 11] |
690 | + t1 = (~a) % 0x100000000; |
691 | + t2 = a ^ b; |
692 | + t3 = a ^ d; |
693 | + t4 = c ^ t1; |
694 | + t5 = t2 | t3; |
695 | + e = t4 ^ t5; |
696 | + t7 = d & e; |
697 | + t8 = t2 ^ e; |
698 | + t10 = t1 | e; |
699 | + f = t7 ^ t8; |
700 | + t11 = t2 | t7; |
701 | + t12 = t3 ^ t10; |
702 | + t14 = b ^ t7; |
703 | + g = t11 ^ t12; |
704 | + t15 = f & t12; |
705 | + h = t14 ^ t15 |
706 | + key[4 * 6 + 8] = e |
707 | + key[4 * 6 + 9] = f |
708 | + key[4 * 6 + 10] = g |
709 | + key[4 * 6 + 11] = h |
710 | + a = key[4 * 7 + 8] |
711 | + b = key[4 * 7 + 9] |
712 | + c = key[4 * 7 + 10] |
713 | + d = key[4 * 7 + 11] |
714 | + t1 = a ^ d; |
715 | + t2 = d & t1; |
716 | + t3 = c ^ t2; |
717 | + t4 = b | t3; |
718 | + h = t1 ^ t4; |
719 | + t6 = (~b) % 0x100000000; |
720 | + t7 = t1 | t6; |
721 | + e = t3 ^ t7; |
722 | + t9 = a & e; |
723 | + t10 = t1 ^ t6; |
724 | + t11 = t4 & t10; |
725 | + g = t9 ^ t11; |
726 | + t13 = a ^ t3; |
727 | + t14 = t10 & g; |
728 | + f = t13 ^ t14 |
729 | + key[4 * 7 + 8] = e |
730 | + key[4 * 7 + 9] = f |
731 | + key[4 * 7 + 10] = g |
732 | + key[4 * 7 + 11] = h |
733 | + a = key[4 * 8 + 8] |
734 | + b = key[4 * 8 + 9] |
735 | + c = key[4 * 8 + 10] |
736 | + d = key[4 * 8 + 11] |
737 | + t1 = a ^ c; |
738 | + t2 = d ^ t1; |
739 | + t3 = a & t2; |
740 | + t4 = d ^ t3; |
741 | + t5 = b & t4; |
742 | + g = t2 ^ t5; |
743 | + t7 = a | g; |
744 | + t8 = b | d; |
745 | + t11 = a | d; |
746 | + t9 = t4 & t7; |
747 | + f = t8 ^ t9; |
748 | + t12 = b ^ t11; |
749 | + t13 = g ^ t9; |
750 | + t15 = t3 ^ t8; |
751 | + h = t12 ^ t13; |
752 | + t16 = c & t15; |
753 | + e = t12 ^ t16 |
754 | + key[4 * 8 + 8] = e |
755 | + key[4 * 8 + 9] = f |
756 | + key[4 * 8 + 10] = g |
757 | + key[4 * 8 + 11] = h |
758 | + a = key[4 * 9 + 8] |
759 | + b = key[4 * 9 + 9] |
760 | + c = key[4 * 9 + 10] |
761 | + d = key[4 * 9 + 11] |
762 | + t1 = (~a) % 0x100000000; |
763 | + t2 = b ^ d; |
764 | + t3 = c & t1; |
765 | + t13 = d | t1; |
766 | + e = t2 ^ t3; |
767 | + t5 = c ^ t1; |
768 | + t6 = c ^ e; |
769 | + t7 = b & t6; |
770 | + t10 = e | t5; |
771 | + h = t5 ^ t7; |
772 | + t9 = d | t7; |
773 | + t11 = t9 & t10; |
774 | + t14 = t2 ^ h; |
775 | + g = a ^ t11; |
776 | + t15 = g ^ t13; |
777 | + f = t14 ^ t15 |
778 | + key[4 * 9 + 8] = e |
779 | + key[4 * 9 + 9] = f |
780 | + key[4 * 9 + 10] = g |
781 | + key[4 * 9 + 11] = h |
782 | + a = key[4 * 10 + 8] |
783 | + b = key[4 * 10 + 9] |
784 | + c = key[4 * 10 + 10] |
785 | + d = key[4 * 10 + 11] |
786 | + t1 = (~a) % 0x100000000; |
787 | + t2 = b ^ t1; |
788 | + t3 = a | t2; |
789 | + t4 = d | t2; |
790 | + t5 = c ^ t3; |
791 | + g = d ^ t5; |
792 | + t7 = b ^ t4; |
793 | + t8 = t2 ^ g; |
794 | + t9 = t5 & t7; |
795 | + h = t8 ^ t9; |
796 | + t11 = t5 ^ t7; |
797 | + f = h ^ t11; |
798 | + t13 = t8 & t11; |
799 | + e = t5 ^ t13 |
800 | + key[4 * 10 + 8] = e |
801 | + key[4 * 10 + 9] = f |
802 | + key[4 * 10 + 10] = g |
803 | + key[4 * 10 + 11] = h |
804 | + a = key[4 * 11 + 8] |
805 | + b = key[4 * 11 + 9] |
806 | + c = key[4 * 11 + 10] |
807 | + d = key[4 * 11 + 11] |
808 | + t1 = a ^ d; |
809 | + t2 = a & d; |
810 | + t3 = c ^ t1; |
811 | + t6 = b & t1; |
812 | + t4 = b ^ t3; |
813 | + t10 = (~t3) % 0x100000000; |
814 | + h = t2 ^ t4; |
815 | + t7 = a ^ t6; |
816 | + t14 = (~t7) % 0x100000000; |
817 | + t8 = c | t7; |
818 | + t11 = t3 ^ t7; |
819 | + g = t4 ^ t8; |
820 | + t12 = h & t11; |
821 | + f = t10 ^ t12; |
822 | + e = t12 ^ t14 |
823 | + key[4 * 11 + 8] = e |
824 | + key[4 * 11 + 9] = f |
825 | + key[4 * 11 + 10] = g |
826 | + key[4 * 11 + 11] = h |
827 | + a = key[4 * 12 + 8] |
828 | + b = key[4 * 12 + 9] |
829 | + c = key[4 * 12 + 10] |
830 | + d = key[4 * 12 + 11] |
831 | + t1 = (~c) % 0x100000000; |
832 | + t2 = b ^ c; |
833 | + t3 = b | t1; |
834 | + t4 = d ^ t3; |
835 | + t5 = a & t4; |
836 | + t7 = a ^ d; |
837 | + h = t2 ^ t5; |
838 | + t8 = b ^ t5; |
839 | + t9 = t2 | t8; |
840 | + t11 = d & t3; |
841 | + f = t7 ^ t9; |
842 | + t12 = t5 ^ f; |
843 | + t15 = t1 | t4; |
844 | + t13 = h & t12; |
845 | + g = t11 ^ t13; |
846 | + t16 = t12 ^ g; |
847 | + e = t15 ^ t16 |
848 | + key[4 * 12 + 8] = e |
849 | + key[4 * 12 + 9] = f |
850 | + key[4 * 12 + 10] = g |
851 | + key[4 * 12 + 11] = h |
852 | + a = key[4 * 13 + 8] |
853 | + b = key[4 * 13 + 9] |
854 | + c = key[4 * 13 + 10] |
855 | + d = key[4 * 13 + 11] |
856 | + t1 = (~a) % 0x100000000; |
857 | + t2 = a ^ d; |
858 | + t3 = b ^ t2; |
859 | + t4 = t1 | t2; |
860 | + t5 = c ^ t4; |
861 | + f = b ^ t5; |
862 | + t13 = (~t5) % 0x100000000; |
863 | + t7 = t2 | f; |
864 | + t8 = d ^ t7; |
865 | + t9 = t5 & t8; |
866 | + g = t3 ^ t9; |
867 | + t11 = t5 ^ t8; |
868 | + e = g ^ t11; |
869 | + t14 = t3 & t11; |
870 | + h = t13 ^ t14 |
871 | + key[4 * 13 + 8] = e |
872 | + key[4 * 13 + 9] = f |
873 | + key[4 * 13 + 10] = g |
874 | + key[4 * 13 + 11] = h |
875 | + a = key[4 * 14 + 8] |
876 | + b = key[4 * 14 + 9] |
877 | + c = key[4 * 14 + 10] |
878 | + d = key[4 * 14 + 11] |
879 | + t1 = (~a) % 0x100000000; |
880 | + t2 = a ^ b; |
881 | + t3 = a ^ d; |
882 | + t4 = c ^ t1; |
883 | + t5 = t2 | t3; |
884 | + e = t4 ^ t5; |
885 | + t7 = d & e; |
886 | + t8 = t2 ^ e; |
887 | + t10 = t1 | e; |
888 | + f = t7 ^ t8; |
889 | + t11 = t2 | t7; |
890 | + t12 = t3 ^ t10; |
891 | + t14 = b ^ t7; |
892 | + g = t11 ^ t12; |
893 | + t15 = f & t12; |
894 | + h = t14 ^ t15 |
895 | + key[4 * 14 + 8] = e |
896 | + key[4 * 14 + 9] = f |
897 | + key[4 * 14 + 10] = g |
898 | + key[4 * 14 + 11] = h |
899 | + a = key[4 * 15 + 8] |
900 | + b = key[4 * 15 + 9] |
901 | + c = key[4 * 15 + 10] |
902 | + d = key[4 * 15 + 11] |
903 | + t1 = a ^ d; |
904 | + t2 = d & t1; |
905 | + t3 = c ^ t2; |
906 | + t4 = b | t3; |
907 | + h = t1 ^ t4; |
908 | + t6 = (~b) % 0x100000000; |
909 | + t7 = t1 | t6; |
910 | + e = t3 ^ t7; |
911 | + t9 = a & e; |
912 | + t10 = t1 ^ t6; |
913 | + t11 = t4 & t10; |
914 | + g = t9 ^ t11; |
915 | + t13 = a ^ t3; |
916 | + t14 = t10 & g; |
917 | + f = t13 ^ t14 |
918 | + key[4 * 15 + 8] = e |
919 | + key[4 * 15 + 9] = f |
920 | + key[4 * 15 + 10] = g |
921 | + key[4 * 15 + 11] = h |
922 | + a = key[4 * 16 + 8] |
923 | + b = key[4 * 16 + 9] |
924 | + c = key[4 * 16 + 10] |
925 | + d = key[4 * 16 + 11] |
926 | + t1 = a ^ c; |
927 | + t2 = d ^ t1; |
928 | + t3 = a & t2; |
929 | + t4 = d ^ t3; |
930 | + t5 = b & t4; |
931 | + g = t2 ^ t5; |
932 | + t7 = a | g; |
933 | + t8 = b | d; |
934 | + t11 = a | d; |
935 | + t9 = t4 & t7; |
936 | + f = t8 ^ t9; |
937 | + t12 = b ^ t11; |
938 | + t13 = g ^ t9; |
939 | + t15 = t3 ^ t8; |
940 | + h = t12 ^ t13; |
941 | + t16 = c & t15; |
942 | + e = t12 ^ t16 |
943 | + key[4 * 16 + 8] = e |
944 | + key[4 * 16 + 9] = f |
945 | + key[4 * 16 + 10] = g |
946 | + key[4 * 16 + 11] = h |
947 | + a = key[4 * 17 + 8] |
948 | + b = key[4 * 17 + 9] |
949 | + c = key[4 * 17 + 10] |
950 | + d = key[4 * 17 + 11] |
951 | + t1 = (~a) % 0x100000000; |
952 | + t2 = b ^ d; |
953 | + t3 = c & t1; |
954 | + t13 = d | t1; |
955 | + e = t2 ^ t3; |
956 | + t5 = c ^ t1; |
957 | + t6 = c ^ e; |
958 | + t7 = b & t6; |
959 | + t10 = e | t5; |
960 | + h = t5 ^ t7; |
961 | + t9 = d | t7; |
962 | + t11 = t9 & t10; |
963 | + t14 = t2 ^ h; |
964 | + g = a ^ t11; |
965 | + t15 = g ^ t13; |
966 | + f = t14 ^ t15 |
967 | + key[4 * 17 + 8] = e |
968 | + key[4 * 17 + 9] = f |
969 | + key[4 * 17 + 10] = g |
970 | + key[4 * 17 + 11] = h |
971 | + a = key[4 * 18 + 8] |
972 | + b = key[4 * 18 + 9] |
973 | + c = key[4 * 18 + 10] |
974 | + d = key[4 * 18 + 11] |
975 | + t1 = (~a) % 0x100000000; |
976 | + t2 = b ^ t1; |
977 | + t3 = a | t2; |
978 | + t4 = d | t2; |
979 | + t5 = c ^ t3; |
980 | + g = d ^ t5; |
981 | + t7 = b ^ t4; |
982 | + t8 = t2 ^ g; |
983 | + t9 = t5 & t7; |
984 | + h = t8 ^ t9; |
985 | + t11 = t5 ^ t7; |
986 | + f = h ^ t11; |
987 | + t13 = t8 & t11; |
988 | + e = t5 ^ t13 |
989 | + key[4 * 18 + 8] = e |
990 | + key[4 * 18 + 9] = f |
991 | + key[4 * 18 + 10] = g |
992 | + key[4 * 18 + 11] = h |
993 | + a = key[4 * 19 + 8] |
994 | + b = key[4 * 19 + 9] |
995 | + c = key[4 * 19 + 10] |
996 | + d = key[4 * 19 + 11] |
997 | + t1 = a ^ d; |
998 | + t2 = a & d; |
999 | + t3 = c ^ t1; |
1000 | + t6 = b & t1; |
1001 | + t4 = b ^ t3; |
1002 | + t10 = (~t3) % 0x100000000; |
1003 | + h = t2 ^ t4; |
1004 | + t7 = a ^ t6; |
1005 | + t14 = (~t7) % 0x100000000; |
1006 | + t8 = c | t7; |
1007 | + t11 = t3 ^ t7; |
1008 | + g = t4 ^ t8; |
1009 | + t12 = h & t11; |
1010 | + f = t10 ^ t12; |
1011 | + e = t12 ^ t14 |
1012 | + key[4 * 19 + 8] = e |
1013 | + key[4 * 19 + 9] = f |
1014 | + key[4 * 19 + 10] = g |
1015 | + key[4 * 19 + 11] = h |
1016 | + a = key[4 * 20 + 8] |
1017 | + b = key[4 * 20 + 9] |
1018 | + c = key[4 * 20 + 10] |
1019 | + d = key[4 * 20 + 11] |
1020 | + t1 = (~c) % 0x100000000; |
1021 | + t2 = b ^ c; |
1022 | + t3 = b | t1; |
1023 | + t4 = d ^ t3; |
1024 | + t5 = a & t4; |
1025 | + t7 = a ^ d; |
1026 | + h = t2 ^ t5; |
1027 | + t8 = b ^ t5; |
1028 | + t9 = t2 | t8; |
1029 | + t11 = d & t3; |
1030 | + f = t7 ^ t9; |
1031 | + t12 = t5 ^ f; |
1032 | + t15 = t1 | t4; |
1033 | + t13 = h & t12; |
1034 | + g = t11 ^ t13; |
1035 | + t16 = t12 ^ g; |
1036 | + e = t15 ^ t16 |
1037 | + key[4 * 20 + 8] = e |
1038 | + key[4 * 20 + 9] = f |
1039 | + key[4 * 20 + 10] = g |
1040 | + key[4 * 20 + 11] = h |
1041 | + a = key[4 * 21 + 8] |
1042 | + b = key[4 * 21 + 9] |
1043 | + c = key[4 * 21 + 10] |
1044 | + d = key[4 * 21 + 11] |
1045 | + t1 = (~a) % 0x100000000; |
1046 | + t2 = a ^ d; |
1047 | + t3 = b ^ t2; |
1048 | + t4 = t1 | t2; |
1049 | + t5 = c ^ t4; |
1050 | + f = b ^ t5; |
1051 | + t13 = (~t5) % 0x100000000; |
1052 | + t7 = t2 | f; |
1053 | + t8 = d ^ t7; |
1054 | + t9 = t5 & t8; |
1055 | + g = t3 ^ t9; |
1056 | + t11 = t5 ^ t8; |
1057 | + e = g ^ t11; |
1058 | + t14 = t3 & t11; |
1059 | + h = t13 ^ t14 |
1060 | + key[4 * 21 + 8] = e |
1061 | + key[4 * 21 + 9] = f |
1062 | + key[4 * 21 + 10] = g |
1063 | + key[4 * 21 + 11] = h |
1064 | + a = key[4 * 22 + 8] |
1065 | + b = key[4 * 22 + 9] |
1066 | + c = key[4 * 22 + 10] |
1067 | + d = key[4 * 22 + 11] |
1068 | + t1 = (~a) % 0x100000000; |
1069 | + t2 = a ^ b; |
1070 | + t3 = a ^ d; |
1071 | + t4 = c ^ t1; |
1072 | + t5 = t2 | t3; |
1073 | + e = t4 ^ t5; |
1074 | + t7 = d & e; |
1075 | + t8 = t2 ^ e; |
1076 | + t10 = t1 | e; |
1077 | + f = t7 ^ t8; |
1078 | + t11 = t2 | t7; |
1079 | + t12 = t3 ^ t10; |
1080 | + t14 = b ^ t7; |
1081 | + g = t11 ^ t12; |
1082 | + t15 = f & t12; |
1083 | + h = t14 ^ t15 |
1084 | + key[4 * 22 + 8] = e |
1085 | + key[4 * 22 + 9] = f |
1086 | + key[4 * 22 + 10] = g |
1087 | + key[4 * 22 + 11] = h |
1088 | + a = key[4 * 23 + 8] |
1089 | + b = key[4 * 23 + 9] |
1090 | + c = key[4 * 23 + 10] |
1091 | + d = key[4 * 23 + 11] |
1092 | + t1 = a ^ d; |
1093 | + t2 = d & t1; |
1094 | + t3 = c ^ t2; |
1095 | + t4 = b | t3; |
1096 | + h = t1 ^ t4; |
1097 | + t6 = (~b) % 0x100000000; |
1098 | + t7 = t1 | t6; |
1099 | + e = t3 ^ t7; |
1100 | + t9 = a & e; |
1101 | + t10 = t1 ^ t6; |
1102 | + t11 = t4 & t10; |
1103 | + g = t9 ^ t11; |
1104 | + t13 = a ^ t3; |
1105 | + t14 = t10 & g; |
1106 | + f = t13 ^ t14 |
1107 | + key[4 * 23 + 8] = e |
1108 | + key[4 * 23 + 9] = f |
1109 | + key[4 * 23 + 10] = g |
1110 | + key[4 * 23 + 11] = h |
1111 | + a = key[4 * 24 + 8] |
1112 | + b = key[4 * 24 + 9] |
1113 | + c = key[4 * 24 + 10] |
1114 | + d = key[4 * 24 + 11] |
1115 | + t1 = a ^ c; |
1116 | + t2 = d ^ t1; |
1117 | + t3 = a & t2; |
1118 | + t4 = d ^ t3; |
1119 | + t5 = b & t4; |
1120 | + g = t2 ^ t5; |
1121 | + t7 = a | g; |
1122 | + t8 = b | d; |
1123 | + t11 = a | d; |
1124 | + t9 = t4 & t7; |
1125 | + f = t8 ^ t9; |
1126 | + t12 = b ^ t11; |
1127 | + t13 = g ^ t9; |
1128 | + t15 = t3 ^ t8; |
1129 | + h = t12 ^ t13; |
1130 | + t16 = c & t15; |
1131 | + e = t12 ^ t16 |
1132 | + key[4 * 24 + 8] = e |
1133 | + key[4 * 24 + 9] = f |
1134 | + key[4 * 24 + 10] = g |
1135 | + key[4 * 24 + 11] = h |
1136 | + a = key[4 * 25 + 8] |
1137 | + b = key[4 * 25 + 9] |
1138 | + c = key[4 * 25 + 10] |
1139 | + d = key[4 * 25 + 11] |
1140 | + t1 = (~a) % 0x100000000; |
1141 | + t2 = b ^ d; |
1142 | + t3 = c & t1; |
1143 | + t13 = d | t1; |
1144 | + e = t2 ^ t3; |
1145 | + t5 = c ^ t1; |
1146 | + t6 = c ^ e; |
1147 | + t7 = b & t6; |
1148 | + t10 = e | t5; |
1149 | + h = t5 ^ t7; |
1150 | + t9 = d | t7; |
1151 | + t11 = t9 & t10; |
1152 | + t14 = t2 ^ h; |
1153 | + g = a ^ t11; |
1154 | + t15 = g ^ t13; |
1155 | + f = t14 ^ t15 |
1156 | + key[4 * 25 + 8] = e |
1157 | + key[4 * 25 + 9] = f |
1158 | + key[4 * 25 + 10] = g |
1159 | + key[4 * 25 + 11] = h |
1160 | + a = key[4 * 26 + 8] |
1161 | + b = key[4 * 26 + 9] |
1162 | + c = key[4 * 26 + 10] |
1163 | + d = key[4 * 26 + 11] |
1164 | + t1 = (~a) % 0x100000000; |
1165 | + t2 = b ^ t1; |
1166 | + t3 = a | t2; |
1167 | + t4 = d | t2; |
1168 | + t5 = c ^ t3; |
1169 | + g = d ^ t5; |
1170 | + t7 = b ^ t4; |
1171 | + t8 = t2 ^ g; |
1172 | + t9 = t5 & t7; |
1173 | + h = t8 ^ t9; |
1174 | + t11 = t5 ^ t7; |
1175 | + f = h ^ t11; |
1176 | + t13 = t8 & t11; |
1177 | + e = t5 ^ t13 |
1178 | + key[4 * 26 + 8] = e |
1179 | + key[4 * 26 + 9] = f |
1180 | + key[4 * 26 + 10] = g |
1181 | + key[4 * 26 + 11] = h |
1182 | + a = key[4 * 27 + 8] |
1183 | + b = key[4 * 27 + 9] |
1184 | + c = key[4 * 27 + 10] |
1185 | + d = key[4 * 27 + 11] |
1186 | + t1 = a ^ d; |
1187 | + t2 = a & d; |
1188 | + t3 = c ^ t1; |
1189 | + t6 = b & t1; |
1190 | + t4 = b ^ t3; |
1191 | + t10 = (~t3) % 0x100000000; |
1192 | + h = t2 ^ t4; |
1193 | + t7 = a ^ t6; |
1194 | + t14 = (~t7) % 0x100000000; |
1195 | + t8 = c | t7; |
1196 | + t11 = t3 ^ t7; |
1197 | + g = t4 ^ t8; |
1198 | + t12 = h & t11; |
1199 | + f = t10 ^ t12; |
1200 | + e = t12 ^ t14 |
1201 | + key[4 * 27 + 8] = e |
1202 | + key[4 * 27 + 9] = f |
1203 | + key[4 * 27 + 10] = g |
1204 | + key[4 * 27 + 11] = h |
1205 | + a = key[4 * 28 + 8] |
1206 | + b = key[4 * 28 + 9] |
1207 | + c = key[4 * 28 + 10] |
1208 | + d = key[4 * 28 + 11] |
1209 | + t1 = (~c) % 0x100000000; |
1210 | + t2 = b ^ c; |
1211 | + t3 = b | t1; |
1212 | + t4 = d ^ t3; |
1213 | + t5 = a & t4; |
1214 | + t7 = a ^ d; |
1215 | + h = t2 ^ t5; |
1216 | + t8 = b ^ t5; |
1217 | + t9 = t2 | t8; |
1218 | + t11 = d & t3; |
1219 | + f = t7 ^ t9; |
1220 | + t12 = t5 ^ f; |
1221 | + t15 = t1 | t4; |
1222 | + t13 = h & t12; |
1223 | + g = t11 ^ t13; |
1224 | + t16 = t12 ^ g; |
1225 | + e = t15 ^ t16 |
1226 | + key[4 * 28 + 8] = e |
1227 | + key[4 * 28 + 9] = f |
1228 | + key[4 * 28 + 10] = g |
1229 | + key[4 * 28 + 11] = h |
1230 | + a = key[4 * 29 + 8] |
1231 | + b = key[4 * 29 + 9] |
1232 | + c = key[4 * 29 + 10] |
1233 | + d = key[4 * 29 + 11] |
1234 | + t1 = (~a) % 0x100000000; |
1235 | + t2 = a ^ d; |
1236 | + t3 = b ^ t2; |
1237 | + t4 = t1 | t2; |
1238 | + t5 = c ^ t4; |
1239 | + f = b ^ t5; |
1240 | + t13 = (~t5) % 0x100000000; |
1241 | + t7 = t2 | f; |
1242 | + t8 = d ^ t7; |
1243 | + t9 = t5 & t8; |
1244 | + g = t3 ^ t9; |
1245 | + t11 = t5 ^ t8; |
1246 | + e = g ^ t11; |
1247 | + t14 = t3 & t11; |
1248 | + h = t13 ^ t14 |
1249 | + key[4 * 29 + 8] = e |
1250 | + key[4 * 29 + 9] = f |
1251 | + key[4 * 29 + 10] = g |
1252 | + key[4 * 29 + 11] = h |
1253 | + a = key[4 * 30 + 8] |
1254 | + b = key[4 * 30 + 9] |
1255 | + c = key[4 * 30 + 10] |
1256 | + d = key[4 * 30 + 11] |
1257 | + t1 = (~a) % 0x100000000; |
1258 | + t2 = a ^ b; |
1259 | + t3 = a ^ d; |
1260 | + t4 = c ^ t1; |
1261 | + t5 = t2 | t3; |
1262 | + e = t4 ^ t5; |
1263 | + t7 = d & e; |
1264 | + t8 = t2 ^ e; |
1265 | + t10 = t1 | e; |
1266 | + f = t7 ^ t8; |
1267 | + t11 = t2 | t7; |
1268 | + t12 = t3 ^ t10; |
1269 | + t14 = b ^ t7; |
1270 | + g = t11 ^ t12; |
1271 | + t15 = f & t12; |
1272 | + h = t14 ^ t15 |
1273 | + key[4 * 30 + 8] = e |
1274 | + key[4 * 30 + 9] = f |
1275 | + key[4 * 30 + 10] = g |
1276 | + key[4 * 30 + 11] = h |
1277 | + a = key[4 * 31 + 8] |
1278 | + b = key[4 * 31 + 9] |
1279 | + c = key[4 * 31 + 10] |
1280 | + d = key[4 * 31 + 11] |
1281 | + t1 = a ^ d; |
1282 | + t2 = d & t1; |
1283 | + t3 = c ^ t2; |
1284 | + t4 = b | t3; |
1285 | + h = t1 ^ t4; |
1286 | + t6 = (~b) % 0x100000000; |
1287 | + t7 = t1 | t6; |
1288 | + e = t3 ^ t7; |
1289 | + t9 = a & e; |
1290 | + t10 = t1 ^ t6; |
1291 | + t11 = t4 & t10; |
1292 | + g = t9 ^ t11; |
1293 | + t13 = a ^ t3; |
1294 | + t14 = t10 & g; |
1295 | + f = t13 ^ t14 |
1296 | + key[4 * 31 + 8] = e |
1297 | + key[4 * 31 + 9] = f |
1298 | + key[4 * 31 + 10] = g |
1299 | + key[4 * 31 + 11] = h |
1300 | + a = key[4 * 32 + 8] |
1301 | + b = key[4 * 32 + 9] |
1302 | + c = key[4 * 32 + 10] |
1303 | + d = key[4 * 32 + 11] |
1304 | + t1 = a ^ c; |
1305 | + t2 = d ^ t1; |
1306 | + t3 = a & t2; |
1307 | + t4 = d ^ t3; |
1308 | + t5 = b & t4; |
1309 | + g = t2 ^ t5; |
1310 | + t7 = a | g; |
1311 | + t8 = b | d; |
1312 | + t11 = a | d; |
1313 | + t9 = t4 & t7; |
1314 | + f = t8 ^ t9; |
1315 | + t12 = b ^ t11; |
1316 | + t13 = g ^ t9; |
1317 | + t15 = t3 ^ t8; |
1318 | + h = t12 ^ t13; |
1319 | + t16 = c & t15; |
1320 | + e = t12 ^ t16 |
1321 | + key[4 * 32 + 8] = e |
1322 | + key[4 * 32 + 9] = f |
1323 | + key[4 * 32 + 10] = g |
1324 | + key[4 * 32 + 11] = h |
1325 | + |
1326 | +def encrypt(key, in_blk): |
1327 | + # serpent_generate.py |
1328 | + a = in_blk[0] |
1329 | + b = in_blk[1] |
1330 | + c = in_blk[2] |
1331 | + d = in_blk[3] |
1332 | + if WORD_BIGENDIAN: |
1333 | + a = byteswap32(a) |
1334 | + b = byteswap32(b) |
1335 | + c = byteswap32(c) |
1336 | + d = byteswap32(d) |
1337 | + e = 0 |
1338 | + f = 0 |
1339 | + g = 0 |
1340 | + h = 0 |
1341 | + t1 = 0 |
1342 | + t2 = 0 |
1343 | + t3 = 0 |
1344 | + t4 = 0 |
1345 | + t5 = 0 |
1346 | + t6 = 0 |
1347 | + t7 = 0 |
1348 | + t8 = 0 |
1349 | + t9 = 0 |
1350 | + t10 = 0 |
1351 | + t11 = 0 |
1352 | + t12 = 0 |
1353 | + t13 = 0 |
1354 | + t14 = 0 |
1355 | + t15 = 0 |
1356 | + t16 = 0 |
1357 | + a ^= key[4 * 0 + 8] |
1358 | + b ^= key[4 * 0 + 9] |
1359 | + c ^= key[4 * 0 + 10] |
1360 | + d ^= key[4 * 0 + 11] |
1361 | + t1 = a ^ d; |
1362 | + t2 = a & d; |
1363 | + t3 = c ^ t1; |
1364 | + t6 = b & t1; |
1365 | + t4 = b ^ t3; |
1366 | + t10 = (~t3) % 0x100000000; |
1367 | + h = t2 ^ t4; |
1368 | + t7 = a ^ t6; |
1369 | + t14 = (~t7) % 0x100000000; |
1370 | + t8 = c | t7; |
1371 | + t11 = t3 ^ t7; |
1372 | + g = t4 ^ t8; |
1373 | + t12 = h & t11; |
1374 | + f = t10 ^ t12; |
1375 | + e = t12 ^ t14 |
1376 | + e = rotl32(e, 13) |
1377 | + g = rotl32(g, 3) |
1378 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
1379 | + f ^= e ^ g |
1380 | + h = rotl32(h, 7) |
1381 | + f = rotl32(f, 1) |
1382 | + e ^= f ^ h |
1383 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
1384 | + e = rotl32(e, 5) |
1385 | + g = rotl32(g, 22) |
1386 | + e ^= key[4 * 1 + 8] |
1387 | + f ^= key[4 * 1 + 9] |
1388 | + g ^= key[4 * 1 + 10] |
1389 | + h ^= key[4 * 1 + 11] |
1390 | + t1 = (~e) % 0x100000000; |
1391 | + t2 = f ^ t1; |
1392 | + t3 = e | t2; |
1393 | + t4 = h | t2; |
1394 | + t5 = g ^ t3; |
1395 | + c = h ^ t5; |
1396 | + t7 = f ^ t4; |
1397 | + t8 = t2 ^ c; |
1398 | + t9 = t5 & t7; |
1399 | + d = t8 ^ t9; |
1400 | + t11 = t5 ^ t7; |
1401 | + b = d ^ t11; |
1402 | + t13 = t8 & t11; |
1403 | + a = t5 ^ t13 |
1404 | + a = rotl32(a, 13) |
1405 | + c = rotl32(c, 3) |
1406 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
1407 | + b ^= a ^ c |
1408 | + d = rotl32(d, 7) |
1409 | + b = rotl32(b, 1) |
1410 | + a ^= b ^ d |
1411 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
1412 | + a = rotl32(a, 5) |
1413 | + c = rotl32(c, 22) |
1414 | + a ^= key[4 * 2 + 8] |
1415 | + b ^= key[4 * 2 + 9] |
1416 | + c ^= key[4 * 2 + 10] |
1417 | + d ^= key[4 * 2 + 11] |
1418 | + t1 = (~a) % 0x100000000; |
1419 | + t2 = b ^ d; |
1420 | + t3 = c & t1; |
1421 | + t13 = d | t1; |
1422 | + e = t2 ^ t3; |
1423 | + t5 = c ^ t1; |
1424 | + t6 = c ^ e; |
1425 | + t7 = b & t6; |
1426 | + t10 = e | t5; |
1427 | + h = t5 ^ t7; |
1428 | + t9 = d | t7; |
1429 | + t11 = t9 & t10; |
1430 | + t14 = t2 ^ h; |
1431 | + g = a ^ t11; |
1432 | + t15 = g ^ t13; |
1433 | + f = t14 ^ t15 |
1434 | + e = rotl32(e, 13) |
1435 | + g = rotl32(g, 3) |
1436 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
1437 | + f ^= e ^ g |
1438 | + h = rotl32(h, 7) |
1439 | + f = rotl32(f, 1) |
1440 | + e ^= f ^ h |
1441 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
1442 | + e = rotl32(e, 5) |
1443 | + g = rotl32(g, 22) |
1444 | + e ^= key[4 * 3 + 8] |
1445 | + f ^= key[4 * 3 + 9] |
1446 | + g ^= key[4 * 3 + 10] |
1447 | + h ^= key[4 * 3 + 11] |
1448 | + t1 = e ^ g; |
1449 | + t2 = h ^ t1; |
1450 | + t3 = e & t2; |
1451 | + t4 = h ^ t3; |
1452 | + t5 = f & t4; |
1453 | + c = t2 ^ t5; |
1454 | + t7 = e | c; |
1455 | + t8 = f | h; |
1456 | + t11 = e | h; |
1457 | + t9 = t4 & t7; |
1458 | + b = t8 ^ t9; |
1459 | + t12 = f ^ t11; |
1460 | + t13 = c ^ t9; |
1461 | + t15 = t3 ^ t8; |
1462 | + d = t12 ^ t13; |
1463 | + t16 = g & t15; |
1464 | + a = t12 ^ t16 |
1465 | + a = rotl32(a, 13) |
1466 | + c = rotl32(c, 3) |
1467 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
1468 | + b ^= a ^ c |
1469 | + d = rotl32(d, 7) |
1470 | + b = rotl32(b, 1) |
1471 | + a ^= b ^ d |
1472 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
1473 | + a = rotl32(a, 5) |
1474 | + c = rotl32(c, 22) |
1475 | + a ^= key[4 * 4 + 8] |
1476 | + b ^= key[4 * 4 + 9] |
1477 | + c ^= key[4 * 4 + 10] |
1478 | + d ^= key[4 * 4 + 11] |
1479 | + t1 = a ^ d; |
1480 | + t2 = d & t1; |
1481 | + t3 = c ^ t2; |
1482 | + t4 = b | t3; |
1483 | + h = t1 ^ t4; |
1484 | + t6 = (~b) % 0x100000000; |
1485 | + t7 = t1 | t6; |
1486 | + e = t3 ^ t7; |
1487 | + t9 = a & e; |
1488 | + t10 = t1 ^ t6; |
1489 | + t11 = t4 & t10; |
1490 | + g = t9 ^ t11; |
1491 | + t13 = a ^ t3; |
1492 | + t14 = t10 & g; |
1493 | + f = t13 ^ t14 |
1494 | + e = rotl32(e, 13) |
1495 | + g = rotl32(g, 3) |
1496 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
1497 | + f ^= e ^ g |
1498 | + h = rotl32(h, 7) |
1499 | + f = rotl32(f, 1) |
1500 | + e ^= f ^ h |
1501 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
1502 | + e = rotl32(e, 5) |
1503 | + g = rotl32(g, 22) |
1504 | + e ^= key[4 * 5 + 8] |
1505 | + f ^= key[4 * 5 + 9] |
1506 | + g ^= key[4 * 5 + 10] |
1507 | + h ^= key[4 * 5 + 11] |
1508 | + t1 = (~e) % 0x100000000; |
1509 | + t2 = e ^ f; |
1510 | + t3 = e ^ h; |
1511 | + t4 = g ^ t1; |
1512 | + t5 = t2 | t3; |
1513 | + a = t4 ^ t5; |
1514 | + t7 = h & a; |
1515 | + t8 = t2 ^ a; |
1516 | + t10 = t1 | a; |
1517 | + b = t7 ^ t8; |
1518 | + t11 = t2 | t7; |
1519 | + t12 = t3 ^ t10; |
1520 | + t14 = f ^ t7; |
1521 | + c = t11 ^ t12; |
1522 | + t15 = b & t12; |
1523 | + d = t14 ^ t15 |
1524 | + a = rotl32(a, 13) |
1525 | + c = rotl32(c, 3) |
1526 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
1527 | + b ^= a ^ c |
1528 | + d = rotl32(d, 7) |
1529 | + b = rotl32(b, 1) |
1530 | + a ^= b ^ d |
1531 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
1532 | + a = rotl32(a, 5) |
1533 | + c = rotl32(c, 22) |
1534 | + a ^= key[4 * 6 + 8] |
1535 | + b ^= key[4 * 6 + 9] |
1536 | + c ^= key[4 * 6 + 10] |
1537 | + d ^= key[4 * 6 + 11] |
1538 | + t1 = (~a) % 0x100000000; |
1539 | + t2 = a ^ d; |
1540 | + t3 = b ^ t2; |
1541 | + t4 = t1 | t2; |
1542 | + t5 = c ^ t4; |
1543 | + f = b ^ t5; |
1544 | + t13 = (~t5) % 0x100000000; |
1545 | + t7 = t2 | f; |
1546 | + t8 = d ^ t7; |
1547 | + t9 = t5 & t8; |
1548 | + g = t3 ^ t9; |
1549 | + t11 = t5 ^ t8; |
1550 | + e = g ^ t11; |
1551 | + t14 = t3 & t11; |
1552 | + h = t13 ^ t14 |
1553 | + e = rotl32(e, 13) |
1554 | + g = rotl32(g, 3) |
1555 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
1556 | + f ^= e ^ g |
1557 | + h = rotl32(h, 7) |
1558 | + f = rotl32(f, 1) |
1559 | + e ^= f ^ h |
1560 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
1561 | + e = rotl32(e, 5) |
1562 | + g = rotl32(g, 22) |
1563 | + e ^= key[4 * 7 + 8] |
1564 | + f ^= key[4 * 7 + 9] |
1565 | + g ^= key[4 * 7 + 10] |
1566 | + h ^= key[4 * 7 + 11] |
1567 | + t1 = (~g) % 0x100000000; |
1568 | + t2 = f ^ g; |
1569 | + t3 = f | t1; |
1570 | + t4 = h ^ t3; |
1571 | + t5 = e & t4; |
1572 | + t7 = e ^ h; |
1573 | + d = t2 ^ t5; |
1574 | + t8 = f ^ t5; |
1575 | + t9 = t2 | t8; |
1576 | + t11 = h & t3; |
1577 | + b = t7 ^ t9; |
1578 | + t12 = t5 ^ b; |
1579 | + t15 = t1 | t4; |
1580 | + t13 = d & t12; |
1581 | + c = t11 ^ t13; |
1582 | + t16 = t12 ^ c; |
1583 | + a = t15 ^ t16 |
1584 | + a = rotl32(a, 13) |
1585 | + c = rotl32(c, 3) |
1586 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
1587 | + b ^= a ^ c |
1588 | + d = rotl32(d, 7) |
1589 | + b = rotl32(b, 1) |
1590 | + a ^= b ^ d |
1591 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
1592 | + a = rotl32(a, 5) |
1593 | + c = rotl32(c, 22) |
1594 | + a ^= key[4 * 8 + 8] |
1595 | + b ^= key[4 * 8 + 9] |
1596 | + c ^= key[4 * 8 + 10] |
1597 | + d ^= key[4 * 8 + 11] |
1598 | + t1 = a ^ d; |
1599 | + t2 = a & d; |
1600 | + t3 = c ^ t1; |
1601 | + t6 = b & t1; |
1602 | + t4 = b ^ t3; |
1603 | + t10 = (~t3) % 0x100000000; |
1604 | + h = t2 ^ t4; |
1605 | + t7 = a ^ t6; |
1606 | + t14 = (~t7) % 0x100000000; |
1607 | + t8 = c | t7; |
1608 | + t11 = t3 ^ t7; |
1609 | + g = t4 ^ t8; |
1610 | + t12 = h & t11; |
1611 | + f = t10 ^ t12; |
1612 | + e = t12 ^ t14 |
1613 | + e = rotl32(e, 13) |
1614 | + g = rotl32(g, 3) |
1615 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
1616 | + f ^= e ^ g |
1617 | + h = rotl32(h, 7) |
1618 | + f = rotl32(f, 1) |
1619 | + e ^= f ^ h |
1620 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
1621 | + e = rotl32(e, 5) |
1622 | + g = rotl32(g, 22) |
1623 | + e ^= key[4 * 9 + 8] |
1624 | + f ^= key[4 * 9 + 9] |
1625 | + g ^= key[4 * 9 + 10] |
1626 | + h ^= key[4 * 9 + 11] |
1627 | + t1 = (~e) % 0x100000000; |
1628 | + t2 = f ^ t1; |
1629 | + t3 = e | t2; |
1630 | + t4 = h | t2; |
1631 | + t5 = g ^ t3; |
1632 | + c = h ^ t5; |
1633 | + t7 = f ^ t4; |
1634 | + t8 = t2 ^ c; |
1635 | + t9 = t5 & t7; |
1636 | + d = t8 ^ t9; |
1637 | + t11 = t5 ^ t7; |
1638 | + b = d ^ t11; |
1639 | + t13 = t8 & t11; |
1640 | + a = t5 ^ t13 |
1641 | + a = rotl32(a, 13) |
1642 | + c = rotl32(c, 3) |
1643 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
1644 | + b ^= a ^ c |
1645 | + d = rotl32(d, 7) |
1646 | + b = rotl32(b, 1) |
1647 | + a ^= b ^ d |
1648 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
1649 | + a = rotl32(a, 5) |
1650 | + c = rotl32(c, 22) |
1651 | + a ^= key[4 * 10 + 8] |
1652 | + b ^= key[4 * 10 + 9] |
1653 | + c ^= key[4 * 10 + 10] |
1654 | + d ^= key[4 * 10 + 11] |
1655 | + t1 = (~a) % 0x100000000; |
1656 | + t2 = b ^ d; |
1657 | + t3 = c & t1; |
1658 | + t13 = d | t1; |
1659 | + e = t2 ^ t3; |
1660 | + t5 = c ^ t1; |
1661 | + t6 = c ^ e; |
1662 | + t7 = b & t6; |
1663 | + t10 = e | t5; |
1664 | + h = t5 ^ t7; |
1665 | + t9 = d | t7; |
1666 | + t11 = t9 & t10; |
1667 | + t14 = t2 ^ h; |
1668 | + g = a ^ t11; |
1669 | + t15 = g ^ t13; |
1670 | + f = t14 ^ t15 |
1671 | + e = rotl32(e, 13) |
1672 | + g = rotl32(g, 3) |
1673 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
1674 | + f ^= e ^ g |
1675 | + h = rotl32(h, 7) |
1676 | + f = rotl32(f, 1) |
1677 | + e ^= f ^ h |
1678 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
1679 | + e = rotl32(e, 5) |
1680 | + g = rotl32(g, 22) |
1681 | + e ^= key[4 * 11 + 8] |
1682 | + f ^= key[4 * 11 + 9] |
1683 | + g ^= key[4 * 11 + 10] |
1684 | + h ^= key[4 * 11 + 11] |
1685 | + t1 = e ^ g; |
1686 | + t2 = h ^ t1; |
1687 | + t3 = e & t2; |
1688 | + t4 = h ^ t3; |
1689 | + t5 = f & t4; |
1690 | + c = t2 ^ t5; |
1691 | + t7 = e | c; |
1692 | + t8 = f | h; |
1693 | + t11 = e | h; |
1694 | + t9 = t4 & t7; |
1695 | + b = t8 ^ t9; |
1696 | + t12 = f ^ t11; |
1697 | + t13 = c ^ t9; |
1698 | + t15 = t3 ^ t8; |
1699 | + d = t12 ^ t13; |
1700 | + t16 = g & t15; |
1701 | + a = t12 ^ t16 |
1702 | + a = rotl32(a, 13) |
1703 | + c = rotl32(c, 3) |
1704 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
1705 | + b ^= a ^ c |
1706 | + d = rotl32(d, 7) |
1707 | + b = rotl32(b, 1) |
1708 | + a ^= b ^ d |
1709 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
1710 | + a = rotl32(a, 5) |
1711 | + c = rotl32(c, 22) |
1712 | + a ^= key[4 * 12 + 8] |
1713 | + b ^= key[4 * 12 + 9] |
1714 | + c ^= key[4 * 12 + 10] |
1715 | + d ^= key[4 * 12 + 11] |
1716 | + t1 = a ^ d; |
1717 | + t2 = d & t1; |
1718 | + t3 = c ^ t2; |
1719 | + t4 = b | t3; |
1720 | + h = t1 ^ t4; |
1721 | + t6 = (~b) % 0x100000000; |
1722 | + t7 = t1 | t6; |
1723 | + e = t3 ^ t7; |
1724 | + t9 = a & e; |
1725 | + t10 = t1 ^ t6; |
1726 | + t11 = t4 & t10; |
1727 | + g = t9 ^ t11; |
1728 | + t13 = a ^ t3; |
1729 | + t14 = t10 & g; |
1730 | + f = t13 ^ t14 |
1731 | + e = rotl32(e, 13) |
1732 | + g = rotl32(g, 3) |
1733 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
1734 | + f ^= e ^ g |
1735 | + h = rotl32(h, 7) |
1736 | + f = rotl32(f, 1) |
1737 | + e ^= f ^ h |
1738 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
1739 | + e = rotl32(e, 5) |
1740 | + g = rotl32(g, 22) |
1741 | + e ^= key[4 * 13 + 8] |
1742 | + f ^= key[4 * 13 + 9] |
1743 | + g ^= key[4 * 13 + 10] |
1744 | + h ^= key[4 * 13 + 11] |
1745 | + t1 = (~e) % 0x100000000; |
1746 | + t2 = e ^ f; |
1747 | + t3 = e ^ h; |
1748 | + t4 = g ^ t1; |
1749 | + t5 = t2 | t3; |
1750 | + a = t4 ^ t5; |
1751 | + t7 = h & a; |
1752 | + t8 = t2 ^ a; |
1753 | + t10 = t1 | a; |
1754 | + b = t7 ^ t8; |
1755 | + t11 = t2 | t7; |
1756 | + t12 = t3 ^ t10; |
1757 | + t14 = f ^ t7; |
1758 | + c = t11 ^ t12; |
1759 | + t15 = b & t12; |
1760 | + d = t14 ^ t15 |
1761 | + a = rotl32(a, 13) |
1762 | + c = rotl32(c, 3) |
1763 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
1764 | + b ^= a ^ c |
1765 | + d = rotl32(d, 7) |
1766 | + b = rotl32(b, 1) |
1767 | + a ^= b ^ d |
1768 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
1769 | + a = rotl32(a, 5) |
1770 | + c = rotl32(c, 22) |
1771 | + a ^= key[4 * 14 + 8] |
1772 | + b ^= key[4 * 14 + 9] |
1773 | + c ^= key[4 * 14 + 10] |
1774 | + d ^= key[4 * 14 + 11] |
1775 | + t1 = (~a) % 0x100000000; |
1776 | + t2 = a ^ d; |
1777 | + t3 = b ^ t2; |
1778 | + t4 = t1 | t2; |
1779 | + t5 = c ^ t4; |
1780 | + f = b ^ t5; |
1781 | + t13 = (~t5) % 0x100000000; |
1782 | + t7 = t2 | f; |
1783 | + t8 = d ^ t7; |
1784 | + t9 = t5 & t8; |
1785 | + g = t3 ^ t9; |
1786 | + t11 = t5 ^ t8; |
1787 | + e = g ^ t11; |
1788 | + t14 = t3 & t11; |
1789 | + h = t13 ^ t14 |
1790 | + e = rotl32(e, 13) |
1791 | + g = rotl32(g, 3) |
1792 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
1793 | + f ^= e ^ g |
1794 | + h = rotl32(h, 7) |
1795 | + f = rotl32(f, 1) |
1796 | + e ^= f ^ h |
1797 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
1798 | + e = rotl32(e, 5) |
1799 | + g = rotl32(g, 22) |
1800 | + e ^= key[4 * 15 + 8] |
1801 | + f ^= key[4 * 15 + 9] |
1802 | + g ^= key[4 * 15 + 10] |
1803 | + h ^= key[4 * 15 + 11] |
1804 | + t1 = (~g) % 0x100000000; |
1805 | + t2 = f ^ g; |
1806 | + t3 = f | t1; |
1807 | + t4 = h ^ t3; |
1808 | + t5 = e & t4; |
1809 | + t7 = e ^ h; |
1810 | + d = t2 ^ t5; |
1811 | + t8 = f ^ t5; |
1812 | + t9 = t2 | t8; |
1813 | + t11 = h & t3; |
1814 | + b = t7 ^ t9; |
1815 | + t12 = t5 ^ b; |
1816 | + t15 = t1 | t4; |
1817 | + t13 = d & t12; |
1818 | + c = t11 ^ t13; |
1819 | + t16 = t12 ^ c; |
1820 | + a = t15 ^ t16 |
1821 | + a = rotl32(a, 13) |
1822 | + c = rotl32(c, 3) |
1823 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
1824 | + b ^= a ^ c |
1825 | + d = rotl32(d, 7) |
1826 | + b = rotl32(b, 1) |
1827 | + a ^= b ^ d |
1828 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
1829 | + a = rotl32(a, 5) |
1830 | + c = rotl32(c, 22) |
1831 | + a ^= key[4 * 16 + 8] |
1832 | + b ^= key[4 * 16 + 9] |
1833 | + c ^= key[4 * 16 + 10] |
1834 | + d ^= key[4 * 16 + 11] |
1835 | + t1 = a ^ d; |
1836 | + t2 = a & d; |
1837 | + t3 = c ^ t1; |
1838 | + t6 = b & t1; |
1839 | + t4 = b ^ t3; |
1840 | + t10 = (~t3) % 0x100000000; |
1841 | + h = t2 ^ t4; |
1842 | + t7 = a ^ t6; |
1843 | + t14 = (~t7) % 0x100000000; |
1844 | + t8 = c | t7; |
1845 | + t11 = t3 ^ t7; |
1846 | + g = t4 ^ t8; |
1847 | + t12 = h & t11; |
1848 | + f = t10 ^ t12; |
1849 | + e = t12 ^ t14 |
1850 | + e = rotl32(e, 13) |
1851 | + g = rotl32(g, 3) |
1852 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
1853 | + f ^= e ^ g |
1854 | + h = rotl32(h, 7) |
1855 | + f = rotl32(f, 1) |
1856 | + e ^= f ^ h |
1857 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
1858 | + e = rotl32(e, 5) |
1859 | + g = rotl32(g, 22) |
1860 | + e ^= key[4 * 17 + 8] |
1861 | + f ^= key[4 * 17 + 9] |
1862 | + g ^= key[4 * 17 + 10] |
1863 | + h ^= key[4 * 17 + 11] |
1864 | + t1 = (~e) % 0x100000000; |
1865 | + t2 = f ^ t1; |
1866 | + t3 = e | t2; |
1867 | + t4 = h | t2; |
1868 | + t5 = g ^ t3; |
1869 | + c = h ^ t5; |
1870 | + t7 = f ^ t4; |
1871 | + t8 = t2 ^ c; |
1872 | + t9 = t5 & t7; |
1873 | + d = t8 ^ t9; |
1874 | + t11 = t5 ^ t7; |
1875 | + b = d ^ t11; |
1876 | + t13 = t8 & t11; |
1877 | + a = t5 ^ t13 |
1878 | + a = rotl32(a, 13) |
1879 | + c = rotl32(c, 3) |
1880 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
1881 | + b ^= a ^ c |
1882 | + d = rotl32(d, 7) |
1883 | + b = rotl32(b, 1) |
1884 | + a ^= b ^ d |
1885 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
1886 | + a = rotl32(a, 5) |
1887 | + c = rotl32(c, 22) |
1888 | + a ^= key[4 * 18 + 8] |
1889 | + b ^= key[4 * 18 + 9] |
1890 | + c ^= key[4 * 18 + 10] |
1891 | + d ^= key[4 * 18 + 11] |
1892 | + t1 = (~a) % 0x100000000; |
1893 | + t2 = b ^ d; |
1894 | + t3 = c & t1; |
1895 | + t13 = d | t1; |
1896 | + e = t2 ^ t3; |
1897 | + t5 = c ^ t1; |
1898 | + t6 = c ^ e; |
1899 | + t7 = b & t6; |
1900 | + t10 = e | t5; |
1901 | + h = t5 ^ t7; |
1902 | + t9 = d | t7; |
1903 | + t11 = t9 & t10; |
1904 | + t14 = t2 ^ h; |
1905 | + g = a ^ t11; |
1906 | + t15 = g ^ t13; |
1907 | + f = t14 ^ t15 |
1908 | + e = rotl32(e, 13) |
1909 | + g = rotl32(g, 3) |
1910 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
1911 | + f ^= e ^ g |
1912 | + h = rotl32(h, 7) |
1913 | + f = rotl32(f, 1) |
1914 | + e ^= f ^ h |
1915 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
1916 | + e = rotl32(e, 5) |
1917 | + g = rotl32(g, 22) |
1918 | + e ^= key[4 * 19 + 8] |
1919 | + f ^= key[4 * 19 + 9] |
1920 | + g ^= key[4 * 19 + 10] |
1921 | + h ^= key[4 * 19 + 11] |
1922 | + t1 = e ^ g; |
1923 | + t2 = h ^ t1; |
1924 | + t3 = e & t2; |
1925 | + t4 = h ^ t3; |
1926 | + t5 = f & t4; |
1927 | + c = t2 ^ t5; |
1928 | + t7 = e | c; |
1929 | + t8 = f | h; |
1930 | + t11 = e | h; |
1931 | + t9 = t4 & t7; |
1932 | + b = t8 ^ t9; |
1933 | + t12 = f ^ t11; |
1934 | + t13 = c ^ t9; |
1935 | + t15 = t3 ^ t8; |
1936 | + d = t12 ^ t13; |
1937 | + t16 = g & t15; |
1938 | + a = t12 ^ t16 |
1939 | + a = rotl32(a, 13) |
1940 | + c = rotl32(c, 3) |
1941 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
1942 | + b ^= a ^ c |
1943 | + d = rotl32(d, 7) |
1944 | + b = rotl32(b, 1) |
1945 | + a ^= b ^ d |
1946 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
1947 | + a = rotl32(a, 5) |
1948 | + c = rotl32(c, 22) |
1949 | + a ^= key[4 * 20 + 8] |
1950 | + b ^= key[4 * 20 + 9] |
1951 | + c ^= key[4 * 20 + 10] |
1952 | + d ^= key[4 * 20 + 11] |
1953 | + t1 = a ^ d; |
1954 | + t2 = d & t1; |
1955 | + t3 = c ^ t2; |
1956 | + t4 = b | t3; |
1957 | + h = t1 ^ t4; |
1958 | + t6 = (~b) % 0x100000000; |
1959 | + t7 = t1 | t6; |
1960 | + e = t3 ^ t7; |
1961 | + t9 = a & e; |
1962 | + t10 = t1 ^ t6; |
1963 | + t11 = t4 & t10; |
1964 | + g = t9 ^ t11; |
1965 | + t13 = a ^ t3; |
1966 | + t14 = t10 & g; |
1967 | + f = t13 ^ t14 |
1968 | + e = rotl32(e, 13) |
1969 | + g = rotl32(g, 3) |
1970 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
1971 | + f ^= e ^ g |
1972 | + h = rotl32(h, 7) |
1973 | + f = rotl32(f, 1) |
1974 | + e ^= f ^ h |
1975 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
1976 | + e = rotl32(e, 5) |
1977 | + g = rotl32(g, 22) |
1978 | + e ^= key[4 * 21 + 8] |
1979 | + f ^= key[4 * 21 + 9] |
1980 | + g ^= key[4 * 21 + 10] |
1981 | + h ^= key[4 * 21 + 11] |
1982 | + t1 = (~e) % 0x100000000; |
1983 | + t2 = e ^ f; |
1984 | + t3 = e ^ h; |
1985 | + t4 = g ^ t1; |
1986 | + t5 = t2 | t3; |
1987 | + a = t4 ^ t5; |
1988 | + t7 = h & a; |
1989 | + t8 = t2 ^ a; |
1990 | + t10 = t1 | a; |
1991 | + b = t7 ^ t8; |
1992 | + t11 = t2 | t7; |
1993 | + t12 = t3 ^ t10; |
1994 | + t14 = f ^ t7; |
1995 | + c = t11 ^ t12; |
1996 | + t15 = b & t12; |
1997 | + d = t14 ^ t15 |
1998 | + a = rotl32(a, 13) |
1999 | + c = rotl32(c, 3) |
2000 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
2001 | + b ^= a ^ c |
2002 | + d = rotl32(d, 7) |
2003 | + b = rotl32(b, 1) |
2004 | + a ^= b ^ d |
2005 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
2006 | + a = rotl32(a, 5) |
2007 | + c = rotl32(c, 22) |
2008 | + a ^= key[4 * 22 + 8] |
2009 | + b ^= key[4 * 22 + 9] |
2010 | + c ^= key[4 * 22 + 10] |
2011 | + d ^= key[4 * 22 + 11] |
2012 | + t1 = (~a) % 0x100000000; |
2013 | + t2 = a ^ d; |
2014 | + t3 = b ^ t2; |
2015 | + t4 = t1 | t2; |
2016 | + t5 = c ^ t4; |
2017 | + f = b ^ t5; |
2018 | + t13 = (~t5) % 0x100000000; |
2019 | + t7 = t2 | f; |
2020 | + t8 = d ^ t7; |
2021 | + t9 = t5 & t8; |
2022 | + g = t3 ^ t9; |
2023 | + t11 = t5 ^ t8; |
2024 | + e = g ^ t11; |
2025 | + t14 = t3 & t11; |
2026 | + h = t13 ^ t14 |
2027 | + e = rotl32(e, 13) |
2028 | + g = rotl32(g, 3) |
2029 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
2030 | + f ^= e ^ g |
2031 | + h = rotl32(h, 7) |
2032 | + f = rotl32(f, 1) |
2033 | + e ^= f ^ h |
2034 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
2035 | + e = rotl32(e, 5) |
2036 | + g = rotl32(g, 22) |
2037 | + e ^= key[4 * 23 + 8] |
2038 | + f ^= key[4 * 23 + 9] |
2039 | + g ^= key[4 * 23 + 10] |
2040 | + h ^= key[4 * 23 + 11] |
2041 | + t1 = (~g) % 0x100000000; |
2042 | + t2 = f ^ g; |
2043 | + t3 = f | t1; |
2044 | + t4 = h ^ t3; |
2045 | + t5 = e & t4; |
2046 | + t7 = e ^ h; |
2047 | + d = t2 ^ t5; |
2048 | + t8 = f ^ t5; |
2049 | + t9 = t2 | t8; |
2050 | + t11 = h & t3; |
2051 | + b = t7 ^ t9; |
2052 | + t12 = t5 ^ b; |
2053 | + t15 = t1 | t4; |
2054 | + t13 = d & t12; |
2055 | + c = t11 ^ t13; |
2056 | + t16 = t12 ^ c; |
2057 | + a = t15 ^ t16 |
2058 | + a = rotl32(a, 13) |
2059 | + c = rotl32(c, 3) |
2060 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
2061 | + b ^= a ^ c |
2062 | + d = rotl32(d, 7) |
2063 | + b = rotl32(b, 1) |
2064 | + a ^= b ^ d |
2065 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
2066 | + a = rotl32(a, 5) |
2067 | + c = rotl32(c, 22) |
2068 | + a ^= key[4 * 24 + 8] |
2069 | + b ^= key[4 * 24 + 9] |
2070 | + c ^= key[4 * 24 + 10] |
2071 | + d ^= key[4 * 24 + 11] |
2072 | + t1 = a ^ d; |
2073 | + t2 = a & d; |
2074 | + t3 = c ^ t1; |
2075 | + t6 = b & t1; |
2076 | + t4 = b ^ t3; |
2077 | + t10 = (~t3) % 0x100000000; |
2078 | + h = t2 ^ t4; |
2079 | + t7 = a ^ t6; |
2080 | + t14 = (~t7) % 0x100000000; |
2081 | + t8 = c | t7; |
2082 | + t11 = t3 ^ t7; |
2083 | + g = t4 ^ t8; |
2084 | + t12 = h & t11; |
2085 | + f = t10 ^ t12; |
2086 | + e = t12 ^ t14 |
2087 | + e = rotl32(e, 13) |
2088 | + g = rotl32(g, 3) |
2089 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
2090 | + f ^= e ^ g |
2091 | + h = rotl32(h, 7) |
2092 | + f = rotl32(f, 1) |
2093 | + e ^= f ^ h |
2094 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
2095 | + e = rotl32(e, 5) |
2096 | + g = rotl32(g, 22) |
2097 | + e ^= key[4 * 25 + 8] |
2098 | + f ^= key[4 * 25 + 9] |
2099 | + g ^= key[4 * 25 + 10] |
2100 | + h ^= key[4 * 25 + 11] |
2101 | + t1 = (~e) % 0x100000000; |
2102 | + t2 = f ^ t1; |
2103 | + t3 = e | t2; |
2104 | + t4 = h | t2; |
2105 | + t5 = g ^ t3; |
2106 | + c = h ^ t5; |
2107 | + t7 = f ^ t4; |
2108 | + t8 = t2 ^ c; |
2109 | + t9 = t5 & t7; |
2110 | + d = t8 ^ t9; |
2111 | + t11 = t5 ^ t7; |
2112 | + b = d ^ t11; |
2113 | + t13 = t8 & t11; |
2114 | + a = t5 ^ t13 |
2115 | + a = rotl32(a, 13) |
2116 | + c = rotl32(c, 3) |
2117 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
2118 | + b ^= a ^ c |
2119 | + d = rotl32(d, 7) |
2120 | + b = rotl32(b, 1) |
2121 | + a ^= b ^ d |
2122 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
2123 | + a = rotl32(a, 5) |
2124 | + c = rotl32(c, 22) |
2125 | + a ^= key[4 * 26 + 8] |
2126 | + b ^= key[4 * 26 + 9] |
2127 | + c ^= key[4 * 26 + 10] |
2128 | + d ^= key[4 * 26 + 11] |
2129 | + t1 = (~a) % 0x100000000; |
2130 | + t2 = b ^ d; |
2131 | + t3 = c & t1; |
2132 | + t13 = d | t1; |
2133 | + e = t2 ^ t3; |
2134 | + t5 = c ^ t1; |
2135 | + t6 = c ^ e; |
2136 | + t7 = b & t6; |
2137 | + t10 = e | t5; |
2138 | + h = t5 ^ t7; |
2139 | + t9 = d | t7; |
2140 | + t11 = t9 & t10; |
2141 | + t14 = t2 ^ h; |
2142 | + g = a ^ t11; |
2143 | + t15 = g ^ t13; |
2144 | + f = t14 ^ t15 |
2145 | + e = rotl32(e, 13) |
2146 | + g = rotl32(g, 3) |
2147 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
2148 | + f ^= e ^ g |
2149 | + h = rotl32(h, 7) |
2150 | + f = rotl32(f, 1) |
2151 | + e ^= f ^ h |
2152 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
2153 | + e = rotl32(e, 5) |
2154 | + g = rotl32(g, 22) |
2155 | + e ^= key[4 * 27 + 8] |
2156 | + f ^= key[4 * 27 + 9] |
2157 | + g ^= key[4 * 27 + 10] |
2158 | + h ^= key[4 * 27 + 11] |
2159 | + t1 = e ^ g; |
2160 | + t2 = h ^ t1; |
2161 | + t3 = e & t2; |
2162 | + t4 = h ^ t3; |
2163 | + t5 = f & t4; |
2164 | + c = t2 ^ t5; |
2165 | + t7 = e | c; |
2166 | + t8 = f | h; |
2167 | + t11 = e | h; |
2168 | + t9 = t4 & t7; |
2169 | + b = t8 ^ t9; |
2170 | + t12 = f ^ t11; |
2171 | + t13 = c ^ t9; |
2172 | + t15 = t3 ^ t8; |
2173 | + d = t12 ^ t13; |
2174 | + t16 = g & t15; |
2175 | + a = t12 ^ t16 |
2176 | + a = rotl32(a, 13) |
2177 | + c = rotl32(c, 3) |
2178 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
2179 | + b ^= a ^ c |
2180 | + d = rotl32(d, 7) |
2181 | + b = rotl32(b, 1) |
2182 | + a ^= b ^ d |
2183 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
2184 | + a = rotl32(a, 5) |
2185 | + c = rotl32(c, 22) |
2186 | + a ^= key[4 * 28 + 8] |
2187 | + b ^= key[4 * 28 + 9] |
2188 | + c ^= key[4 * 28 + 10] |
2189 | + d ^= key[4 * 28 + 11] |
2190 | + t1 = a ^ d; |
2191 | + t2 = d & t1; |
2192 | + t3 = c ^ t2; |
2193 | + t4 = b | t3; |
2194 | + h = t1 ^ t4; |
2195 | + t6 = (~b) % 0x100000000; |
2196 | + t7 = t1 | t6; |
2197 | + e = t3 ^ t7; |
2198 | + t9 = a & e; |
2199 | + t10 = t1 ^ t6; |
2200 | + t11 = t4 & t10; |
2201 | + g = t9 ^ t11; |
2202 | + t13 = a ^ t3; |
2203 | + t14 = t10 & g; |
2204 | + f = t13 ^ t14 |
2205 | + e = rotl32(e, 13) |
2206 | + g = rotl32(g, 3) |
2207 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
2208 | + f ^= e ^ g |
2209 | + h = rotl32(h, 7) |
2210 | + f = rotl32(f, 1) |
2211 | + e ^= f ^ h |
2212 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
2213 | + e = rotl32(e, 5) |
2214 | + g = rotl32(g, 22) |
2215 | + e ^= key[4 * 29 + 8] |
2216 | + f ^= key[4 * 29 + 9] |
2217 | + g ^= key[4 * 29 + 10] |
2218 | + h ^= key[4 * 29 + 11] |
2219 | + t1 = (~e) % 0x100000000; |
2220 | + t2 = e ^ f; |
2221 | + t3 = e ^ h; |
2222 | + t4 = g ^ t1; |
2223 | + t5 = t2 | t3; |
2224 | + a = t4 ^ t5; |
2225 | + t7 = h & a; |
2226 | + t8 = t2 ^ a; |
2227 | + t10 = t1 | a; |
2228 | + b = t7 ^ t8; |
2229 | + t11 = t2 | t7; |
2230 | + t12 = t3 ^ t10; |
2231 | + t14 = f ^ t7; |
2232 | + c = t11 ^ t12; |
2233 | + t15 = b & t12; |
2234 | + d = t14 ^ t15 |
2235 | + a = rotl32(a, 13) |
2236 | + c = rotl32(c, 3) |
2237 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
2238 | + b ^= a ^ c |
2239 | + d = rotl32(d, 7) |
2240 | + b = rotl32(b, 1) |
2241 | + a ^= b ^ d |
2242 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
2243 | + a = rotl32(a, 5) |
2244 | + c = rotl32(c, 22) |
2245 | + a ^= key[4 * 30 + 8] |
2246 | + b ^= key[4 * 30 + 9] |
2247 | + c ^= key[4 * 30 + 10] |
2248 | + d ^= key[4 * 30 + 11] |
2249 | + t1 = (~a) % 0x100000000; |
2250 | + t2 = a ^ d; |
2251 | + t3 = b ^ t2; |
2252 | + t4 = t1 | t2; |
2253 | + t5 = c ^ t4; |
2254 | + f = b ^ t5; |
2255 | + t13 = (~t5) % 0x100000000; |
2256 | + t7 = t2 | f; |
2257 | + t8 = d ^ t7; |
2258 | + t9 = t5 & t8; |
2259 | + g = t3 ^ t9; |
2260 | + t11 = t5 ^ t8; |
2261 | + e = g ^ t11; |
2262 | + t14 = t3 & t11; |
2263 | + h = t13 ^ t14 |
2264 | + e = rotl32(e, 13) |
2265 | + g = rotl32(g, 3) |
2266 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
2267 | + f ^= e ^ g |
2268 | + h = rotl32(h, 7) |
2269 | + f = rotl32(f, 1) |
2270 | + e ^= f ^ h |
2271 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
2272 | + e = rotl32(e, 5) |
2273 | + g = rotl32(g, 22) |
2274 | + e ^= key[4 * 31 + 8] |
2275 | + f ^= key[4 * 31 + 9] |
2276 | + g ^= key[4 * 31 + 10] |
2277 | + h ^= key[4 * 31 + 11] |
2278 | + t1 = (~g) % 0x100000000; |
2279 | + t2 = f ^ g; |
2280 | + t3 = f | t1; |
2281 | + t4 = h ^ t3; |
2282 | + t5 = e & t4; |
2283 | + t7 = e ^ h; |
2284 | + d = t2 ^ t5; |
2285 | + t8 = f ^ t5; |
2286 | + t9 = t2 | t8; |
2287 | + t11 = h & t3; |
2288 | + b = t7 ^ t9; |
2289 | + t12 = t5 ^ b; |
2290 | + t15 = t1 | t4; |
2291 | + t13 = d & t12; |
2292 | + c = t11 ^ t13; |
2293 | + t16 = t12 ^ c; |
2294 | + a = t15 ^ t16 |
2295 | + a ^= key[4 * 32 + 8] |
2296 | + b ^= key[4 * 32 + 9] |
2297 | + c ^= key[4 * 32 + 10] |
2298 | + d ^= key[4 * 32 + 11] |
2299 | + if WORD_BIGENDIAN: |
2300 | + a = byteswap32(a) |
2301 | + b = byteswap32(b) |
2302 | + c = byteswap32(c) |
2303 | + d = byteswap32(d) |
2304 | + in_blk[0] = a |
2305 | + in_blk[1] = b |
2306 | + in_blk[2] = c |
2307 | + in_blk[3] = d |
2308 | + |
2309 | +def decrypt(key, in_blk): |
2310 | + # serpent_generate.py |
2311 | + a = in_blk[0] |
2312 | + b = in_blk[1] |
2313 | + c = in_blk[2] |
2314 | + d = in_blk[3] |
2315 | + if WORD_BIGENDIAN: |
2316 | + a = byteswap32(a) |
2317 | + b = byteswap32(b) |
2318 | + c = byteswap32(c) |
2319 | + d = byteswap32(d) |
2320 | + e = 0 |
2321 | + f = 0 |
2322 | + g = 0 |
2323 | + h = 0 |
2324 | + t1 = 0 |
2325 | + t2 = 0 |
2326 | + t3 = 0 |
2327 | + t4 = 0 |
2328 | + t5 = 0 |
2329 | + t6 = 0 |
2330 | + t7 = 0 |
2331 | + t8 = 0 |
2332 | + t9 = 0 |
2333 | + t10 = 0 |
2334 | + t11 = 0 |
2335 | + t12 = 0 |
2336 | + t13 = 0 |
2337 | + t14 = 0 |
2338 | + t15 = 0 |
2339 | + t16 = 0 |
2340 | + a ^= key[4 * 32 + 8] |
2341 | + b ^= key[4 * 32 + 9] |
2342 | + c ^= key[4 * 32 + 10] |
2343 | + d ^= key[4 * 32 + 11] |
2344 | + t1 = a & b; |
2345 | + t2 = a | b; |
2346 | + t3 = c | t1; |
2347 | + t4 = d & t2; |
2348 | + h = t3 ^ t4; |
2349 | + t6 = (~d) % 0x100000000; |
2350 | + t7 = b ^ t4; |
2351 | + t8 = h ^ t6; |
2352 | + t11 = c ^ t7; |
2353 | + t9 = t7 | t8; |
2354 | + f = a ^ t9; |
2355 | + t12 = d | f; |
2356 | + e = t11 ^ t12; |
2357 | + t14 = a & h; |
2358 | + t15 = t3 ^ f; |
2359 | + t16 = e ^ t14; |
2360 | + g = t15 ^ t16 |
2361 | + e ^= key[4 * 31 + 8] |
2362 | + f ^= key[4 * 31 + 9] |
2363 | + g ^= key[4 * 31 + 10] |
2364 | + h ^= key[4 * 31 + 11] |
2365 | + g = rotr32(g, 22) |
2366 | + e = rotr32(e, 5) |
2367 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
2368 | + e ^= f ^ h |
2369 | + h = rotr32(h, 7) |
2370 | + f = rotr32(f, 1) |
2371 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
2372 | + f ^= e ^ g |
2373 | + g = rotr32(g, 3) |
2374 | + e = rotr32(e, 13) |
2375 | + t1 = (~e) % 0x100000000; |
2376 | + t2 = e ^ f; |
2377 | + t3 = g ^ t2; |
2378 | + t4 = g | t1; |
2379 | + t5 = h ^ t4; |
2380 | + t13 = h & t1; |
2381 | + b = t3 ^ t5; |
2382 | + t7 = t3 & t5; |
2383 | + t8 = t2 ^ t7; |
2384 | + t9 = f | t8; |
2385 | + d = t5 ^ t9; |
2386 | + t11 = f | d; |
2387 | + a = t8 ^ t11; |
2388 | + t14 = t3 ^ t11; |
2389 | + c = t13 ^ t14 |
2390 | + a ^= key[4 * 30 + 8] |
2391 | + b ^= key[4 * 30 + 9] |
2392 | + c ^= key[4 * 30 + 10] |
2393 | + d ^= key[4 * 30 + 11] |
2394 | + c = rotr32(c, 22) |
2395 | + a = rotr32(a, 5) |
2396 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
2397 | + a ^= b ^ d |
2398 | + d = rotr32(d, 7) |
2399 | + b = rotr32(b, 1) |
2400 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
2401 | + b ^= a ^ c |
2402 | + c = rotr32(c, 3) |
2403 | + a = rotr32(a, 13) |
2404 | + t1 = (~c) % 0x100000000; |
2405 | + t2 = b & t1; |
2406 | + t3 = d ^ t2; |
2407 | + t4 = a & t3; |
2408 | + t5 = b ^ t1; |
2409 | + h = t4 ^ t5; |
2410 | + t7 = b | h; |
2411 | + t8 = a & t7; |
2412 | + f = t3 ^ t8; |
2413 | + t10 = a | d; |
2414 | + t11 = t1 ^ t7; |
2415 | + e = t10 ^ t11; |
2416 | + t13 = a ^ c; |
2417 | + t14 = b & t10; |
2418 | + t15 = t4 | t13; |
2419 | + g = t14 ^ t15 |
2420 | + e ^= key[4 * 29 + 8] |
2421 | + f ^= key[4 * 29 + 9] |
2422 | + g ^= key[4 * 29 + 10] |
2423 | + h ^= key[4 * 29 + 11] |
2424 | + g = rotr32(g, 22) |
2425 | + e = rotr32(e, 5) |
2426 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
2427 | + e ^= f ^ h |
2428 | + h = rotr32(h, 7) |
2429 | + f = rotr32(f, 1) |
2430 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
2431 | + f ^= e ^ g |
2432 | + g = rotr32(g, 3) |
2433 | + e = rotr32(e, 13) |
2434 | + t1 = g ^ h; |
2435 | + t2 = g | h; |
2436 | + t3 = f ^ t2; |
2437 | + t4 = e & t3; |
2438 | + b = t1 ^ t4; |
2439 | + t6 = e ^ h; |
2440 | + t7 = f | h; |
2441 | + t8 = t6 & t7; |
2442 | + d = t3 ^ t8; |
2443 | + t10 = (~e) % 0x100000000; |
2444 | + t11 = g ^ d; |
2445 | + t12 = t10 | t11; |
2446 | + a = t3 ^ t12; |
2447 | + t14 = g | t4; |
2448 | + t15 = t7 ^ t14; |
2449 | + t16 = d | t10; |
2450 | + c = t15 ^ t16 |
2451 | + a ^= key[4 * 28 + 8] |
2452 | + b ^= key[4 * 28 + 9] |
2453 | + c ^= key[4 * 28 + 10] |
2454 | + d ^= key[4 * 28 + 11] |
2455 | + c = rotr32(c, 22) |
2456 | + a = rotr32(a, 5) |
2457 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
2458 | + a ^= b ^ d |
2459 | + d = rotr32(d, 7) |
2460 | + b = rotr32(b, 1) |
2461 | + |
2462 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
2463 | + b ^= a ^ c |
2464 | + c = rotr32(c, 3) |
2465 | + a = rotr32(a, 13) |
2466 | + t1 = b ^ c; |
2467 | + t2 = b | c; |
2468 | + t3 = a ^ c; |
2469 | + t7 = a ^ d; |
2470 | + t4 = t2 ^ t3; |
2471 | + t5 = d | t4; |
2472 | + t9 = t2 ^ t7; |
2473 | + e = t1 ^ t5; |
2474 | + t8 = t1 | t5; |
2475 | + t11 = a & t4; |
2476 | + g = t8 ^ t9; |
2477 | + t12 = e | t9; |
2478 | + f = t11 ^ t12; |
2479 | + t14 = a & g; |
2480 | + t15 = t2 ^ t14; |
2481 | + t16 = e & t15; |
2482 | + h = t4 ^ t16 |
2483 | + e ^= key[4 * 27 + 8] |
2484 | + f ^= key[4 * 27 + 9] |
2485 | + g ^= key[4 * 27 + 10] |
2486 | + h ^= key[4 * 27 + 11] |
2487 | + g = rotr32(g, 22) |
2488 | + e = rotr32(e, 5) |
2489 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
2490 | + e ^= f ^ h |
2491 | + h = rotr32(h, 7) |
2492 | + f = rotr32(f, 1) |
2493 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
2494 | + f ^= e ^ g |
2495 | + g = rotr32(g, 3) |
2496 | + e = rotr32(e, 13) |
2497 | + t1 = f ^ h; |
2498 | + t2 = (~t1) % 0x100000000; |
2499 | + t3 = e ^ g; |
2500 | + t4 = g ^ t1; |
2501 | + t7 = e | t2; |
2502 | + t5 = f & t4; |
2503 | + t8 = h ^ t7; |
2504 | + t11 = (~t4) % 0x100000000; |
2505 | + a = t3 ^ t5; |
2506 | + t9 = t3 | t8; |
2507 | + t14 = h & t11; |
2508 | + d = t1 ^ t9; |
2509 | + t12 = a | d; |
2510 | + b = t11 ^ t12; |
2511 | + t15 = t3 ^ t12; |
2512 | + c = t14 ^ t15 |
2513 | + a ^= key[4 * 26 + 8] |
2514 | + b ^= key[4 * 26 + 9] |
2515 | + c ^= key[4 * 26 + 10] |
2516 | + d ^= key[4 * 26 + 11] |
2517 | + c = rotr32(c, 22) |
2518 | + a = rotr32(a, 5) |
2519 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
2520 | + a ^= b ^ d |
2521 | + d = rotr32(d, 7) |
2522 | + b = rotr32(b, 1) |
2523 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
2524 | + b ^= a ^ c |
2525 | + c = rotr32(c, 3) |
2526 | + a = rotr32(a, 13) |
2527 | + t1 = a ^ d; |
2528 | + t2 = a & b; |
2529 | + t3 = b ^ c; |
2530 | + t4 = a ^ t3; |
2531 | + t5 = b | d; |
2532 | + t7 = c | t1; |
2533 | + h = t4 ^ t5; |
2534 | + t8 = b ^ t7; |
2535 | + t11 = (~t2) % 0x100000000; |
2536 | + t9 = t4 & t8; |
2537 | + f = t1 ^ t9; |
2538 | + t13 = t9 ^ t11; |
2539 | + t12 = h & f; |
2540 | + g = t12 ^ t13; |
2541 | + t15 = a & d; |
2542 | + t16 = c ^ t13; |
2543 | + e = t15 ^ t16 |
2544 | + e ^= key[4 * 25 + 8] |
2545 | + f ^= key[4 * 25 + 9] |
2546 | + g ^= key[4 * 25 + 10] |
2547 | + h ^= key[4 * 25 + 11] |
2548 | + g = rotr32(g, 22) |
2549 | + e = rotr32(e, 5) |
2550 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
2551 | + e ^= f ^ h |
2552 | + h = rotr32(h, 7) |
2553 | + f = rotr32(f, 1) |
2554 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
2555 | + f ^= e ^ g |
2556 | + g = rotr32(g, 3) |
2557 | + e = rotr32(e, 13) |
2558 | + t1 = (~e) % 0x100000000 |
2559 | + t2 = e ^ f |
2560 | + t3 = t1 | t2 |
2561 | + t4 = h ^ t3 |
2562 | + t7 = h & t2 |
2563 | + t5 = g ^ t4 |
2564 | + t8 = t1 ^ t7 |
2565 | + c = t2 ^ t5 |
2566 | + t11 = e & t4 |
2567 | + t9 = c & t8 |
2568 | + t14 = t5 ^ t8 |
2569 | + b = t4 ^ t9 |
2570 | + t12 = t5 | b |
2571 | + d = t11 ^ t12 |
2572 | + a = d ^ t14 |
2573 | + a ^= key[4 * 24 + 8] |
2574 | + b ^= key[4 * 24 + 9] |
2575 | + c ^= key[4 * 24 + 10] |
2576 | + d ^= key[4 * 24 + 11] |
2577 | + c = rotr32(c, 22) |
2578 | + a = rotr32(a, 5) |
2579 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
2580 | + a ^= b ^ d |
2581 | + d = rotr32(d, 7) |
2582 | + b = rotr32(b, 1) |
2583 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
2584 | + b ^= a ^ c |
2585 | + c = rotr32(c, 3) |
2586 | + a = rotr32(a, 13) |
2587 | + t1 = a & b; |
2588 | + t2 = a | b; |
2589 | + t3 = c | t1; |
2590 | + t4 = d & t2; |
2591 | + h = t3 ^ t4; |
2592 | + t6 = (~d) % 0x100000000; |
2593 | + t7 = b ^ t4; |
2594 | + t8 = h ^ t6; |
2595 | + t11 = c ^ t7; |
2596 | + t9 = t7 | t8; |
2597 | + f = a ^ t9; |
2598 | + t12 = d | f; |
2599 | + e = t11 ^ t12; |
2600 | + t14 = a & h; |
2601 | + t15 = t3 ^ f; |
2602 | + t16 = e ^ t14; |
2603 | + g = t15 ^ t16 |
2604 | + e ^= key[4 * 23 + 8] |
2605 | + f ^= key[4 * 23 + 9] |
2606 | + g ^= key[4 * 23 + 10] |
2607 | + h ^= key[4 * 23 + 11] |
2608 | + g = rotr32(g, 22) |
2609 | + e = rotr32(e, 5) |
2610 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
2611 | + e ^= f ^ h |
2612 | + h = rotr32(h, 7) |
2613 | + f = rotr32(f, 1) |
2614 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
2615 | + f ^= e ^ g |
2616 | + g = rotr32(g, 3) |
2617 | + e = rotr32(e, 13) |
2618 | + t1 = (~e) % 0x100000000; |
2619 | + t2 = e ^ f; |
2620 | + t3 = g ^ t2; |
2621 | + t4 = g | t1; |
2622 | + t5 = h ^ t4; |
2623 | + t13 = h & t1; |
2624 | + b = t3 ^ t5; |
2625 | + t7 = t3 & t5; |
2626 | + t8 = t2 ^ t7; |
2627 | + t9 = f | t8; |
2628 | + d = t5 ^ t9; |
2629 | + t11 = f | d; |
2630 | + a = t8 ^ t11; |
2631 | + t14 = t3 ^ t11; |
2632 | + c = t13 ^ t14 |
2633 | + a ^= key[4 * 22 + 8] |
2634 | + b ^= key[4 * 22 + 9] |
2635 | + c ^= key[4 * 22 + 10] |
2636 | + d ^= key[4 * 22 + 11] |
2637 | + c = rotr32(c, 22) |
2638 | + a = rotr32(a, 5) |
2639 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
2640 | + a ^= b ^ d |
2641 | + d = rotr32(d, 7) |
2642 | + b = rotr32(b, 1) |
2643 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
2644 | + b ^= a ^ c |
2645 | + c = rotr32(c, 3) |
2646 | + a = rotr32(a, 13) |
2647 | + t1 = (~c) % 0x100000000; |
2648 | + t2 = b & t1; |
2649 | + t3 = d ^ t2; |
2650 | + t4 = a & t3; |
2651 | + t5 = b ^ t1; |
2652 | + h = t4 ^ t5; |
2653 | + t7 = b | h; |
2654 | + t8 = a & t7; |
2655 | + f = t3 ^ t8; |
2656 | + t10 = a | d; |
2657 | + t11 = t1 ^ t7; |
2658 | + e = t10 ^ t11; |
2659 | + t13 = a ^ c; |
2660 | + t14 = b & t10; |
2661 | + t15 = t4 | t13; |
2662 | + g = t14 ^ t15 |
2663 | + e ^= key[4 * 21 + 8] |
2664 | + f ^= key[4 * 21 + 9] |
2665 | + g ^= key[4 * 21 + 10] |
2666 | + h ^= key[4 * 21 + 11] |
2667 | + g = rotr32(g, 22) |
2668 | + e = rotr32(e, 5) |
2669 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
2670 | + e ^= f ^ h |
2671 | + h = rotr32(h, 7) |
2672 | + f = rotr32(f, 1) |
2673 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
2674 | + f ^= e ^ g |
2675 | + g = rotr32(g, 3) |
2676 | + e = rotr32(e, 13) |
2677 | + t1 = g ^ h; |
2678 | + t2 = g | h; |
2679 | + t3 = f ^ t2; |
2680 | + t4 = e & t3; |
2681 | + b = t1 ^ t4; |
2682 | + t6 = e ^ h; |
2683 | + t7 = f | h; |
2684 | + t8 = t6 & t7; |
2685 | + d = t3 ^ t8; |
2686 | + t10 = (~e) % 0x100000000; |
2687 | + t11 = g ^ d; |
2688 | + t12 = t10 | t11; |
2689 | + a = t3 ^ t12; |
2690 | + t14 = g | t4; |
2691 | + t15 = t7 ^ t14; |
2692 | + t16 = d | t10; |
2693 | + c = t15 ^ t16 |
2694 | + a ^= key[4 * 20 + 8] |
2695 | + b ^= key[4 * 20 + 9] |
2696 | + c ^= key[4 * 20 + 10] |
2697 | + d ^= key[4 * 20 + 11] |
2698 | + c = rotr32(c, 22) |
2699 | + a = rotr32(a, 5) |
2700 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
2701 | + a ^= b ^ d |
2702 | + d = rotr32(d, 7) |
2703 | + b = rotr32(b, 1) |
2704 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
2705 | + b ^= a ^ c |
2706 | + c = rotr32(c, 3) |
2707 | + a = rotr32(a, 13) |
2708 | + t1 = b ^ c; |
2709 | + t2 = b | c; |
2710 | + t3 = a ^ c; |
2711 | + t7 = a ^ d; |
2712 | + t4 = t2 ^ t3; |
2713 | + t5 = d | t4; |
2714 | + t9 = t2 ^ t7; |
2715 | + e = t1 ^ t5; |
2716 | + t8 = t1 | t5; |
2717 | + t11 = a & t4; |
2718 | + g = t8 ^ t9; |
2719 | + t12 = e | t9; |
2720 | + f = t11 ^ t12; |
2721 | + t14 = a & g; |
2722 | + t15 = t2 ^ t14; |
2723 | + t16 = e & t15; |
2724 | + h = t4 ^ t16 |
2725 | + e ^= key[4 * 19 + 8] |
2726 | + f ^= key[4 * 19 + 9] |
2727 | + g ^= key[4 * 19 + 10] |
2728 | + h ^= key[4 * 19 + 11] |
2729 | + g = rotr32(g, 22) |
2730 | + e = rotr32(e, 5) |
2731 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
2732 | + e ^= f ^ h |
2733 | + h = rotr32(h, 7) |
2734 | + f = rotr32(f, 1) |
2735 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
2736 | + f ^= e ^ g |
2737 | + g = rotr32(g, 3) |
2738 | + e = rotr32(e, 13) |
2739 | + t1 = f ^ h; |
2740 | + t2 = (~t1) % 0x100000000; |
2741 | + t3 = e ^ g; |
2742 | + t4 = g ^ t1; |
2743 | + t7 = e | t2; |
2744 | + t5 = f & t4; |
2745 | + t8 = h ^ t7; |
2746 | + t11 = (~t4) % 0x100000000; |
2747 | + a = t3 ^ t5; |
2748 | + t9 = t3 | t8; |
2749 | + t14 = h & t11; |
2750 | + d = t1 ^ t9; |
2751 | + t12 = a | d; |
2752 | + b = t11 ^ t12; |
2753 | + t15 = t3 ^ t12; |
2754 | + c = t14 ^ t15 |
2755 | + a ^= key[4 * 18 + 8] |
2756 | + b ^= key[4 * 18 + 9] |
2757 | + c ^= key[4 * 18 + 10] |
2758 | + d ^= key[4 * 18 + 11] |
2759 | + c = rotr32(c, 22) |
2760 | + a = rotr32(a, 5) |
2761 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
2762 | + a ^= b ^ d |
2763 | + d = rotr32(d, 7) |
2764 | + b = rotr32(b, 1) |
2765 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
2766 | + b ^= a ^ c |
2767 | + c = rotr32(c, 3) |
2768 | + a = rotr32(a, 13) |
2769 | + t1 = a ^ d; |
2770 | + t2 = a & b; |
2771 | + t3 = b ^ c; |
2772 | + t4 = a ^ t3; |
2773 | + t5 = b | d; |
2774 | + t7 = c | t1; |
2775 | + h = t4 ^ t5; |
2776 | + t8 = b ^ t7; |
2777 | + t11 = (~t2) % 0x100000000; |
2778 | + t9 = t4 & t8; |
2779 | + f = t1 ^ t9; |
2780 | + t13 = t9 ^ t11; |
2781 | + t12 = h & f; |
2782 | + g = t12 ^ t13; |
2783 | + t15 = a & d; |
2784 | + t16 = c ^ t13; |
2785 | + e = t15 ^ t16 |
2786 | + e ^= key[4 * 17 + 8] |
2787 | + f ^= key[4 * 17 + 9] |
2788 | + g ^= key[4 * 17 + 10] |
2789 | + h ^= key[4 * 17 + 11] |
2790 | + g = rotr32(g, 22) |
2791 | + e = rotr32(e, 5) |
2792 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
2793 | + e ^= f ^ h |
2794 | + h = rotr32(h, 7) |
2795 | + f = rotr32(f, 1) |
2796 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
2797 | + f ^= e ^ g |
2798 | + g = rotr32(g, 3) |
2799 | + e = rotr32(e, 13) |
2800 | + t1 = (~e) % 0x100000000 |
2801 | + t2 = e ^ f |
2802 | + t3 = t1 | t2 |
2803 | + t4 = h ^ t3 |
2804 | + t7 = h & t2 |
2805 | + t5 = g ^ t4 |
2806 | + t8 = t1 ^ t7 |
2807 | + c = t2 ^ t5 |
2808 | + t11 = e & t4 |
2809 | + t9 = c & t8 |
2810 | + t14 = t5 ^ t8 |
2811 | + b = t4 ^ t9 |
2812 | + t12 = t5 | b |
2813 | + d = t11 ^ t12 |
2814 | + a = d ^ t14 |
2815 | + a ^= key[4 * 16 + 8] |
2816 | + b ^= key[4 * 16 + 9] |
2817 | + c ^= key[4 * 16 + 10] |
2818 | + d ^= key[4 * 16 + 11] |
2819 | + c = rotr32(c, 22) |
2820 | + a = rotr32(a, 5) |
2821 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
2822 | + a ^= b ^ d |
2823 | + d = rotr32(d, 7) |
2824 | + b = rotr32(b, 1) |
2825 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
2826 | + b ^= a ^ c |
2827 | + c = rotr32(c, 3) |
2828 | + a = rotr32(a, 13) |
2829 | + t1 = a & b; |
2830 | + t2 = a | b; |
2831 | + t3 = c | t1; |
2832 | + t4 = d & t2; |
2833 | + h = t3 ^ t4; |
2834 | + t6 = (~d) % 0x100000000; |
2835 | + t7 = b ^ t4; |
2836 | + t8 = h ^ t6; |
2837 | + t11 = c ^ t7; |
2838 | + t9 = t7 | t8; |
2839 | + f = a ^ t9; |
2840 | + t12 = d | f; |
2841 | + e = t11 ^ t12; |
2842 | + t14 = a & h; |
2843 | + t15 = t3 ^ f; |
2844 | + t16 = e ^ t14; |
2845 | + g = t15 ^ t16 |
2846 | + e ^= key[4 * 15 + 8] |
2847 | + f ^= key[4 * 15 + 9] |
2848 | + g ^= key[4 * 15 + 10] |
2849 | + h ^= key[4 * 15 + 11] |
2850 | + g = rotr32(g, 22) |
2851 | + e = rotr32(e, 5) |
2852 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
2853 | + e ^= f ^ h |
2854 | + h = rotr32(h, 7) |
2855 | + f = rotr32(f, 1) |
2856 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
2857 | + f ^= e ^ g |
2858 | + g = rotr32(g, 3) |
2859 | + e = rotr32(e, 13) |
2860 | + t1 = (~e) % 0x100000000; |
2861 | + t2 = e ^ f; |
2862 | + t3 = g ^ t2; |
2863 | + t4 = g | t1; |
2864 | + t5 = h ^ t4; |
2865 | + t13 = h & t1; |
2866 | + b = t3 ^ t5; |
2867 | + t7 = t3 & t5; |
2868 | + t8 = t2 ^ t7; |
2869 | + t9 = f | t8; |
2870 | + d = t5 ^ t9; |
2871 | + t11 = f | d; |
2872 | + a = t8 ^ t11; |
2873 | + t14 = t3 ^ t11; |
2874 | + c = t13 ^ t14 |
2875 | + a ^= key[4 * 14 + 8] |
2876 | + b ^= key[4 * 14 + 9] |
2877 | + c ^= key[4 * 14 + 10] |
2878 | + d ^= key[4 * 14 + 11] |
2879 | + c = rotr32(c, 22) |
2880 | + a = rotr32(a, 5) |
2881 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
2882 | + a ^= b ^ d |
2883 | + d = rotr32(d, 7) |
2884 | + b = rotr32(b, 1) |
2885 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
2886 | + b ^= a ^ c |
2887 | + c = rotr32(c, 3) |
2888 | + a = rotr32(a, 13) |
2889 | + t1 = (~c) % 0x100000000; |
2890 | + t2 = b & t1; |
2891 | + t3 = d ^ t2; |
2892 | + t4 = a & t3; |
2893 | + t5 = b ^ t1; |
2894 | + h = t4 ^ t5; |
2895 | + t7 = b | h; |
2896 | + t8 = a & t7; |
2897 | + f = t3 ^ t8; |
2898 | + t10 = a | d; |
2899 | + t11 = t1 ^ t7; |
2900 | + e = t10 ^ t11; |
2901 | + t13 = a ^ c; |
2902 | + t14 = b & t10; |
2903 | + t15 = t4 | t13; |
2904 | + g = t14 ^ t15 |
2905 | + e ^= key[4 * 13 + 8] |
2906 | + f ^= key[4 * 13 + 9] |
2907 | + g ^= key[4 * 13 + 10] |
2908 | + h ^= key[4 * 13 + 11] |
2909 | + g = rotr32(g, 22) |
2910 | + e = rotr32(e, 5) |
2911 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
2912 | + e ^= f ^ h |
2913 | + h = rotr32(h, 7) |
2914 | + f = rotr32(f, 1) |
2915 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
2916 | + f ^= e ^ g |
2917 | + g = rotr32(g, 3) |
2918 | + e = rotr32(e, 13) |
2919 | + t1 = g ^ h; |
2920 | + t2 = g | h; |
2921 | + t3 = f ^ t2; |
2922 | + t4 = e & t3; |
2923 | + b = t1 ^ t4; |
2924 | + t6 = e ^ h; |
2925 | + t7 = f | h; |
2926 | + t8 = t6 & t7; |
2927 | + d = t3 ^ t8; |
2928 | + t10 = (~e) % 0x100000000; |
2929 | + t11 = g ^ d; |
2930 | + t12 = t10 | t11; |
2931 | + a = t3 ^ t12; |
2932 | + t14 = g | t4; |
2933 | + t15 = t7 ^ t14; |
2934 | + t16 = d | t10; |
2935 | + c = t15 ^ t16 |
2936 | + a ^= key[4 * 12 + 8] |
2937 | + b ^= key[4 * 12 + 9] |
2938 | + c ^= key[4 * 12 + 10] |
2939 | + d ^= key[4 * 12 + 11] |
2940 | + c = rotr32(c, 22) |
2941 | + a = rotr32(a, 5) |
2942 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
2943 | + a ^= b ^ d |
2944 | + d = rotr32(d, 7) |
2945 | + b = rotr32(b, 1) |
2946 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
2947 | + b ^= a ^ c |
2948 | + c = rotr32(c, 3) |
2949 | + a = rotr32(a, 13) |
2950 | + t1 = b ^ c; |
2951 | + t2 = b | c; |
2952 | + t3 = a ^ c; |
2953 | + t7 = a ^ d; |
2954 | + t4 = t2 ^ t3; |
2955 | + t5 = d | t4; |
2956 | + t9 = t2 ^ t7; |
2957 | + e = t1 ^ t5; |
2958 | + t8 = t1 | t5; |
2959 | + t11 = a & t4; |
2960 | + g = t8 ^ t9; |
2961 | + t12 = e | t9; |
2962 | + f = t11 ^ t12; |
2963 | + t14 = a & g; |
2964 | + t15 = t2 ^ t14; |
2965 | + t16 = e & t15; |
2966 | + h = t4 ^ t16 |
2967 | + e ^= key[4 * 11 + 8] |
2968 | + f ^= key[4 * 11 + 9] |
2969 | + g ^= key[4 * 11 + 10] |
2970 | + h ^= key[4 * 11 + 11] |
2971 | + g = rotr32(g, 22) |
2972 | + e = rotr32(e, 5) |
2973 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
2974 | + e ^= f ^ h |
2975 | + h = rotr32(h, 7) |
2976 | + f = rotr32(f, 1) |
2977 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
2978 | + f ^= e ^ g |
2979 | + g = rotr32(g, 3) |
2980 | + e = rotr32(e, 13) |
2981 | + t1 = f ^ h; |
2982 | + t2 = (~t1) % 0x100000000; |
2983 | + t3 = e ^ g; |
2984 | + t4 = g ^ t1; |
2985 | + t7 = e | t2; |
2986 | + t5 = f & t4; |
2987 | + t8 = h ^ t7; |
2988 | + t11 = (~t4) % 0x100000000; |
2989 | + a = t3 ^ t5; |
2990 | + t9 = t3 | t8; |
2991 | + t14 = h & t11; |
2992 | + d = t1 ^ t9; |
2993 | + t12 = a | d; |
2994 | + b = t11 ^ t12; |
2995 | + t15 = t3 ^ t12; |
2996 | + c = t14 ^ t15 |
2997 | + a ^= key[4 * 10 + 8] |
2998 | + b ^= key[4 * 10 + 9] |
2999 | + c ^= key[4 * 10 + 10] |
3000 | + d ^= key[4 * 10 + 11] |
3001 | + c = rotr32(c, 22) |
3002 | + a = rotr32(a, 5) |
3003 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
3004 | + a ^= b ^ d |
3005 | + d = rotr32(d, 7) |
3006 | + b = rotr32(b, 1) |
3007 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
3008 | + b ^= a ^ c |
3009 | + c = rotr32(c, 3) |
3010 | + a = rotr32(a, 13) |
3011 | + t1 = a ^ d; |
3012 | + t2 = a & b; |
3013 | + t3 = b ^ c; |
3014 | + t4 = a ^ t3; |
3015 | + t5 = b | d; |
3016 | + t7 = c | t1; |
3017 | + h = t4 ^ t5; |
3018 | + t8 = b ^ t7; |
3019 | + t11 = (~t2) % 0x100000000; |
3020 | + t9 = t4 & t8; |
3021 | + f = t1 ^ t9; |
3022 | + t13 = t9 ^ t11; |
3023 | + t12 = h & f; |
3024 | + g = t12 ^ t13; |
3025 | + t15 = a & d; |
3026 | + t16 = c ^ t13; |
3027 | + e = t15 ^ t16 |
3028 | + e ^= key[4 * 9 + 8] |
3029 | + f ^= key[4 * 9 + 9] |
3030 | + g ^= key[4 * 9 + 10] |
3031 | + h ^= key[4 * 9 + 11] |
3032 | + g = rotr32(g, 22) |
3033 | + e = rotr32(e, 5) |
3034 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
3035 | + e ^= f ^ h |
3036 | + h = rotr32(h, 7) |
3037 | + f = rotr32(f, 1) |
3038 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
3039 | + f ^= e ^ g |
3040 | + g = rotr32(g, 3) |
3041 | + e = rotr32(e, 13) |
3042 | + t1 = (~e) % 0x100000000 |
3043 | + t2 = e ^ f |
3044 | + t3 = t1 | t2 |
3045 | + t4 = h ^ t3 |
3046 | + t7 = h & t2 |
3047 | + t5 = g ^ t4 |
3048 | + t8 = t1 ^ t7 |
3049 | + c = t2 ^ t5 |
3050 | + t11 = e & t4 |
3051 | + t9 = c & t8 |
3052 | + t14 = t5 ^ t8 |
3053 | + b = t4 ^ t9 |
3054 | + t12 = t5 | b |
3055 | + d = t11 ^ t12 |
3056 | + a = d ^ t14 |
3057 | + a ^= key[4 * 8 + 8] |
3058 | + b ^= key[4 * 8 + 9] |
3059 | + c ^= key[4 * 8 + 10] |
3060 | + d ^= key[4 * 8 + 11] |
3061 | + c = rotr32(c, 22) |
3062 | + a = rotr32(a, 5) |
3063 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
3064 | + a ^= b ^ d |
3065 | + d = rotr32(d, 7) |
3066 | + b = rotr32(b, 1) |
3067 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
3068 | + b ^= a ^ c |
3069 | + c = rotr32(c, 3) |
3070 | + a = rotr32(a, 13) |
3071 | + t1 = a & b; |
3072 | + t2 = a | b; |
3073 | + t3 = c | t1; |
3074 | + t4 = d & t2; |
3075 | + h = t3 ^ t4; |
3076 | + t6 = (~d) % 0x100000000; |
3077 | + t7 = b ^ t4; |
3078 | + t8 = h ^ t6; |
3079 | + t11 = c ^ t7; |
3080 | + t9 = t7 | t8; |
3081 | + f = a ^ t9; |
3082 | + t12 = d | f; |
3083 | + e = t11 ^ t12; |
3084 | + t14 = a & h; |
3085 | + t15 = t3 ^ f; |
3086 | + t16 = e ^ t14; |
3087 | + g = t15 ^ t16 |
3088 | + e ^= key[4 * 7 + 8] |
3089 | + f ^= key[4 * 7 + 9] |
3090 | + g ^= key[4 * 7 + 10] |
3091 | + h ^= key[4 * 7 + 11] |
3092 | + g = rotr32(g, 22) |
3093 | + e = rotr32(e, 5) |
3094 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
3095 | + e ^= f ^ h |
3096 | + h = rotr32(h, 7) |
3097 | + f = rotr32(f, 1) |
3098 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
3099 | + f ^= e ^ g |
3100 | + g = rotr32(g, 3) |
3101 | + e = rotr32(e, 13) |
3102 | + t1 = (~e) % 0x100000000; |
3103 | + t2 = e ^ f; |
3104 | + t3 = g ^ t2; |
3105 | + t4 = g | t1; |
3106 | + t5 = h ^ t4; |
3107 | + t13 = h & t1; |
3108 | + b = t3 ^ t5; |
3109 | + t7 = t3 & t5; |
3110 | + t8 = t2 ^ t7; |
3111 | + t9 = f | t8; |
3112 | + d = t5 ^ t9; |
3113 | + t11 = f | d; |
3114 | + a = t8 ^ t11; |
3115 | + t14 = t3 ^ t11; |
3116 | + c = t13 ^ t14 |
3117 | + a ^= key[4 * 6 + 8] |
3118 | + b ^= key[4 * 6 + 9] |
3119 | + c ^= key[4 * 6 + 10] |
3120 | + d ^= key[4 * 6 + 11] |
3121 | + c = rotr32(c, 22) |
3122 | + a = rotr32(a, 5) |
3123 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
3124 | + a ^= b ^ d |
3125 | + d = rotr32(d, 7) |
3126 | + b = rotr32(b, 1) |
3127 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
3128 | + b ^= a ^ c |
3129 | + c = rotr32(c, 3) |
3130 | + a = rotr32(a, 13) |
3131 | + t1 = (~c) % 0x100000000; |
3132 | + t2 = b & t1; |
3133 | + t3 = d ^ t2; |
3134 | + t4 = a & t3; |
3135 | + t5 = b ^ t1; |
3136 | + h = t4 ^ t5; |
3137 | + t7 = b | h; |
3138 | + t8 = a & t7; |
3139 | + f = t3 ^ t8; |
3140 | + t10 = a | d; |
3141 | + t11 = t1 ^ t7; |
3142 | + e = t10 ^ t11; |
3143 | + t13 = a ^ c; |
3144 | + t14 = b & t10; |
3145 | + t15 = t4 | t13; |
3146 | + g = t14 ^ t15 |
3147 | + e ^= key[4 * 5 + 8] |
3148 | + f ^= key[4 * 5 + 9] |
3149 | + g ^= key[4 * 5 + 10] |
3150 | + h ^= key[4 * 5 + 11] |
3151 | + g = rotr32(g, 22) |
3152 | + e = rotr32(e, 5) |
3153 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
3154 | + e ^= f ^ h |
3155 | + h = rotr32(h, 7) |
3156 | + f = rotr32(f, 1) |
3157 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
3158 | + f ^= e ^ g |
3159 | + g = rotr32(g, 3) |
3160 | + e = rotr32(e, 13) |
3161 | + t1 = g ^ h; |
3162 | + t2 = g | h; |
3163 | + t3 = f ^ t2; |
3164 | + t4 = e & t3; |
3165 | + b = t1 ^ t4; |
3166 | + t6 = e ^ h; |
3167 | + t7 = f | h; |
3168 | + t8 = t6 & t7; |
3169 | + d = t3 ^ t8; |
3170 | + t10 = (~e) % 0x100000000; |
3171 | + t11 = g ^ d; |
3172 | + t12 = t10 | t11; |
3173 | + a = t3 ^ t12; |
3174 | + t14 = g | t4; |
3175 | + t15 = t7 ^ t14; |
3176 | + t16 = d | t10; |
3177 | + c = t15 ^ t16 |
3178 | + a ^= key[4 * 4 + 8] |
3179 | + b ^= key[4 * 4 + 9] |
3180 | + c ^= key[4 * 4 + 10] |
3181 | + d ^= key[4 * 4 + 11] |
3182 | + c = rotr32(c, 22) |
3183 | + a = rotr32(a, 5) |
3184 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
3185 | + a ^= b ^ d |
3186 | + d = rotr32(d, 7) |
3187 | + b = rotr32(b, 1) |
3188 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
3189 | + b ^= a ^ c |
3190 | + c = rotr32(c, 3) |
3191 | + a = rotr32(a, 13) |
3192 | + t1 = b ^ c; |
3193 | + t2 = b | c; |
3194 | + t3 = a ^ c; |
3195 | + t7 = a ^ d; |
3196 | + t4 = t2 ^ t3; |
3197 | + t5 = d | t4; |
3198 | + t9 = t2 ^ t7; |
3199 | + e = t1 ^ t5; |
3200 | + t8 = t1 | t5; |
3201 | + t11 = a & t4; |
3202 | + g = t8 ^ t9; |
3203 | + t12 = e | t9; |
3204 | + f = t11 ^ t12; |
3205 | + t14 = a & g; |
3206 | + t15 = t2 ^ t14; |
3207 | + t16 = e & t15; |
3208 | + h = t4 ^ t16 |
3209 | + e ^= key[4 * 3 + 8] |
3210 | + f ^= key[4 * 3 + 9] |
3211 | + g ^= key[4 * 3 + 10] |
3212 | + h ^= key[4 * 3 + 11] |
3213 | + g = rotr32(g, 22) |
3214 | + e = rotr32(e, 5) |
3215 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
3216 | + e ^= f ^ h |
3217 | + h = rotr32(h, 7) |
3218 | + f = rotr32(f, 1) |
3219 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
3220 | + f ^= e ^ g |
3221 | + g = rotr32(g, 3) |
3222 | + e = rotr32(e, 13) |
3223 | + t1 = f ^ h; |
3224 | + t2 = (~t1) % 0x100000000; |
3225 | + t3 = e ^ g; |
3226 | + t4 = g ^ t1; |
3227 | + t7 = e | t2; |
3228 | + t5 = f & t4; |
3229 | + t8 = h ^ t7; |
3230 | + t11 = (~t4) % 0x100000000; |
3231 | + a = t3 ^ t5; |
3232 | + t9 = t3 | t8; |
3233 | + t14 = h & t11; |
3234 | + d = t1 ^ t9; |
3235 | + t12 = a | d; |
3236 | + b = t11 ^ t12; |
3237 | + t15 = t3 ^ t12; |
3238 | + c = t14 ^ t15 |
3239 | + a ^= key[4 * 2 + 8] |
3240 | + b ^= key[4 * 2 + 9] |
3241 | + c ^= key[4 * 2 + 10] |
3242 | + d ^= key[4 * 2 + 11] |
3243 | + c = rotr32(c, 22) |
3244 | + a = rotr32(a, 5) |
3245 | + c ^= d ^ ((b << 7) & 0xFFFFFFFF) |
3246 | + a ^= b ^ d |
3247 | + d = rotr32(d, 7) |
3248 | + b = rotr32(b, 1) |
3249 | + d ^= c ^ ((a << 3) & 0xFFFFFFFF) |
3250 | + b ^= a ^ c |
3251 | + c = rotr32(c, 3) |
3252 | + a = rotr32(a, 13) |
3253 | + t1 = a ^ d; |
3254 | + t2 = a & b; |
3255 | + t3 = b ^ c; |
3256 | + t4 = a ^ t3; |
3257 | + t5 = b | d; |
3258 | + t7 = c | t1; |
3259 | + h = t4 ^ t5; |
3260 | + t8 = b ^ t7; |
3261 | + t11 = (~t2) % 0x100000000; |
3262 | + t9 = t4 & t8; |
3263 | + f = t1 ^ t9; |
3264 | + t13 = t9 ^ t11; |
3265 | + t12 = h & f; |
3266 | + g = t12 ^ t13; |
3267 | + t15 = a & d; |
3268 | + t16 = c ^ t13; |
3269 | + e = t15 ^ t16 |
3270 | + e ^= key[4 * 1 + 8] |
3271 | + f ^= key[4 * 1 + 9] |
3272 | + g ^= key[4 * 1 + 10] |
3273 | + h ^= key[4 * 1 + 11] |
3274 | + g = rotr32(g, 22) |
3275 | + e = rotr32(e, 5) |
3276 | + g ^= h ^ ((f << 7) & 0xFFFFFFFF) |
3277 | + e ^= f ^ h |
3278 | + h = rotr32(h, 7) |
3279 | + f = rotr32(f, 1) |
3280 | + h ^= g ^ ((e << 3) & 0xFFFFFFFF) |
3281 | + f ^= e ^ g |
3282 | + g = rotr32(g, 3) |
3283 | + e = rotr32(e, 13) |
3284 | + t1 = (~e) % 0x100000000 |
3285 | + t2 = e ^ f |
3286 | + t3 = t1 | t2 |
3287 | + t4 = h ^ t3 |
3288 | + t7 = h & t2 |
3289 | + t5 = g ^ t4 |
3290 | + t8 = t1 ^ t7 |
3291 | + c = t2 ^ t5 |
3292 | + t11 = e & t4 |
3293 | + t9 = c & t8 |
3294 | + t14 = t5 ^ t8 |
3295 | + b = t4 ^ t9 |
3296 | + t12 = t5 | b |
3297 | + d = t11 ^ t12 |
3298 | + a = d ^ t14 |
3299 | + a ^= key[4 * 0 + 8] |
3300 | + b ^= key[4 * 0 + 9] |
3301 | + c ^= key[4 * 0 + 10] |
3302 | + d ^= key[4 * 0 + 11] |
3303 | + if WORD_BIGENDIAN: |
3304 | + a = byteswap32(a) |
3305 | + b = byteswap32(b) |
3306 | + c = byteswap32(c) |
3307 | + d = byteswap32(d) |
3308 | + in_blk[0] = a |
3309 | + in_blk[1] = b |
3310 | + in_blk[2] = c |
3311 | + in_blk[3] = d |
3312 | + |
3313 | +__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' |
3314 | +__testdat = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f' |
3315 | +assert '\xde&\x9f\xf83\xe42\xb8[.\x88\xd2p\x1c\xe7\\' == Serpent(__testkey).encrypt(__testdat) |
3316 | +assert __testdat == Serpent(__testkey).decrypt('\xde&\x9f\xf83\xe42\xb8[.\x88\xd2p\x1c\xe7\\') |
3317 | + |
3318 | +#CBC Encrypt - Jason Reaves |
3319 | +def serpent_cbc_encrypt(key, data, iv='\x00'*16): |
3320 | + out = "" |
3321 | + last = iv |
3322 | + for i in range((len(data)/16)): |
3323 | + temp = data[i*16:(i+1)*16] |
3324 | + to_encode = "" |
3325 | + for j in range(4): |
3326 | + temp1 = struct.unpack_from('<I', temp[j*4:])[0] |
3327 | + temp2 = struct.unpack_from('<I', last[j*4:])[0] |
3328 | + to_encode += struct.pack('<I',((temp1 ^ temp2) & 0xffffffff)) |
3329 | + last= Serpent(key).encrypt(to_encode) |
3330 | + out += last |
3331 | + #print(binascii.hexlify(Serpent(key).encrypt(data))) |
3332 | + return out |
3333 | + |
3334 | +#CBC Decrypt - Jason Reaves |
3335 | +def serpent_cbc_decrypt(key,data,iv='\x00'*16): |
3336 | + out2 = "" |
3337 | + last = iv |
3338 | + for i in range((len(data)/16)): |
3339 | + temp = Serpent(key).decrypt(data[i*16:(i+1)*16]) |
3340 | + to_decode = "" |
3341 | + for j in range(4): |
3342 | + temp1 = struct.unpack_from('<I', temp[j*4:])[0] |
3343 | + temp2 = struct.unpack_from('<I', last[j*4:])[0] |
3344 | + to_decode += struct.pack('<I',((temp1 ^ temp2) & 0xffffffff)) |
3345 | + out2 += to_decode |
3346 | + last = data[i*16:(i+1)*16] |
3347 | + return out2 |
3348 | diff --git a/lib/server.py b/lib/server.py |
3349 | index 38bf514..a248f1a 100644 |
3350 | |
3351 | |
3352 | |
3353 | if x == udp_server_socket: |
3354 | bytes_address_pair = udp_server_socket.recvfrom(PACKET_SIZE) |
3355 | message = bytes_address_pair[0] |
3356 | - address = bytes_address_pair[1] |
3357 | - print message |
3358 | + address = bytes_address_pair[1][0] |
3359 | for c in self.clients: |
3360 | - self.clients[c].udp_data_received(message) |
3361 | + self.clients[c].udp_data_received(address, message) |
3362 | for x in iwtd: |
3363 | if x in self.clients: |
3364 | self.clients[x].socket_readable_notification() |
3365 |
- I haven't thoroughly read through this library. It has many many lines of single letter variables. I don't know if this is the standard in implementation of encryption algos but it looks like it will be very difficult to properly fit in head. In addition, the purported authors insist that the implementation is very slow. I don't know how important that is since nothing gets decrypted until the hash is validated, which should be much faster. [↩]
Alcuin
Friday, July 30th, 2021Below is an updated version of the IRC emulator using UDP for links between servers that I published recently. In this update:
- A new name: alcuin
- Refactored into multiple files for ease of reading
- Messages are now sent between servers with hashes attached so that garbage messages can be easily discarded
- Apparently JOIN/PART messages are actually supported, your server just has to be running in time to catch them
- Added a perfunctory amount of documentation in README.txt
1 | diff --git a/Makefile b/Makefile |
2 | new file mode 100644 |
3 | index 0000000..1db3ff4 |
4 | |
5 | |
6 | |
7 | +VERSION := $(shell sed -ne 's/^VERSION = "\(.*\)"/\1/p' lib/server.py) |
8 | + |
9 | +DISTFILES = alcuin config.py.example README.txt lib |
10 | + |
11 | +all: |
12 | + echo "Nothing to do." |
13 | + |
14 | +dist: |
15 | + mkdir alcuin-$(VERSION) |
16 | + cp -r $(DISTFILES) alcuin-$(VERSION) |
17 | + tar cvzf alcuin-$(VERSION).tar.gz alcuin-$(VERSION) |
18 | + rm -rf alcuin-$(VERSION) |
19 | + |
20 | +clean: |
21 | + rm -rf genesis.vdiff genesis.vdiff.escaped alcuin-$(VERSION) |
22 | + find . -name "*.swp" -delete |
23 | + find . -name "*.pyc" -delete |
24 | + |
25 | +genesis: |
26 | + git show --pretty="format:" -1 HEAD > genesis.vdiff |
27 | + |
28 | +escaped-genesis: |
29 | + git show --pretty="format:" -1 HEAD | sed 's/&/\&/g; s/</\</g; s/>/\>/g; s/"/\"/g; s/'"'"'/\'/g; s/((/\(\(/g; s/))/\)\)/g; s/\[([0-9])\[/\[$1\[/g; s/]]/\]\]/g' > genesis.vdiff.escaped |
30 | diff --git a/README.txt b/README.txt |
31 | new file mode 100644 |
32 | index 0000000..2d5ff88 |
33 | |
34 | |
35 | |
36 | +Alcuin implements an IRC server with a udp client built in |
37 | +such that it can connect to other alcuin servers via a |
38 | +gossip network. It is a work in progress and much is |
39 | +yet to be completed including but not limited to: |
40 | + |
41 | +- gossip style message forwarding |
42 | +- message deduplication |
43 | +- symmetric encryption of messages |
44 | +- support for broadcasting several important IRC commands |
45 | + over the gossip net. |
46 | +- mitigation of hash length extension attacks |
47 | + |
48 | +GETTING STARTED |
49 | + |
50 | +1. Copy config.py.example to config.py (nothing in the config file is |
51 | +used yet, but alcuin will crash if it doesn't exist). |
52 | +2. Launch alcuin with something like the following command: |
53 | +./alcuin --verbose --port=6668 --peers=206.189.163.145 |
54 | + |
55 | +NOTES FOR DIFF/PATCH N00B5 |
56 | + |
57 | +To apply the genesis patch (or any patch) to the current directory |
58 | +and recreate the directory structure of the original: |
59 | + |
60 | +patch -p1 -ruN < <wherever>/genesis.vdiff |
61 | diff --git a/alcuin b/alcuin |
62 | new file mode 100755 |
63 | index 0000000..bbf9ed4 |
64 | |
65 | |
66 | |
67 | +#! /usr/bin/env python |
68 | + |
69 | +import os |
70 | +import re |
71 | +import select |
72 | +import socket |
73 | +import string |
74 | +import sys |
75 | +import tempfile |
76 | +import time |
77 | +from lib.server import VERSION |
78 | +from lib.server import Server |
79 | +from lib.peer import Peer |
80 | +from datetime import datetime |
81 | +from optparse import OptionParser |
82 | +import config as cfg |
83 | + |
84 | + |
85 | +def main(argv): |
86 | + op = OptionParser( |
87 | + version=VERSION, |
88 | + description="alcuin is a small and limited IRC server emulator for gossip networks.") |
89 | + op.add_option( |
90 | + "-d", "--daemon", |
91 | + action="store_true", |
92 | + help="fork and become a daemon") |
93 | + op.add_option( |
94 | + "--debug", |
95 | + action="store_true", |
96 | + help="print debug messages to stdout") |
97 | + op.add_option( |
98 | + "--listen", |
99 | + metavar="X", |
100 | + help="listen on specific IP address X") |
101 | + op.add_option( |
102 | + "--logdir", |
103 | + metavar="X", |
104 | + help="store channel log in directory X") |
105 | + op.add_option( |
106 | + "--motd", |
107 | + metavar="X", |
108 | + help="display file X as message of the day") |
109 | + op.add_option( |
110 | + "-s", "--ssl-pem-file", |
111 | + metavar="FILE", |
112 | + help="enable SSL and use FILE as the .pem certificate+key") |
113 | + op.add_option( |
114 | + "-p", "--password", |
115 | + metavar="X", |
116 | + help="require connection password X; default: no password") |
117 | + op.add_option( |
118 | + "--ports", |
119 | + metavar="X", |
120 | + help="listen to ports X (a list separated by comma or whitespace);" |
121 | + " default: 6667 or 6697 if SSL is enabled") |
122 | + op.add_option( |
123 | + "--udp-port", |
124 | + metavar="X", |
125 | + help="listen for UDP packets on X;" |
126 | + " default: 7778") |
127 | + op.add_option( |
128 | + "--peers", |
129 | + metavar="X", |
130 | + help="Broadcast to X (a list of IP addresses separated by comma or whitespace)") |
131 | + op.add_option( |
132 | + "--statedir", |
133 | + metavar="X", |
134 | + help="save persistent channel state (topic, key) in directory X") |
135 | + op.add_option( |
136 | + "--verbose", |
137 | + action="store_true", |
138 | + help="be verbose (print some progress messages to stdout)") |
139 | + if os.name == "posix": |
140 | + op.add_option( |
141 | + "--chroot", |
142 | + metavar="X", |
143 | + help="change filesystem root to directory X after startup" |
144 | + " (requires root)") |
145 | + op.add_option( |
146 | + "--setuid", |
147 | + metavar="U[:G]", |
148 | + help="change process user (and optionally group) after startup" |
149 | + " (requires root)") |
150 | + |
151 | + (options, args) = op.parse_args(argv[1:]) |
152 | + if options.debug: |
153 | + options.verbose = True |
154 | + if options.ports is None: |
155 | + if options.ssl_pem_file is None: |
156 | + options.ports = "6667" |
157 | + else: |
158 | + options.ports = "6697" |
159 | + if options.peers is None: |
160 | + options.peers = "" |
161 | + if options.udp_port is None: |
162 | + options.udp_port = 7778 |
163 | + else: |
164 | + options.udp_port = int(options.udp_port) |
165 | + if options.chroot: |
166 | + if os.getuid() != 0: |
167 | + op.error("Must be root to use --chroot") |
168 | + if options.setuid: |
169 | + from pwd import getpwnam |
170 | + from grp import getgrnam |
171 | + if os.getuid() != 0: |
172 | + op.error("Must be root to use --setuid") |
173 | + matches = options.setuid.split(":") |
174 | + if len(matches) == 2: |
175 | + options.setuid = (getpwnam(matches[0]).pw_uid, |
176 | + getgrnam(matches[1]).gr_gid) |
177 | + elif len(matches) == 1: |
178 | + options.setuid = (getpwnam(matches[0]).pw_uid, |
179 | + getpwnam(matches[0]).pw_gid) |
180 | + else: |
181 | + op.error("Specify a user, or user and group separated by a colon," |
182 | + " e.g. --setuid daemon, --setuid nobody:nobody") |
183 | + if (os.getuid() == 0 or os.getgid() == 0) and not options.setuid: |
184 | + op.error("Running this service as root is not recommended. Use the" |
185 | + " --setuid option to switch to an unprivileged account after" |
186 | + " startup. If you really intend to run as root, use" |
187 | + " \"--setuid root\".") |
188 | + |
189 | + ports = [] |
190 | + for port in re.split(r"[,\s]+", options.ports): |
191 | + try: |
192 | + ports.append(int(port)) |
193 | + except ValueError: |
194 | + op.error("bad port: %r" % port) |
195 | + options.ports = ports |
196 | + peers = [] |
197 | + for peer in re.split(r"[,\s]+", options.peers): |
198 | + try: |
199 | + peers.append(Peer(peer)) |
200 | + except ValueError: |
201 | + op.error("bad peer ip: %r" % peer) |
202 | + options.peers = peers |
203 | + server = Server(options) |
204 | + if options.daemon: |
205 | + server.daemonize() |
206 | + try: |
207 | + server.start() |
208 | + except KeyboardInterrupt: |
209 | + server.print_error("Interrupted.") |
210 | + |
211 | + |
212 | +main(sys.argv) |
213 | diff --git a/config.py.example b/config.py.example |
214 | new file mode 100644 |
215 | index 0000000..f9adc62 |
216 | |
217 | |
218 | |
219 | +secret = "SEEKRIT" |
220 | +peer_secrets = { |
221 | + "10.0.0.1":"K33P-0U7!" |
222 | +} |
223 | diff --git a/lib/__init__.py b/lib/__init__.py |
224 | new file mode 100644 |
225 | index 0000000..d2e75fb |
226 | |
227 | |
228 | |
229 | +# This file can't be empty otherwise diff won't see it. |
230 | diff --git a/lib/channel.py b/lib/channel.py |
231 | new file mode 100644 |
232 | index 0000000..5086804 |
233 | |
234 | |
235 | |
236 | +class Channel(object): |
237 | + def __init__(self, server, name): |
238 | + self.server = server |
239 | + self.name = name |
240 | + self.members = set() |
241 | + self._topic = "" |
242 | + self._key = None |
243 | + if self.server.statedir: |
244 | + self._state_path = "%s/%s" % ( |
245 | + self.server.statedir, |
246 | + name.replace("_", "__").replace("/", "_")) |
247 | + self._read_state() |
248 | + else: |
249 | + self._state_path = None |
250 | + |
251 | + def add_member(self, client): |
252 | + self.members.add(client) |
253 | + |
254 | + def get_topic(self): |
255 | + return self._topic |
256 | + |
257 | + def set_topic(self, value): |
258 | + self._topic = value |
259 | + self._write_state() |
260 | + |
261 | + topic = property(get_topic, set_topic) |
262 | + |
263 | + def get_key(self): |
264 | + return self._key |
265 | + |
266 | + def set_key(self, value): |
267 | + self._key = value |
268 | + self._write_state() |
269 | + |
270 | + key = property(get_key, set_key) |
271 | + |
272 | + def remove_client(self, client): |
273 | + self.members.discard(client) |
274 | + if not self.members: |
275 | + self.server.remove_channel(self) |
276 | + |
277 | + def _read_state(self): |
278 | + if not (self._state_path and os.path.exists(self._state_path)): |
279 | + return |
280 | + data = {} |
281 | + exec(open(self._state_path), {}, data) |
282 | + self._topic = data.get("topic", "") |
283 | + self._key = data.get("key") |
284 | + |
285 | + def _write_state(self): |
286 | + if not self._state_path: |
287 | + return |
288 | + (fd, path) = tempfile.mkstemp(dir=os.path.dirname(self._state_path)) |
289 | + fp = os.fdopen(fd, "w") |
290 | + fp.write("topic = %r\n" % self.topic) |
291 | + fp.write("key = %r\n" % self.key) |
292 | + fp.close() |
293 | + os.rename(path, self._state_path) |
294 | + |
295 | + |
296 | diff --git a/lib/client.py b/lib/client.py |
297 | new file mode 100644 |
298 | index 0000000..cfc5331 |
299 | |
300 | |
301 | |
302 | +import time |
303 | +import sys |
304 | +import re |
305 | +import string |
306 | +from lib.server import VERSION |
307 | +from lib.infosec import Infosec |
308 | +from funcs import * |
309 | + |
310 | +class Client(object): |
311 | + __linesep_regexp = re.compile(r"\r?\n") |
312 | + # The RFC limit for nicknames is 9 characters, but what the heck. |
313 | + __valid_nickname_regexp = re.compile( |
314 | + r"^[][\`_^{|}A-Za-z][][\`_^{|}A-Za-z0-9-]{0,50}$") |
315 | + __valid_channelname_regexp = re.compile( |
316 | + r"^[&#+!][^\x00\x07\x0a\x0d ,:]{0,50}$") |
317 | + |
318 | + def __init__(self, server, socket): |
319 | + self.server = server |
320 | + self.socket = socket |
321 | + self.channels = {} # irc_lower(Channel name) --> Channel |
322 | + self.nickname = None |
323 | + self.user = None |
324 | + self.realname = None |
325 | + (self.host, self.port) = socket.getpeername() |
326 | + self.__timestamp = time.time() |
327 | + self.__readbuffer = "" |
328 | + self.__writebuffer = "" |
329 | + self.__sent_ping = False |
330 | + self.infosec = Infosec() |
331 | + if self.server.password: |
332 | + self.__handle_command = self.__pass_handler |
333 | + else: |
334 | + self.__handle_command = self.__registration_handler |
335 | + |
336 | + def get_prefix(self): |
337 | + return "%s!%s@%s" % (self.nickname, self.user, self.host) |
338 | + prefix = property(get_prefix) |
339 | + |
340 | + def check_aliveness(self): |
341 | + now = time.time() |
342 | + if self.__timestamp + 180 < now: |
343 | + self.disconnect("ping timeout") |
344 | + return |
345 | + if not self.__sent_ping and self.__timestamp + 90 < now: |
346 | + if self.__handle_command == self.__command_handler: |
347 | + # Registered. |
348 | + self.message("PING :%s" % self.server.name) |
349 | + self.__sent_ping = True |
350 | + else: |
351 | + # Not registered. |
352 | + self.disconnect("ping timeout") |
353 | + |
354 | + def write_queue_size(self): |
355 | + return len(self.__writebuffer) |
356 | + |
357 | + def __parse_read_buffer(self): |
358 | + lines = self.__linesep_regexp.split(self.__readbuffer) |
359 | + self.__readbuffer = lines[-1] |
360 | + lines = lines[:-1] |
361 | + for line in lines: |
362 | + if not line: |
363 | + # Empty line. Ignore. |
364 | + continue |
365 | + x = line.split(" ", 1) |
366 | + command = x[0].upper() |
367 | + if len(x) == 1: |
368 | + arguments = [] |
369 | + else: |
370 | + if len(x[1]) > 0 and x[1][0] == ":": |
371 | + arguments = [x[1][1:]] |
372 | + else: |
373 | + y = string.split(x[1], " :", 1) |
374 | + arguments = string.split(y[0]) |
375 | + if len(y) == 2: |
376 | + arguments.append(y[1]) |
377 | + self.__handle_command(command, arguments) |
378 | + |
379 | + def __pass_handler(self, command, arguments): |
380 | + server = self.server |
381 | + if command == "PASS": |
382 | + if len(arguments) == 0: |
383 | + self.reply_461("PASS") |
384 | + else: |
385 | + if arguments[0].lower() == server.password: |
386 | + self.__handle_command = self.__registration_handler |
387 | + else: |
388 | + self.reply("464 :Password incorrect") |
389 | + elif command == "QUIT": |
390 | + self.disconnect("Client quit") |
391 | + return |
392 | + |
393 | + def __registration_handler(self, command, arguments): |
394 | + server = self.server |
395 | + if command == "NICK": |
396 | + if len(arguments) < 1: |
397 | + self.reply("431 :No nickname given") |
398 | + return |
399 | + nick = arguments[0] |
400 | + if server.get_client(nick): |
401 | + self.reply("433 * %s :Nickname is already in use" % nick) |
402 | + elif not self.__valid_nickname_regexp.match(nick): |
403 | + self.reply("432 * %s :Erroneous nickname" % nick) |
404 | + else: |
405 | + self.nickname = nick |
406 | + server.client_changed_nickname(self, None) |
407 | + elif command == "USER": |
408 | + if len(arguments) < 4: |
409 | + self.reply_461("USER") |
410 | + return |
411 | + self.user = arguments[0] |
412 | + self.realname = arguments[3] |
413 | + elif command == "QUIT": |
414 | + self.disconnect("Client quit") |
415 | + return |
416 | + if self.nickname and self.user: |
417 | + self.reply("001 %s :Hi, welcome to IRC" % self.nickname) |
418 | + self.reply("002 %s :Your host is %s, running version miniircd-%s" |
419 | + % (self.nickname, server.name, VERSION)) |
420 | + self.reply("003 %s :This server was created sometime" |
421 | + % self.nickname) |
422 | + self.reply("004 %s :%s miniircd-%s o o" |
423 | + % (self.nickname, server.name, VERSION)) |
424 | + self.send_lusers() |
425 | + self.send_motd() |
426 | + self.__handle_command = self.__command_handler |
427 | + |
428 | + def __command_handler(self, command, arguments): |
429 | + def away_handler(): |
430 | + pass |
431 | + |
432 | + def ison_handler(): |
433 | + if len(arguments) < 1: |
434 | + self.reply_461("ISON") |
435 | + return |
436 | + nicks = arguments |
437 | + online = [n for n in nicks if server.get_client(n)] |
438 | + self.reply("303 %s :%s" % (self.nickname, " ".join(online))) |
439 | + |
440 | + def join_handler(): |
441 | + if len(arguments) < 1: |
442 | + self.reply_461("JOIN") |
443 | + return |
444 | + if arguments[0] == "0": |
445 | + for (channelname, channel) in self.channels.items(): |
446 | + self.message_channel(channel, "PART", channelname, True) |
447 | + self.channel_log(channel, "left", meta=True) |
448 | + server.remove_member_from_channel(self, channelname) |
449 | + self.channels = {} |
450 | + return |
451 | + channelnames = arguments[0].split(",") |
452 | + if len(arguments) > 1: |
453 | + keys = arguments[1].split(",") |
454 | + else: |
455 | + keys = [] |
456 | + keys.extend((len(channelnames) - len(keys)) * [None]) |
457 | + for (i, channelname) in enumerate(channelnames): |
458 | + if irc_lower(channelname) in self.channels: |
459 | + continue |
460 | + if not valid_channel_re.match(channelname): |
461 | + self.reply_403(channelname) |
462 | + continue |
463 | + channel = server.get_channel(channelname) |
464 | + if channel.key is not None and channel.key != keys[i]: |
465 | + self.reply( |
466 | + "475 %s %s :Cannot join channel (+k) - bad key" |
467 | + % (self.nickname, channelname)) |
468 | + continue |
469 | + channel.add_member(self) |
470 | + self.channels[irc_lower(channelname)] = channel |
471 | + self.message_channel(channel, "JOIN", channelname, True) |
472 | + self.channel_log(channel, "joined", meta=True) |
473 | + if channel.topic: |
474 | + self.reply("332 %s %s :%s" |
475 | + % (self.nickname, channel.name, channel.topic)) |
476 | + else: |
477 | + self.reply("331 %s %s :No topic is set" |
478 | + % (self.nickname, channel.name)) |
479 | + self.reply("353 %s = %s :%s" |
480 | + % (self.nickname, |
481 | + channelname, |
482 | + " ".join(sorted(x.nickname |
483 | + for x in channel.members)))) |
484 | + self.reply("366 %s %s :End of NAMES list" |
485 | + % (self.nickname, channelname)) |
486 | + |
487 | + def list_handler(): |
488 | + if len(arguments) < 1: |
489 | + channels = server.channels.values() |
490 | + else: |
491 | + channels = [] |
492 | + for channelname in arguments[0].split(","): |
493 | + if server.has_channel(channelname): |
494 | + channels.append(server.get_channel(channelname)) |
495 | + channels.sort(key=lambda x: x.name) |
496 | + for channel in channels: |
497 | + self.reply("322 %s %s %d :%s" |
498 | + % (self.nickname, channel.name, |
499 | + len(channel.members), channel.topic)) |
500 | + self.reply("323 %s :End of LIST" % self.nickname) |
501 | + |
502 | + def lusers_handler(): |
503 | + self.send_lusers() |
504 | + |
505 | + def mode_handler(): |
506 | + if len(arguments) < 1: |
507 | + self.reply_461("MODE") |
508 | + return |
509 | + targetname = arguments[0] |
510 | + if server.has_channel(targetname): |
511 | + channel = server.get_channel(targetname) |
512 | + if len(arguments) < 2: |
513 | + if channel.key: |
514 | + modes = "+k" |
515 | + if irc_lower(channel.name) in self.channels: |
516 | + modes += " %s" % channel.key |
517 | + else: |
518 | + modes = "+" |
519 | + self.reply("324 %s %s %s" |
520 | + % (self.nickname, targetname, modes)) |
521 | + return |
522 | + flag = arguments[1] |
523 | + if flag == "+k": |
524 | + if len(arguments) < 3: |
525 | + self.reply_461("MODE") |
526 | + return |
527 | + key = arguments[2] |
528 | + if irc_lower(channel.name) in self.channels: |
529 | + channel.key = key |
530 | + self.message_channel( |
531 | + channel, "MODE", "%s +k %s" % (channel.name, key), |
532 | + True) |
533 | + self.channel_log( |
534 | + channel, "set channel key to %s" % key, meta=True) |
535 | + else: |
536 | + self.reply("442 %s :You're not on that channel" |
537 | + % targetname) |
538 | + elif flag == "-k": |
539 | + if irc_lower(channel.name) in self.channels: |
540 | + channel.key = None |
541 | + self.message_channel( |
542 | + channel, "MODE", "%s -k" % channel.name, |
543 | + True) |
544 | + self.channel_log( |
545 | + channel, "removed channel key", meta=True) |
546 | + else: |
547 | + self.reply("442 %s :You're not on that channel" |
548 | + % targetname) |
549 | + else: |
550 | + self.reply("472 %s %s :Unknown MODE flag" |
551 | + % (self.nickname, flag)) |
552 | + elif targetname == self.nickname: |
553 | + if len(arguments) == 1: |
554 | + self.reply("221 %s +" % self.nickname) |
555 | + else: |
556 | + self.reply("501 %s :Unknown MODE flag" % self.nickname) |
557 | + else: |
558 | + self.reply_403(targetname) |
559 | + |
560 | + def motd_handler(): |
561 | + self.send_motd() |
562 | + |
563 | + def nick_handler(): |
564 | + if len(arguments) < 1: |
565 | + self.reply("431 :No nickname given") |
566 | + return |
567 | + newnick = arguments[0] |
568 | + client = server.get_client(newnick) |
569 | + if newnick == self.nickname: |
570 | + pass |
571 | + elif client and client is not self: |
572 | + self.reply("433 %s %s :Nickname is already in use" |
573 | + % (self.nickname, newnick)) |
574 | + elif not self.__valid_nickname_regexp.match(newnick): |
575 | + self.reply("432 %s %s :Erroneous Nickname" |
576 | + % (self.nickname, newnick)) |
577 | + else: |
578 | + for x in self.channels.values(): |
579 | + self.channel_log( |
580 | + x, "changed nickname to %s" % newnick, meta=True) |
581 | + oldnickname = self.nickname |
582 | + self.nickname = newnick |
583 | + server.client_changed_nickname(self, oldnickname) |
584 | + self.message_related( |
585 | + ":%s!%s@%s NICK %s" |
586 | + % (oldnickname, self.user, self.host, self.nickname), |
587 | + True) |
588 | + |
589 | + def notice_and_privmsg_handler(): |
590 | + if len(arguments) == 0: |
591 | + self.reply("411 %s :No recipient given (%s)" |
592 | + % (self.nickname, command)) |
593 | + return |
594 | + if len(arguments) == 1: |
595 | + self.reply("412 %s :No text to send" % self.nickname) |
596 | + return |
597 | + targetname = arguments[0] |
598 | + message = arguments[1] |
599 | + client = server.get_client(targetname) |
600 | + |
601 | + if client: |
602 | + client.message(":%s %s %s :%s" |
603 | + % (self.prefix, command, targetname, message)) |
604 | + elif server.has_channel(targetname): |
605 | + channel = server.get_channel(targetname) |
606 | + self.message_channel( |
607 | + channel, command, "%s :%s" % (channel.name, message)) |
608 | + self.channel_log(channel, message) |
609 | + else: |
610 | + self.reply("401 %s %s :No such nick/channel" |
611 | + % (self.nickname, targetname)) |
612 | + |
613 | + def part_handler(): |
614 | + if len(arguments) < 1: |
615 | + self.reply_461("PART") |
616 | + return |
617 | + if len(arguments) > 1: |
618 | + partmsg = arguments[1] |
619 | + else: |
620 | + partmsg = self.nickname |
621 | + for channelname in arguments[0].split(","): |
622 | + if not valid_channel_re.match(channelname): |
623 | + self.reply_403(channelname) |
624 | + elif not irc_lower(channelname) in self.channels: |
625 | + self.reply("442 %s %s :You're not on that channel" |
626 | + % (self.nickname, channelname)) |
627 | + else: |
628 | + channel = self.channels[irc_lower(channelname)] |
629 | + self.message_channel( |
630 | + channel, "PART", "%s :%s" % (channelname, partmsg), |
631 | + True) |
632 | + self.channel_log(channel, "left (%s)" % partmsg, meta=True) |
633 | + del self.channels[irc_lower(channelname)] |
634 | + server.remove_member_from_channel(self, channelname) |
635 | + |
636 | + def ping_handler(): |
637 | + if len(arguments) < 1: |
638 | + self.reply("409 %s :No origin specified" % self.nickname) |
639 | + return |
640 | + self.reply("PONG %s :%s" % (server.name, arguments[0])) |
641 | + |
642 | + def pong_handler(): |
643 | + pass |
644 | + |
645 | + def quit_handler(): |
646 | + if len(arguments) < 1: |
647 | + quitmsg = self.nickname |
648 | + else: |
649 | + quitmsg = arguments[0] |
650 | + self.disconnect(quitmsg) |
651 | + |
652 | + def topic_handler(): |
653 | + if len(arguments) < 1: |
654 | + self.reply_461("TOPIC") |
655 | + return |
656 | + channelname = arguments[0] |
657 | + channel = self.channels.get(irc_lower(channelname)) |
658 | + if channel: |
659 | + if len(arguments) > 1: |
660 | + newtopic = arguments[1] |
661 | + channel.topic = newtopic |
662 | + self.message_channel( |
663 | + channel, "TOPIC", "%s :%s" % (channelname, newtopic), |
664 | + True) |
665 | + self.channel_log( |
666 | + channel, "set topic to %r" % newtopic, meta=True) |
667 | + else: |
668 | + if channel.topic: |
669 | + self.reply("332 %s %s :%s" |
670 | + % (self.nickname, channel.name, |
671 | + channel.topic)) |
672 | + else: |
673 | + self.reply("331 %s %s :No topic is set" |
674 | + % (self.nickname, channel.name)) |
675 | + else: |
676 | + self.reply("442 %s :You're not on that channel" % channelname) |
677 | + |
678 | + def wallops_handler(): |
679 | + if len(arguments) < 1: |
680 | + self.reply_461(command) |
681 | + message = arguments[0] |
682 | + for client in server.clients.values(): |
683 | + client.message(":%s NOTICE %s :Global notice: %s" |
684 | + % (self.prefix, client.nickname, message)) |
685 | + |
686 | + def who_handler(): |
687 | + if len(arguments) < 1: |
688 | + return |
689 | + targetname = arguments[0] |
690 | + if server.has_channel(targetname): |
691 | + channel = server.get_channel(targetname) |
692 | + for member in channel.members: |
693 | + self.reply("352 %s %s %s %s %s %s H :0 %s" |
694 | + % (self.nickname, targetname, member.user, |
695 | + member.host, server.name, member.nickname, |
696 | + member.realname)) |
697 | + self.reply("315 %s %s :End of WHO list" |
698 | + % (self.nickname, targetname)) |
699 | + |
700 | + def whois_handler(): |
701 | + if len(arguments) < 1: |
702 | + return |
703 | + username = arguments[0] |
704 | + user = server.get_client(username) |
705 | + if user: |
706 | + self.reply("311 %s %s %s %s * :%s" |
707 | + % (self.nickname, user.nickname, user.user, |
708 | + user.host, user.realname)) |
709 | + self.reply("312 %s %s %s :%s" |
710 | + % (self.nickname, user.nickname, server.name, |
711 | + server.name)) |
712 | + self.reply("319 %s %s :%s" |
713 | + % (self.nickname, user.nickname, |
714 | + " ".join(user.channels))) |
715 | + self.reply("318 %s %s :End of WHOIS list" |
716 | + % (self.nickname, user.nickname)) |
717 | + else: |
718 | + self.reply("401 %s %s :No such nick" |
719 | + % (self.nickname, username)) |
720 | + |
721 | + handler_table = { |
722 | + "AWAY": away_handler, |
723 | + "ISON": ison_handler, |
724 | + "JOIN": join_handler, |
725 | + "LIST": list_handler, |
726 | + "LUSERS": lusers_handler, |
727 | + "MODE": mode_handler, |
728 | + "MOTD": motd_handler, |
729 | + "NICK": nick_handler, |
730 | + "NOTICE": notice_and_privmsg_handler, |
731 | + "PART": part_handler, |
732 | + "PING": ping_handler, |
733 | + "PONG": pong_handler, |
734 | + "PRIVMSG": notice_and_privmsg_handler, |
735 | + "QUIT": quit_handler, |
736 | + "TOPIC": topic_handler, |
737 | + "WALLOPS": wallops_handler, |
738 | + "WHO": who_handler, |
739 | + "WHOIS": whois_handler, |
740 | + } |
741 | + server = self.server |
742 | + valid_channel_re = self.__valid_channelname_regexp |
743 | + try: |
744 | + handler_table[command]() |
745 | + except KeyError: |
746 | + self.reply("421 %s %s :Unknown command" % (self.nickname, command)) |
747 | + |
748 | + def udp_data_received(self, data): |
749 | + if data: |
750 | + message = self.infosec.unpack(data) |
751 | + if(message != None): |
752 | + self.message(message) |
753 | + |
754 | + def socket_readable_notification(self): |
755 | + try: |
756 | + data = self.socket.recv(2 ** 10) |
757 | + self.server.print_debug( |
758 | + "[%s:%d] -> %r" % (self.host, self.port, data)) |
759 | + quitmsg = "EOT" |
760 | + except socket.error as x: |
761 | + data = "" |
762 | + quitmsg = x |
763 | + if data: |
764 | + self.__readbuffer += data |
765 | + self.__parse_read_buffer() |
766 | + self.__timestamp = time.time() |
767 | + self.__sent_ping = False |
768 | + for peer in self.server.peers: |
769 | + peer.send(self, data) |
770 | + else: |
771 | + self.disconnect(quitmsg) |
772 | + |
773 | + def socket_writable_notification(self): |
774 | + try: |
775 | + print("socket_writable_notification: %s" % self.__writebuffer) |
776 | + sent = self.socket.send(self.__writebuffer) |
777 | + self.server.print_debug( |
778 | + "[%s:%d] <- %r" % ( |
779 | + self.host, self.port, self.__writebuffer[:sent])) |
780 | + self.__writebuffer = self.__writebuffer[sent:] |
781 | + except socket.error as x: |
782 | + self.disconnect(x) |
783 | + |
784 | + def disconnect(self, quitmsg): |
785 | + self.message("ERROR :%s" % quitmsg) |
786 | + self.server.print_info( |
787 | + "Disconnected connection from %s:%s (%s)." % ( |
788 | + self.host, self.port, quitmsg)) |
789 | + self.socket.close() |
790 | + self.server.remove_client(self, quitmsg) |
791 | + |
792 | + def message(self, msg): |
793 | + self.__writebuffer += msg + "\r\n" |
794 | + |
795 | + def reply(self, msg): |
796 | + self.message(":%s %s" % (self.server.name, msg)) |
797 | + |
798 | + def reply_403(self, channel): |
799 | + self.reply("403 %s %s :No such channel" % (self.nickname, channel)) |
800 | + |
801 | + def reply_461(self, command): |
802 | + nickname = self.nickname or "*" |
803 | + self.reply("461 %s %s :Not enough parameters" % (nickname, command)) |
804 | + |
805 | + def message_channel(self, channel, command, message, include_self=False): |
806 | + line = ":%s %s %s" % (self.prefix, command, message) |
807 | + for client in channel.members: |
808 | + if client != self or include_self: |
809 | + client.message(line) |
810 | + |
811 | + def channel_log(self, channel, message, meta=False): |
812 | + if not self.server.logdir: |
813 | + return |
814 | + if meta: |
815 | + format = "[%s] * %s %s\n" |
816 | + else: |
817 | + format = "[%s] <%s> %s\n" |
818 | + timestamp = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC") |
819 | + logname = channel.name.replace("_", "__").replace("/", "_") |
820 | + fp = open("%s/%s.log" % (self.server.logdir, logname), "a") |
821 | + fp.write(format % (timestamp, self.nickname, message)) |
822 | + fp.close() |
823 | + |
824 | + def message_related(self, msg, include_self=False): |
825 | + clients = set() |
826 | + if include_self: |
827 | + clients.add(self) |
828 | + for channel in self.channels.values(): |
829 | + clients |= channel.members |
830 | + if not include_self: |
831 | + clients.discard(self) |
832 | + for client in clients: |
833 | + client.message(msg) |
834 | + |
835 | + def send_lusers(self): |
836 | + self.reply("251 %s :There are %d users and 0 services on 1 server" |
837 | + % (self.nickname, len(self.server.clients))) |
838 | + |
839 | + def send_motd(self): |
840 | + server = self.server |
841 | + motdlines = server.get_motd_lines() |
842 | + if motdlines: |
843 | + self.reply("375 %s :- %s Message of the day -" |
844 | + % (self.nickname, server.name)) |
845 | + for line in motdlines: |
846 | + self.reply("372 %s :- %s" % (self.nickname, line.rstrip())) |
847 | + self.reply("376 %s :End of /MOTD command" % self.nickname) |
848 | + else: |
849 | + self.reply("422 %s :MOTD File is missing" % self.nickname) |
850 | diff --git a/lib/funcs.py b/lib/funcs.py |
851 | new file mode 100644 |
852 | index 0000000..4093964 |
853 | |
854 | |
855 | |
856 | +import sys |
857 | +import string |
858 | + |
859 | +_maketrans = str.maketrans if sys.version_info[0] == 3 else string.maketrans |
860 | +_ircstring_translation = _maketrans( |
861 | + string.ascii_lowercase.upper() + "[]\\^", |
862 | + string.ascii_lowercase + "{}|~") |
863 | + |
864 | +def irc_lower(s): |
865 | + return string.translate(s, _ircstring_translation) |
866 | + |
867 | diff --git a/lib/infosec.py b/lib/infosec.py |
868 | new file mode 100644 |
869 | index 0000000..6e87ca6 |
870 | |
871 | |
872 | |
873 | +import hashlib |
874 | +PACKET_SIZE = 1024 |
875 | +MAX_MESSAGE_SIZE = 512 |
876 | + |
877 | +class Infosec(object): |
878 | + #def __init__(self): |
879 | + # do nothing |
880 | + |
881 | + def pack(self, message): |
882 | + digest = hashlib.sha512(self._pad(message)).hexdigest() |
883 | + return digest + message |
884 | + |
885 | + def unpack(self, package): |
886 | + print("received package: %s" % package) |
887 | + received_digest = package[0:128] |
888 | + message = package[128:1023] |
889 | + digest = hashlib.sha512(self._pad(message)).hexdigest() |
890 | + print("received_digest: %s" % received_digest) |
891 | + print("digest: %s" % digest) |
892 | + print("message: %s") % message |
893 | + if(received_digest == digest): |
894 | + return message |
895 | + else: |
896 | + print("unable to validate package: %s" % package) |
897 | + return None |
898 | + |
899 | + def _pad(self, text): |
900 | + return str(text.ljust(MAX_MESSAGE_SIZE)).encode("ascii") |
901 | + |
902 | diff --git a/lib/peer.py b/lib/peer.py |
903 | new file mode 100644 |
904 | index 0000000..4a64ed7 |
905 | |
906 | |
907 | |
908 | +import socket |
909 | +from infosec import Infosec |
910 | + |
911 | +class Peer(object): |
912 | + def __init__(self, address): |
913 | + self.address = address |
914 | + self.socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) |
915 | + self.infosec = Infosec() |
916 | + |
917 | + def send(self, client, msg): |
918 | + full_message = str.encode(":%s %s" % (client.nickname, msg)) |
919 | + print("sending formatted_msg: %s" % full_message) |
920 | + self.socket.sendto(self.infosec.pack(full_message), (self.address, 7778)) |
921 | diff --git a/lib/server.py b/lib/server.py |
922 | new file mode 100644 |
923 | index 0000000..38bf514 |
924 | |
925 | |
926 | |
927 | +VERSION = "9999" |
928 | + |
929 | +import os |
930 | +import select |
931 | +import socket |
932 | +import sys |
933 | +import sys |
934 | +import tempfile |
935 | +import time |
936 | +import string |
937 | +from datetime import datetime |
938 | +from lib.client import Client |
939 | +from lib.channel import Channel |
940 | +from lib.infosec import PACKET_SIZE |
941 | +from lib.infosec import Infosec |
942 | +from lib.peer import Peer |
943 | +from funcs import * |
944 | + |
945 | +class Server(object): |
946 | + def __init__(self, options): |
947 | + self.ports = options.ports |
948 | + self.peers = options.peers |
949 | + self.udp_port = options.udp_port |
950 | + self.password = options.password |
951 | + self.ssl_pem_file = options.ssl_pem_file |
952 | + self.motdfile = options.motd |
953 | + self.verbose = options.verbose |
954 | + self.debug = options.debug |
955 | + self.logdir = options.logdir |
956 | + self.chroot = options.chroot |
957 | + self.setuid = options.setuid |
958 | + self.statedir = options.statedir |
959 | + |
960 | + if options.listen: |
961 | + self.address = socket.gethostbyname(options.listen) |
962 | + else: |
963 | + self.address = "" |
964 | + server_name_limit = 63 # From the RFC. |
965 | + self.name = socket.getfqdn(self.address)[:server_name_limit] |
966 | + |
967 | + self.channels = {} # irc_lower(Channel name) --> Channel instance. |
968 | + self.clients = {} # Socket --> Client instance..peers = "" |
969 | + self.nicknames = {} # irc_lower(Nickname) --> Client instance. |
970 | + if self.logdir: |
971 | + create_directory(self.logdir) |
972 | + if self.statedir: |
973 | + create_directory(self.statedir) |
974 | + |
975 | + def daemonize(self): |
976 | + try: |
977 | + pid = os.fork() |
978 | + if pid > 0: |
979 | + sys.exit(0) |
980 | + except OSError: |
981 | + sys.exit(1) |
982 | + os.setsid() |
983 | + try: |
984 | + pid = os.fork() |
985 | + if pid > 0: |
986 | + self.print_info("PID: %d" % pid) |
987 | + sys.exit(0) |
988 | + except OSError: |
989 | + sys.exit(1) |
990 | + os.chdir("/") |
991 | + os.umask(0) |
992 | + dev_null = open("/dev/null", "r+") |
993 | + os.dup2(dev_null.fileno(), sys.stdout.fileno()) |
994 | + os.dup2(dev_null.fileno(), sys.stderr.fileno()) |
995 | + os.dup2(dev_null.fileno(), sys.stdin.fileno()) |
996 | + |
997 | + def get_client(self, nickname): |
998 | + return self.nicknames.get(irc_lower(nickname)) |
999 | + |
1000 | + def has_channel(self, name): |
1001 | + return irc_lower(name) in self.channels |
1002 | + |
1003 | + def get_channel(self, channelname): |
1004 | + if irc_lower(channelname) in self.channels: |
1005 | + channel = self.channels[irc_lower(channelname)] |
1006 | + else: |
1007 | + channel = Channel(self, channelname) |
1008 | + self.channels[irc_lower(channelname)] = channel |
1009 | + return channel |
1010 | + |
1011 | + def get_motd_lines(self): |
1012 | + if self.motdfile: |
1013 | + try: |
1014 | + return open(self.motdfile).readlines() |
1015 | + except IOError: |
1016 | + return ["Could not read MOTD file %r." % self.motdfile] |
1017 | + else: |
1018 | + return [] |
1019 | + |
1020 | + def print_info(self, msg): |
1021 | + if self.verbose: |
1022 | + print(msg) |
1023 | + sys.stdout.flush() |
1024 | + |
1025 | + def print_debug(self, msg): |
1026 | + if self.debug: |
1027 | + print(msg) |
1028 | + sys.stdout.flush() |
1029 | + |
1030 | + def print_error(self, msg): |
1031 | + sys.stderr.write("%s\n" % msg) |
1032 | + |
1033 | + def client_changed_nickname(self, client, oldnickname): |
1034 | + if oldnickname: |
1035 | + del self.nicknames[irc_lower(oldnickname)] |
1036 | + self.nicknames[irc_lower(client.nickname)] = client |
1037 | + |
1038 | + def remove_member_from_channel(self, client, channelname): |
1039 | + if irc_lower(channelname) in self.channels: |
1040 | + channel = self.channels[irc_lower(channelname)] |
1041 | + channel.remove_client(client) |
1042 | + |
1043 | + def remove_client(self, client, quitmsg): |
1044 | + client.message_related(":%s QUIT :%s" % (client.prefix, quitmsg)) |
1045 | + for x in client.channels.values(): |
1046 | + client.channel_log(x, "quit (%s)" % quitmsg, meta=True) |
1047 | + x.remove_client(client) |
1048 | + if client.nickname \ |
1049 | + and irc_lower(client.nickname) in self.nicknames: |
1050 | + del self.nicknames[irc_lower(client.nickname)] |
1051 | + del self.clients[client.socket] |
1052 | + |
1053 | + def remove_channel(self, channel): |
1054 | + del self.channels[irc_lower(channel.name)] |
1055 | + |
1056 | + def start(self): |
1057 | + # Setup UDP first |
1058 | + udp_server_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) |
1059 | + udp_server_socket.bind((self.address, self.udp_port)) |
1060 | + |
1061 | + serversockets = [] |
1062 | + for port in self.ports: |
1063 | + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
1064 | + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
1065 | + try: |
1066 | + s.bind((self.address, port)) |
1067 | + except socket.error as e: |
1068 | + self.print_error("Could not bind port %s: %s." % (port, e)) |
1069 | + sys.exit(1) |
1070 | + s.listen(5) |
1071 | + serversockets.append(s) |
1072 | + del s |
1073 | + self.print_info("Listening on port %d." % port) |
1074 | + if self.chroot: |
1075 | + os.chdir(self.chroot) |
1076 | + os.chroot(self.chroot) |
1077 | + self.print_info("Changed root directory to %s" % self.chroot) |
1078 | + if self.setuid: |
1079 | + os.setgid(self.setuid[1]) |
1080 | + os.setuid(self.setuid[0]) |
1081 | + self.print_info("Setting uid:gid to %s:%s" |
1082 | + % (self.setuid[0], self.setuid[1])) |
1083 | + last_aliveness_check = time.time() |
1084 | + while True: |
1085 | + (inputready,outputready,exceptready) = select.select([udp_server_socket],[],[],0) |
1086 | + (iwtd, owtd, ewtd) = select.select( |
1087 | + serversockets + [x.socket for x in self.clients.values()], |
1088 | + [x.socket for x in self.clients.values() |
1089 | + if x.write_queue_size() > 0], |
1090 | + [], |
1091 | + 0) |
1092 | + for x in inputready: |
1093 | + if x == udp_server_socket: |
1094 | + bytes_address_pair = udp_server_socket.recvfrom(PACKET_SIZE) |
1095 | + message = bytes_address_pair[0] |
1096 | + address = bytes_address_pair[1] |
1097 | + print message |
1098 | + for c in self.clients: |
1099 | + self.clients[c].udp_data_received(message) |
1100 | + for x in iwtd: |
1101 | + if x in self.clients: |
1102 | + self.clients[x].socket_readable_notification() |
1103 | + else: |
1104 | + (conn, addr) = x.accept() |
1105 | + if self.ssl_pem_file: |
1106 | + import ssl |
1107 | + try: |
1108 | + conn = ssl.wrap_socket( |
1109 | + conn, |
1110 | + server_side=True, |
1111 | + certfile=self.ssl_pem_file, |
1112 | + keyfile=self.ssl_pem_file) |
1113 | + except ssl.SSLError as e: |
1114 | + self.print_error( |
1115 | + "SSL error for connection from %s:%s: %s" % ( |
1116 | + addr[0], addr[1], e)) |
1117 | + continue |
1118 | + self.clients[conn] = Client(self, conn) |
1119 | + self.print_info("Accepted connection from %s:%s." % ( |
1120 | + addr[0], addr[1])) |
1121 | + for x in owtd: |
1122 | + if x in self.clients: # client may have been disconnected |
1123 | + self.clients[x].socket_writable_notification() |
1124 | + now = time.time() |
1125 | + if last_aliveness_check + 10 < now: |
1126 | + for client in self.clients.values(): |
1127 | + client.check_aliveness() |
1128 | + last_aliveness_check = now |
1129 | + |
1130 | + |
1131 | +def create_directory(path): |
1132 | + if not os.path.isdir(path): |
1133 | + os.makedirs(path) |
1134 | + |
1135 |
Prototype UDP based IRC Emulator
Wednesday, July 28th, 2021
I have hacked up a very simple IRC server written in python that broadcasts messages via UDP to a list of other servers of the same type.
The original IRC server is from this Shithub. I made this mostly just to experiment with UDP and learn something about the IRC protocol.
At the moment all it will do is share PRIVMSGs between servers. It doesn't handle pretty much anything else, such as for example JOIN/PART messages.
1 #! /usr/bin/env python 2 3 VERSION = "1.1" 4 5 import os 6 import re 7 import select 8 import socket 9 import string 10 import sys 11 import tempfile 12 import time 13 from datetime import datetime 14 from optparse import OptionParser 15 16 17 def create_directory(path): 18 if not os.path.isdir(path): 19 os.makedirs(path) 20 21 22 class Channel(object): 23 def __init__(self, server, name): 24 self.server = server 25 self.name = name 26 self.members = set() 27 self._topic = "" 28 self._key = None 29 if self.server.statedir: 30 self._state_path = "%s/%s" % ( 31 self.server.statedir, 32 name.replace("_", "__").replace("/", "_")) 33 self._read_state() 34 else: 35 self._state_path = None 36 37 def add_member(self, client): 38 self.members.add(client) 39 40 def get_topic(self): 41 return self._topic 42 43 def set_topic(self, value): 44 self._topic = value 45 self._write_state() 46 47 topic = property(get_topic, set_topic) 48 49 def get_key(self): 50 return self._key 51 52 def set_key(self, value): 53 self._key = value 54 self._write_state() 55 56 key = property(get_key, set_key) 57 58 def remove_client(self, client): 59 self.members.discard(client) 60 if not self.members: 61 self.server.remove_channel(self) 62 63 def _read_state(self): 64 if not (self._state_path and os.path.exists(self._state_path)): 65 return 66 data = {} 67 exec(open(self._state_path), {}, data) 68 self._topic = data.get("topic", "") 69 self._key = data.get("key") 70 71 def _write_state(self): 72 if not self._state_path: 73 return 74 (fd, path) = tempfile.mkstemp(dir=os.path.dirname(self._state_path)) 75 fp = os.fdopen(fd, "w") 76 fp.write("topic = %r\n" % self.topic) 77 fp.write("key = %r\n" % self.key) 78 fp.close() 79 os.rename(path, self._state_path) 80 81 82 class Client(object): 83 __linesep_regexp = re.compile(r"\r?\n") 84 # The RFC limit for nicknames is 9 characters, but what the heck. 85 __valid_nickname_regexp = re.compile( 86 r"^[][\`_^{|}A-Za-z][][\`_^{|}A-Za-z0-9-]{0,50}$") 87 __valid_channelname_regexp = re.compile( 88 r"^[+!][^\x00\x07\x0a\x0d ,:]{0,50}$") 89 90 def __init__(self, server, socket): 91 self.server = server 92 self.socket = socket 93 self.channels = {} # irc_lower(Channel name) --> Channel 94 self.nickname = None 95 self.user = None 96 self.realname = None 97 (self.host, self.port) = socket.getpeername() 98 self.__timestamp = time.time() 99 self.__readbuffer = "" 100 self.__writebuffer = "" 101 self.__sent_ping = False 102 if self.server.password: 103 self.__handle_command = self.__pass_handler 104 else: 105 self.__handle_command = self.__registration_handler 106 107 def get_prefix(self): 108 return "%s!%s@%s" % (self.nickname, self.user, self.host) 109 prefix = property(get_prefix) 110 111 def check_aliveness(self): 112 now = time.time() 113 if self.__timestamp + 180 < now: 114 self.disconnect("ping timeout") 115 return 116 if not self.__sent_ping and self.__timestamp + 90 < now: 117 if self.__handle_command == self.__command_handler: 118 # Registered. 119 self.message("PING :%s" % self.server.name) 120 self.__sent_ping = True 121 else: 122 # Not registered. 123 self.disconnect("ping timeout") 124 125 def write_queue_size(self): 126 return len(self.__writebuffer) 127 128 def __parse_read_buffer(self): 129 lines = self.__linesep_regexp.split(self.__readbuffer) 130 self.__readbuffer = lines[-1] 131 lines = lines[:-1] 132 for line in lines: 133 if not line: 134 # Empty line. Ignore. 135 continue 136 x = line.split(" ", 1) 137 command = x[0].upper() 138 if len(x) == 1: 139 arguments = [] 140 else: 141 if len(x[1]) > 0 and x[1][0] == ":": 142 arguments = \[x\[1][1:\]\] 143 else: 144 y = string.split(x[1], " :", 1) 145 arguments = string.split(y[0]) 146 if len(y) == 2: 147 arguments.append(y[1]) 148 self.__handle_command(command, arguments) 149 150 def __pass_handler(self, command, arguments): 151 server = self.server 152 if command == "PASS": 153 if len(arguments) == 0: 154 self.reply_461("PASS") 155 else: 156 if arguments[0].lower() == server.password: 157 self.__handle_command = self.__registration_handler 158 else: 159 self.reply("464 :Password incorrect") 160 elif command == "QUIT": 161 self.disconnect("Client quit") 162 return 163 164 def __registration_handler(self, command, arguments): 165 server = self.server 166 if command == "NICK": 167 if len(arguments) < 1: 168 self.reply("431 :No nickname given") 169 return 170 nick = arguments[0] 171 if server.get_client(nick): 172 self.reply("433 * %s :Nickname is already in use" % nick) 173 elif not self.__valid_nickname_regexp.match(nick): 174 self.reply("432 * %s :Erroneous nickname" % nick) 175 else: 176 self.nickname = nick 177 server.client_changed_nickname(self, None) 178 elif command == "USER": 179 if len(arguments) < 4: 180 self.reply_461("USER") 181 return 182 self.user = arguments[0] 183 self.realname = arguments[3] 184 elif command == "QUIT": 185 self.disconnect("Client quit") 186 return 187 if self.nickname and self.user: 188 self.reply("001 %s :Hi, welcome to IRC" % self.nickname) 189 self.reply("002 %s :Your host is %s, running version miniircd-%s" 190 % (self.nickname, server.name, VERSION)) 191 self.reply("003 %s :This server was created sometime" 192 % self.nickname) 193 self.reply("004 %s :%s miniircd-%s o o" 194 % (self.nickname, server.name, VERSION)) 195 self.send_lusers() 196 self.send_motd() 197 self.__handle_command = self.__command_handler 198 199 def __command_handler(self, command, arguments): 200 def away_handler(): 201 pass 202 203 def ison_handler(): 204 if len(arguments) < 1: 205 self.reply_461("ISON") 206 return 207 nicks = arguments 208 online = [n for n in nicks if server.get_client(n)] 209 self.reply("303 %s :%s" % (self.nickname, " ".join(online))) 210 211 def join_handler(): 212 if len(arguments) < 1: 213 self.reply_461("JOIN") 214 return 215 if arguments[0] == "0": 216 for (channelname, channel) in self.channels.items(): 217 self.message_channel(channel, "PART", channelname, True) 218 self.channel_log(channel, "left", meta=True) 219 server.remove_member_from_channel(self, channelname) 220 self.channels = {} 221 return 222 channelnames = arguments[0].split(",") 223 if len(arguments) > 1: 224 keys = arguments[1].split(",") 225 else: 226 keys = [] 227 keys.extend((len(channelnames) - len(keys)) * [None]) 228 for (i, channelname) in enumerate(channelnames): 229 if irc_lower(channelname) in self.channels: 230 continue 231 if not valid_channel_re.match(channelname): 232 self.reply_403(channelname) 233 continue 234 channel = server.get_channel(channelname) 235 if channel.key is not None and channel.key != keys[i]: 236 self.reply( 237 "475 %s %s :Cannot join channel (+k) - bad key" 238 % (self.nickname, channelname)) 239 continue 240 channel.add_member(self) 241 self.channels[irc_lower(channelname)] = channel 242 self.message_channel(channel, "JOIN", channelname, True) 243 self.channel_log(channel, "joined", meta=True) 244 if channel.topic: 245 self.reply("332 %s %s :%s" 246 % (self.nickname, channel.name, channel.topic)) 247 else: 248 self.reply("331 %s %s :No topic is set" 249 % (self.nickname, channel.name)) 250 self.reply("353 %s = %s :%s" 251 % (self.nickname, 252 channelname, 253 " ".join(sorted(x.nickname 254 for x in channel.members)))) 255 self.reply("366 %s %s :End of NAMES list" 256 % (self.nickname, channelname)) 257 258 def list_handler(): 259 if len(arguments) < 1: 260 channels = server.channels.values() 261 else: 262 channels = [] 263 for channelname in arguments[0].split(","): 264 if server.has_channel(channelname): 265 channels.append(server.get_channel(channelname)) 266 channels.sort(key=lambda x: x.name) 267 for channel in channels: 268 self.reply("322 %s %s %d :%s" 269 % (self.nickname, channel.name, 270 len(channel.members), channel.topic)) 271 self.reply("323 %s :End of LIST" % self.nickname) 272 273 def lusers_handler(): 274 self.send_lusers() 275 276 def mode_handler(): 277 if len(arguments) < 1: 278 self.reply_461("MODE") 279 return 280 targetname = arguments[0] 281 if server.has_channel(targetname): 282 channel = server.get_channel(targetname) 283 if len(arguments) < 2: 284 if channel.key: 285 modes = "+k" 286 if irc_lower(channel.name) in self.channels: 287 modes += " %s" % channel.key 288 else: 289 modes = "+" 290 self.reply("324 %s %s %s" 291 % (self.nickname, targetname, modes)) 292 return 293 flag = arguments[1] 294 if flag == "+k": 295 if len(arguments) < 3: 296 self.reply_461("MODE") 297 return 298 key = arguments[2] 299 if irc_lower(channel.name) in self.channels: 300 channel.key = key 301 self.message_channel( 302 channel, "MODE", "%s +k %s" % (channel.name, key), 303 True) 304 self.channel_log( 305 channel, "set channel key to %s" % key, meta=True) 306 else: 307 self.reply("442 %s :You're not on that channel" 308 % targetname) 309 elif flag == "-k": 310 if irc_lower(channel.name) in self.channels: 311 channel.key = None 312 self.message_channel( 313 channel, "MODE", "%s -k" % channel.name, 314 True) 315 self.channel_log( 316 channel, "removed channel key", meta=True) 317 else: 318 self.reply("442 %s :You're not on that channel" 319 % targetname) 320 else: 321 self.reply("472 %s %s :Unknown MODE flag" 322 % (self.nickname, flag)) 323 elif targetname == self.nickname: 324 if len(arguments) == 1: 325 self.reply("221 %s +" % self.nickname) 326 else: 327 self.reply("501 %s :Unknown MODE flag" % self.nickname) 328 else: 329 self.reply_403(targetname) 330 331 def motd_handler(): 332 self.send_motd() 333 334 def nick_handler(): 335 if len(arguments) < 1: 336 self.reply("431 :No nickname given") 337 return 338 newnick = arguments[0] 339 client = server.get_client(newnick) 340 if newnick == self.nickname: 341 pass 342 elif client and client is not self: 343 self.reply("433 %s %s :Nickname is already in use" 344 % (self.nickname, newnick)) 345 elif not self.__valid_nickname_regexp.match(newnick): 346 self.reply("432 %s %s :Erroneous Nickname" 347 % (self.nickname, newnick)) 348 else: 349 for x in self.channels.values(): 350 self.channel_log( 351 x, "changed nickname to %s" % newnick, meta=True) 352 oldnickname = self.nickname 353 self.nickname = newnick 354 server.client_changed_nickname(self, oldnickname) 355 self.message_related( 356 ":%s!%s@%s NICK %s" 357 % (oldnickname, self.user, self.host, self.nickname), 358 True) 359 360 def notice_and_privmsg_handler(): 361 if len(arguments) == 0: 362 self.reply("411 %s :No recipient given (%s)" 363 % (self.nickname, command)) 364 return 365 if len(arguments) == 1: 366 self.reply("412 %s :No text to send" % self.nickname) 367 return 368 targetname = arguments[0] 369 message = arguments[1] 370 client = server.get_client(targetname) 371