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	

===========================
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()