Important:
This tool still is in early development phase and the encryption has not been tested nor peer-reviewed by enough people.
It might be insecure at this point!
Please, do not put your life in the hands of AnonTwi, perhaps is not yet prepared
for that responsibility.
The code below is used for encryption and decryption.
We are working to improve the better encryption algorithm for 140 characters, so, if you have some ideas,
suggestions or code, please JOIN US at:
irc.freenode.net - #anontwi
===========================
AnonTwi code to De/Encrypt:
=================================
#!/usr/bin/python
# -*- coding: iso-8859-15 -*-
"""
$Id$
This file is part of the anontwi project, http://anontwi.sourceforge.net.
Copyright (c) 2012/2015 psy 'root@lordepsylon.net' - 'epsylon@riseup.net'
anontwi is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation version 3 of the License.
anontwi is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public License along
with anontwi; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
###################################################################
# See https://en.wikipedia.org/wiki/HMAC#Implementation
# Example written by: michael@briarproject.org
###################################################################
# Constants for AES256 and HMAC-SHA1
KEY_SIZE = 32
BLOCK_SIZE = 16
MAC_SIZE = 20
from os import urandom
from hashlib import sha1, sha256
from Crypto.Cipher import AES
from base64 import b64encode, b64decode
trans_5C = "".join([chr (x ^ 0x5c) for x in xrange(256)])
trans_36 = "".join([chr (x ^ 0x36) for x in xrange(256)])
def hmac_sha1(key, msg):
if len(key) > 20:
key = sha1(key).digest()
key += chr(0) * (20 - len(key))
o_key_pad = key.translate(trans_5C)
i_key_pad = key.translate(trans_36)
return sha1(o_key_pad + sha1(i_key_pad + msg).digest()).digest()
def derive_keys(key):
h = sha256()
h.update(key)
h.update('cipher')
cipher_key = h.digest()
h = sha256()
h.update(key)
h.update('mac')
mac_key = h.digest()
return (cipher_key, mac_key)
def generate_key():
return b64encode(urandom(KEY_SIZE))
class Cipher(object):
"""
Cipher class
"""
def __init__(self, key="", text=""):
"""
Init
"""
self.block_size = 16
self.mac_size = 20
self.key = self.set_key(key)
self.text = self.set_text(text)
self.mode = AES.MODE_CFB
def set_key(self, key):
"""
Set key
"""
# Base64 decode the key
try:
key = b64decode(key)
except TypeError:
raise ValueError
# The key must be the expected length
if len(key) != KEY_SIZE:
raise ValueError
self.key = key
return self.key
def set_text(self, text):
"""
Set text
"""
self.text = text
return self.text
def encrypt(self):
"""
Encrypt text
"""
# The IV, ciphertext and MAC can't be more than 105 bytes
if BLOCK_SIZE + len(self.text) + MAC_SIZE > 105:
self.text = self.text[:105 - BLOCK_SIZE - MAC_SIZE]
# Derive the cipher and MAC keys
(cipher_key, mac_key) = derive_keys(self.key)
# Generate a random IV
iv = urandom(BLOCK_SIZE)
# Encrypt the plaintext
aes = AES.new(cipher_key, self.mode, iv)
ciphertext = aes.encrypt(self.text)
# Calculate the MAC over the IV and the ciphertext
mac = hmac_sha1(mac_key, iv + ciphertext)
# Base64 encode the IV, ciphertext and MAC
return b64encode(iv + ciphertext + mac)
def decrypt(self):
"""
Decrypt text
"""
# Base64 decode
try:
iv_ciphertext_mac = b64decode(self.text)
except TypeError:
return None
# Separate the IV, ciphertext and MAC
iv = iv_ciphertext_mac[:BLOCK_SIZE]
ciphertext = iv_ciphertext_mac[BLOCK_SIZE:-MAC_SIZE]
mac = iv_ciphertext_mac[-MAC_SIZE:]
# Derive the cipher and MAC keys
(cipher_key, mac_key) = derive_keys(self.key)
# Calculate the expected MAC
expected_mac = hmac_sha1(mac_key, iv + ciphertext)
# Check the MAC
if mac != expected_mac:
return None
# Decrypt the ciphertext
aes = AES.new(cipher_key, self.mode, iv)
return aes.decrypt(ciphertext)
if __name__ == "__main__":
key = generate_key()
print 'Key:', key
# Encrypt and decrypt a short message
text = 'Hello world!'
c = Cipher(key, text)
msg = c.encrypt()
c.set_text(msg)
print '\nCiphertext:', msg
print 'Length:', len(msg)
print 'Plaintext:', c.decrypt()
# Encrypt and decrypt a long message
text = 'Gosh this is a long message, far too long to fit in a tweet I dare say,
especially when you consider the encryption overhead'
c = Cipher(key, text)
msg = c.encrypt()
c.set_text(msg)
print '\nCiphertext:', msg
print 'Length:', len(msg)
print 'Plaintext:', c.decrypt()
# Check that modifying the message invalidates the MAC
text = 'Hello world!'
c = Cipher(key, text)
msg = c.encrypt()
msg = msg[:16] + msg[17] + msg[16] + msg[18:]
c.set_text(msg)
print '\nCiphertext:', msg
print 'Length:', len(msg)
print 'Plaintext:', c.decrypt()
|
|