Last active
December 31, 2015 18:22
-
-
Save com4/8026566 to your computer and use it in GitHub Desktop.
pycrypto based, blowfish irc encryption plugin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
""" | |
enc.py | |
URL: https://gist.github.com/com4/8026566/ | |
Description: pycrypto based, blowfish irc encryption plugin | |
Clients | |
------- | |
* X-Chat | |
* Install: Place this file in .config/xchat2 and type /py load enc.py. It will be auto-loaded when X-Chat opens. | |
Probably Works On | |
----------------- | |
* X-Chat | |
* Ubuntu | |
* Fedora | |
* Arch Linux | |
* OS X & XChat Azure | |
$ ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future sudo pip install pycrypto | |
$ mv enc.py ~/Library/Containers/org.3rddev.xchatazure/Data/Library/Application\ Support/XChat\ Azure/plugins/ # to autoload | |
Commands | |
-------- | |
/listkeys - list current keys | |
/setkey <#chan|nick> <key> - add <key> for #chan or private messages with <nick> | |
/delkey <#chan|nick> - remove the key | |
Changes | |
-------- | |
0.1.1 - strip out bouncer replay timestamps | |
0.1 - initial release | |
""" | |
# SETTINGS | |
############################################################## | |
# A secret phrase used to encrypt the channel key database | |
KEYPASS='asdf' # CHANGE THIS TO ENCRYPT YOUR KEYS | |
############################################################## | |
__module_name__ = "enc" | |
__module_version__ = "0.1.1" | |
__module_description__ = "universal blowfish irc plugin" | |
import base64 | |
import cPickle as pickle | |
import os | |
from random import randrange | |
import re | |
from Crypto.Cipher.Blowfish import BlowfishCipher as Blowfish | |
import xchat | |
encrypted_file = os.path.join(xchat.get_info('xchatdir'), 'enc.secure_pickle') | |
_mb = Blowfish(KEYPASS) | |
def pad(s): | |
pad_bytes = 8 - (len(s) % 8) | |
for i in range(pad_bytes - 1): | |
s += chr(randrange(0, 256)) | |
bflag = randrange(6, 248); bflag -= bflag % 8 - pad_bytes | |
s += chr(bflag) | |
return s | |
def depad(s): | |
pad_bytes = ord(s[-1]) % 8 | |
if not pad_bytes: | |
pad_bytes = 8 | |
return s[:-pad_bytes] | |
e = lambda b, s: b.encrypt(pad(s)) | |
e64 = lambda b, s: base64.b64encode(e(b, s)) | |
d = lambda b, s: depad(b.decrypt(s)) | |
d64 = lambda b, s: d(b, base64.b64decode(s)) | |
def map_deflate(): | |
pass | |
_M = {} | |
def get_map_obj(key): | |
try: | |
return _M[key] | |
except KeyError: | |
_M[key] = Blowfish(MAP[key]) | |
return _M[key] | |
MAP = {} | |
if os.path.exists(encrypted_file): | |
with open(encrypted_file, "rb") as f: | |
s = depad(_mb.decrypt(f.read())) | |
MAP = pickle.loads(s) | |
print("loaded your enc keys") | |
def on_send(word, word_eol, userdata): | |
# 0 = nick | |
# 1 = text | |
mynick = xchat.get_info("nick") | |
nick = xchat.get_context().get_info("channel") | |
msg = word_eol[0] | |
try: | |
secret_str = e64(get_map_obj(nick), msg) | |
except KeyError: | |
return xchat.EAT_NONE | |
xchat.command('PRIVMSG %s :+OK %s' % (nick, secret_str)) | |
xchat.emit_print("Your Message", "⚷%s" % mynick, d64(get_map_obj(nick), secret_str)) | |
del(msg) | |
return xchat.EAT_ALL | |
def on_message(word, word_eol, userdata): | |
# 0 = nick | |
# 1 = text | |
channel = xchat.get_context().get_info("channel") | |
nick = word[0] | |
bouncer_match = re.match(r"^(\[\d{2}:\d{2}:\d{2}\] )(.*)", word[1]) | |
if bouncer_match: | |
raw_text = bouncer_match.groups()[1] | |
else: | |
raw_text = word[1] | |
if raw_text.startswith("+OK "): | |
enc_str = raw_text.split(" ")[1] | |
try: | |
secret_str = d64(get_map_obj(channel), enc_str) | |
except KeyError: | |
return xchat.EAT_NONE | |
if bouncer_match: | |
secret_str = "%s %s" % (bouncer_match.groups()[0].strip(), secret_str) | |
xchat.emit_print("Channel Message", "⚷%s" % nick, secret_str, "@") | |
del(raw_text) | |
return xchat.EAT_ALL | |
def unload(userdata): | |
with open(encrypted_file, 'wb') as f: | |
f.write(_mb.encrypt(pad(pickle.dumps(MAP)))) | |
print("saved your enc keys") | |
print("unloaded enc!") | |
def xsetkey(word, word_eol, userdata): | |
try: | |
chan = word[1] | |
key = word[2] | |
except KeyError: | |
print("USAGE: /setkey <#chan|nick> <key>") | |
return xchat.EAT_NONE | |
print("Set key for %s") % (chan,) | |
try: | |
del(_M[chan]) | |
except KeyError: | |
pass | |
MAP[chan] = key | |
def xdelkey(word, word_eol, userdata): | |
try: | |
chan = word[1] | |
except (KeyError, IndexError): | |
print("USAGE: /delkey <#chan|nick>") | |
return xchat.EAT_NONE | |
print("Removed %s") % (chan,) | |
del(MAP[chan]) | |
del(_M[chan]) | |
def xlistkeys(word, word_eol, userdata): | |
print(" %s" % ("-"*63,)) | |
print("| %s| %s|" % ("channel/nick".ljust(20), "key".ljust(40))) | |
print(" %s" % ("-"*63,)) | |
for k in MAP: | |
print("| %s| %s|" % (k.ljust(20), MAP[k].ljust(40))) | |
else: | |
if len(MAP) < 1: | |
print("| %s |" % "no keys".center(61)) | |
print(" %s" % ("-"*63,)) | |
xchat.hook_print("Channel Message", on_message) | |
xchat.hook_print("Private Message", on_message) | |
xchat.hook_print("Private Message to Dialog", on_message) | |
xchat.hook_command("", on_send) | |
xchat.hook_command("setkey", xsetkey) | |
xchat.hook_command("delkey", xdelkey) | |
xchat.hook_command("listkeys", xlistkeys) | |
xchat.hook_unload(unload) | |
print("loaded enc") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment