from nacl.secret import SecretBox
from nacl.public import PrivateKey, Box
-from nacl.utils import random
+from nacl.utils import random, EncryptedMessage
from nacl.encoding import HexEncoder
import nacl.hash
skey = self.sanitize_key(key)
box = SecretBox(skey)
cipher = box.encrypt(plain)
- box = None
+ box = skey = None
return cipher
skey = self.sanitize_key(key)
box = SecretBox(skey)
plain = box.decrypt(cipher)
- box = None
+ box = skey = None
return plain
key = key.encode('utf-8')
size = len(key)
if size < SecretBox.KEY_SIZE:
- """We must pad"""
- pad = None
- for i in range(SecretBox.KEY_SIZE - size):
- if pad is None:
- pad = b'\0'
- else:
- pad += b'\0'
- newkey = key + pad
+ """ We must pad """
+ newkey = key + bytes(SecretBox.KEY_SIZE - size)
+ elif size > SecretBox.KEY_SIZE:
+ newkey = key[:SecretBox.KEY_SIZE]
else:
newkey = key
return digest.decode()
+ def create_EncryptedMessage(self, payload):
+ nonce = payload[:SecretBox.NONCE_SIZE]
+ ciphertext = payload[SecretBox.NONCE_SIZE:]
+ return EncryptedMessage._from_parts(
+ nonce, ciphertext, nonce + ciphertext)
# You should have received a copy of the GNU General Public License
# along with SecureMail. If not, see <https://www.gnu.org/licenses/>.
+# mysql
+# create table account (
+# id int auto_increment,
+# token char(128) unique not null,
+# cipher blob not null,
+# primary key (id));
+#
+# postgresql
+# create table account (
+# id serial,
+# token char(128) unique not null,
+# cipher bytea not null,
+# primary key (id));
+
+import base64
from config import DBTYPE, DBHOST, DBPORT, DBUID, DBPWD, DBNAME
+from cryptonize import Cryptonize
class Singleton:
def __init__(self, klass):
def get_connection(self):
if self.conn is None:
if DBTYPE == 'mysql':
- import mysql.connector
- self.conn = mysql.connector.connect(host=DBHOST, port=DBPORT, user=DBUID, password=DBPWD, database=DBNAME)
+ #import MySQLdb
+ import MySQLdb
+ self.conn = MySQLdb.connect(host=DBHOST, port=DBPORT, user=DBUID, password=DBPWD, database=DBNAME)
elif DBTYPE == 'postgresql':
import psycopg2
self.conn = psycopg2.connect(host=DBHOST, port=DBPORT, user=DBUID, password=DBPWD, dbname=DBNAME)
+ else:
+ raise ValueError('{0}: Unsupported database'.format(DBTYPE))
return self.conn
def __del__(self):
def load_user(key):
conn = DB().get_connection()
cursor = conn.cursor()
- cursor.execute("select a.cipher from account a where id = '{0}'".format(key))
+ cursor.execute("select a.cipher from account a where token = '{0}'".format(key))
row = cursor.fetchone()
if row is None:
obj = None
else:
- obj = row[0].tobytes()
+ c = Cryptonize()
+ msg = base64.b64decode(row[0])
+ obj = c.create_EncryptedMessage(msg)
cursor.close()
return obj
@staticmethod
def store_user(key, cipher):
+ if DBTYPE == 'mysql':
+ from MySQLdb import Error as DBError
+ elif DBTYPE == 'postgresql':
+ from psycopg2 import Error as DBError
conn = DB().get_connection()
cursor = conn.cursor()
- cursor.execute("insert into account(id, cipher) values(%s, %s)", (key, cipher))
- conn.commit()
- cursor.close()
+ raw = base64.b64encode(cipher)
+ try:
+ cursor.execute("insert into account(token, cipher) values(%s, %s)", (key, raw))
+ conn.commit()
+ except DBError as e:
+ print (e)
+ conn.rollback()
+ raise e
+ finally:
+ cursor.close()
# You should have received a copy of the GNU General Public License
# along with SecureMail. If not, see <https://www.gnu.org/licenses/>.
-try:
- import cPickle as pickle
-except:
- import pickle
+import pickle
from db import DBInterface as DBI
from cryptonize import Cryptonize
+from nacl.public import PublicKey
-class NoSuchUserException(Exception):
+class NoSuchUser(Exception):
pass
class User:
def __init__(self, key=None):
if key is not None:
self.load(key)
+ else:
+ self.pubkeys = {}
def store(self, key):
crypto = Cryptonize()
- cipher = crypto.symmetric_encrypt(key, pickle.dumps(self.__dict__))
+ cipher = crypto.symmetric_encrypt(key, pickle.dumps(self))
DBI.store_user(crypto.generate_hash(key), cipher)
def load(self, key):
crypto = Cryptonize()
cipher = DBI.load_user(crypto.generate_hash(key))
if cipher is None:
- raise NoSuchUserException('{0}: User not found'.format(key))
+ raise NoSuchUser('{0}: User not found'.format(key))
plain = crypto.symmetric_decrypt(key, cipher)
try:
obj = pickle.loads(plain)
- self.__dict__.update(obj)
+ self.__dict__.update(obj.__dict__)
except pickle.UnpicklingError as e:
- raise NoSuchUserException(e)
-
+ raise e
+
+ def add_pubkey(self, email, key):
+ if email not in self.pubkeys:
+ self.pubkeys[email] = key.encode()
+ else:
+ raise KeyError('{0}: Exists'.format(email))
+
+ def update_pubkey(self, email, key):
+ self.pubkeys[email] = key.encode()
+
+ def delete_pubkey(self, email):
+ if email in self.pubkeys:
+ del self.pubkeys[email]
+
+ def get_pubkey(self, email):
+ if email in self.pubkeys:
+ key = self.pubkeys[email]
+ key = PublicKey(key)
+ else:
+ key = None
+
+ return key
+
@property
def name(self):
return self._name
@property
def email(self):
- return self.email
+ return self._email
@email.setter
def email(self, email):
self._email = email
+ @property
+ def pubkeys(self):
+ return self._pubkeys
+
+ @pubkeys.setter
+ def pubkeys(self, pubkeys):
+ if type(pubkeys) is not type({}):
+ raise ValueError('Not dictionary')
+ self._pubkeys = pubkeys
if __name__ == '__main__':
try:
u = User('test')
for attr, value in u.__dict__.items():
print ('{0}: {1}'.format(attr, value))
+ print ('{0} - {1} - {2}'.format(u.name, u.email, u.pubkeys))
+ key = ''
+ for i in range(40):
+ key += '{0}'.format(i)
+ u = User()
+ u.name = 'testname1'
+ u.email = 'testname1@securemail.icu'
+ u.pubkeys = {'test': 'some test', 'test1': 'some test 1'}
+ try:
+ u.store(key)
+ except:
+ u = User(key)
+ for attr, value in u.__dict__.items():
+ print ('{0}: {1}'.format(attr, value))
+ print ('{0} - {1} - {2}'.format(u.name, u.email, u.pubkeys))
+ from nacl.public import Box
c = Cryptonize()
- key = 'æselØre' #c.get_random_key()
- cipher = c.symmetric_encrypt(key, pickle.dumps(u))
- obj = pickle.loads(c.symmetric_decrypt(key, cipher))
- for attr, value in obj.__dict__.items():
- print ('{0}: {1}'.format(attr, value))
- except NoSuchUserException:
+ keypair1 = c.get_key_pair()
+ keypair2 = c.get_key_pair()
+ try:
+ u.add_pubkey('test', keypair2[1])
+ except KeyError:
+ u.update_pubkey('test', keypair2[1])
+ bob_box = Box(keypair1[0], u.get_pubkey('test'))
+ message = "Kill all humans æøåÅØÆ"
+ encrypted = bob_box.encrypt(message.encode())
+ alice_box = Box(keypair2[0], keypair1[1])
+ plaintext = alice_box.decrypt(encrypted)
+ print (plaintext.decode())
+# c = Cryptonize()
+# key = 'æselØre' #c.get_random_key()
+# cipher = c.symmetric_encrypt(key, pickle.dumps(u))
+# obj = pickle.loads(c.symmetric_decrypt(key, cipher))
+# for attr, value in obj.__dict__.items():
+# print ('{0}: {1}'.format(attr, value))
+ except NoSuchUser:
u = User()
u.name = 'testname'
u.email = 'testname@securemail.icu'