adding crypt package wich replace desurveil rsa mapping by Kirmah algorythm

This commit is contained in:
a-Sansara 2012-09-17 03:56:43 +02:00
parent 7ea35b6aa8
commit 14a068a921
4 changed files with 425 additions and 151 deletions

View File

@ -31,6 +31,7 @@
from optparse import OptionParser, OptionGroup from optparse import OptionParser, OptionGroup
import sys import sys
import impra.crypt as crypt
import impra.util as util import impra.util as util
import impra.core as core import impra.core as core
@ -40,9 +41,9 @@ Each file stored on the server is split in severals random parts.
Each part also contains random noise data (lenght depends on a crypt key) Each part also contains random noise data (lenght depends on a crypt key)
to ensure privacy and exclude easy merge without the corresponding key. to ensure privacy and exclude easy merge without the corresponding key.
An index of files stored is encrypt (rsa 1024) and regularly updated. An index of files stored is encrypt (with the symmetric-key algorithm
Once decrypt, it permit to perform search on the server and Kirmah) and regularly updated. Once decrypt, it permit to perform search
download each part. on the server and download each part.
transfert process is transparent. Just vizualize locally the index of transfert process is transparent. Just vizualize locally the index of
stored files and simply select files to download or upload. stored files and simply select files to download or upload.
@ -160,7 +161,7 @@ data command Examples:
gpConf.add_option('-P', '--set-port' , help='set imap port' , action='store', metavar='PORT ') gpConf.add_option('-P', '--set-port' , help='set imap port' , action='store', metavar='PORT ')
gpConf.add_option('-N', '--set-name' , help='set user name' , action='store', metavar='NAME ') gpConf.add_option('-N', '--set-name' , help='set user name' , action='store', metavar='NAME ')
gpConf.add_option('-B', '--set-boxn' , help='set boxName on imap server (default:[%default])' , action='store', metavar='BOXNAME ') gpConf.add_option('-B', '--set-boxn' , help='set boxName on imap server (default:[%default])' , action='store', metavar='BOXNAME ')
gpConf.add_option('-K', '--gen-keys' , help='generate new pub/private keys' , action='store_true', default=False) gpConf.add_option('-K', '--gen-keys' , help='generate new key' , action='store_true', default=False)
gpConf.add_option('-A', '--active-profile', help='set active profile' , action='store', metavar='PROFILE ') gpConf.add_option('-A', '--active-profile', help='set active profile' , action='store', metavar='PROFILE ')
parser.add_option_group(gpConf) parser.add_option_group(gpConf)
@ -203,10 +204,10 @@ data command Examples:
if o.set_port: ini.set('port', o.set_port,o.active_profile+'.imap') if o.set_port: ini.set('port', o.set_port,o.active_profile+'.imap')
if o.set_name: ini.set('name', o.set_name,o.active_profile+'.infos') if o.set_name: ini.set('name', o.set_name,o.active_profile+'.infos')
if o.gen_keys: if o.gen_keys:
rsa = util.Rsa(None,None,path,True) kg = crypt.KeyGen(256)
self.ini.set('prvKey',rsa.prvKey,o.active_profile+'.keys') self.ini.set('key' ,kg.key,o.active_profile+'.keys')
self.ini.set('pubKey',rsa.pubKey,o.active_profile+'.keys') self.ini.set('mark',kg.mark,o.active_profile+'.keys')
self.ini.set('salt' ,'-¤-ImpraStorage-¤-',o.active_profile+'.keys') self.ini.set('salt','-¤-ImpraStorage-¤-',o.active_profile+'.keys')
if self.check_profile(o.active_profile): if self.check_profile(o.active_profile):
self.ini.set('profile', o.active_profile) self.ini.set('profile', o.active_profile)
self.ini.write() self.ini.write()
@ -224,10 +225,9 @@ data command Examples:
if self.check_profile(o.active_profile): if self.check_profile(o.active_profile):
conf = core.ImpraConf(self.ini,o.active_profile) conf = core.ImpraConf(self.ini,o.active_profile)
rsa = util.Rsa(conf.get('prvKey','keys'),conf.get('pubKey','keys'))
impst = None impst = None
try: try:
impst = core.ImpraStorage(rsa, conf) impst = core.ImpraStorage(conf)
except util.BadKeysException as e : except util.BadKeysException as e :
print('Error : ') print('Error : ')
print(e) print(e)
@ -237,15 +237,27 @@ you can remove index but all presents files on the box %s will be unrecoverable
""" % (o.active_profile, conf.get('box','imap'))) """ % (o.active_profile, conf.get('box','imap')))
remIndex = input('remove index ? (yes/no)') remIndex = input('remove index ? (yes/no)')
if remIndex.lower()=='yes': if remIndex.lower()=='yes':
impst = core.ImpraStorage(rsa, conf, True) impst = core.ImpraStorage(conf, True)
else : else :
print('bye') print('bye')
sys.exit(1) sys.exit(1)
if o.list : if o.list :
if impst.index != None: if impst.index != None:
impst.index.print(True,'-'*120+'\n -- INDEX '+impst.rootBox+'\n'+'-'*120) impst.index.print(True,'-'*120+'\n -- INDEX(`'+conf.get('uid','index')+'`) boxname :`'+impst.rootBox+'` '+conf.get('date','index')+'\n'+'-'*120)
impst.index.impracrypt() #encData = impst.index.impraEncrypt(impst.index.toString())
#~ dd = """coucou mon joli coeur :*:* je s"""
#~ kg = crypt.KeyGen(256)
#~ print('-- key --')
#~ print(kg.key)
#~ print('-- mark --')
#~ print(kg.mark)
#~ km = crypt.Kirmah(kg.key, kg.mark)
#~ encData = km.encrypt(dd,'.index',22)
#~ print('*'+encData+'*')
#~ decData = km.decrypt(encData,'.index',22)
#~ print('*'+decData+'*')
elif o.add : elif o.add :
impst.addFile(o.add[0],o.add[1],o.user,o.category) impst.addFile(o.add[0],o.add[1],o.user,o.category)

View File

@ -29,7 +29,7 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~ package core ~~ # ~~ package core ~~
from base64 import urlsafe_b64encode from base64 import urlsafe_b64encode, b64decode
from binascii import b2a_base64, a2b_base64 from binascii import b2a_base64, a2b_base64
from email.encoders import encode_base64 from email.encoders import encode_base64
from email.header import Header from email.header import Header
@ -43,51 +43,11 @@ from os import remove, urandom, sep
from os.path import abspath, dirname, join, realpath, basename, getsize, splitext from os.path import abspath, dirname, join, realpath, basename, getsize, splitext
from re import split as regsplit from re import split as regsplit
from impra.imap import ImapHelper, ImapConfig from impra.imap import ImapHelper, ImapConfig
from impra.util import __CALLER__, Rsa, RuTime, Noiser, Randomiz, RuTime, hash_sha256, formatBytes, randomFrom, bstr, quote_escape, stack, run, file_exists, get_file_content, get_file_binary from impra.util import __CALLER__, RuTime, formatBytes, randomFrom, bstr, quote_escape, stack, run, file_exists, get_file_content
from impra.crypt import Kirmah, ConfigKey, Noiser, Randomiz, hash_sha256
DEBUG = True DEBUG = True
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~ class ConfigKey ~~
class ConfigKey:
""""""
def __init__(self, key=None, psize=19710000):
""""""
if key : self.key = bytes(key,'utf-8')
else : self.key = self._build()
self.psize = psize
self.salt = str(self.key[::-4])
self.noiser = Noiser(self.key)
self.rdmz = Randomiz(1)
def getHashList(self,name,count,noSorted=False):
""""""
rt = RuTime(eval(__CALLER__('"%s",%s,%i' % (name,count,noSorted))))
self.rdmz.new(count)
dic, lst, hroot = {}, [], hash_sha256(self.salt+name)
for i in range(count) :
self.noiser.build(i)
d = str(i).rjust(2,'0')
# part n°, hash, lns, lne, pos
hpart = hash_sha256(self.salt+name+'.part'+d)[:-3]+str(ord(hroot[i])).rjust(3,'0')
lst.append((d, hpart, self.noiser.lns, self.noiser.lne, self.rdmz.get()))
dic['head'] = [name,count,hroot,self.getKey()]
if not noSorted :
lst = sorted(lst, key=lambda lst: lst[4])
dic['data'] = lst
rt.stop()
return dic
def _build(self,l=48):
""""""
return urlsafe_b64encode(urandom(l))
def getKey(self):
""""""
return str(self.key,'utf-8')
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~ class FSplitter ~~ # ~~ class FSplitter ~~
@ -131,6 +91,7 @@ class FSplitter :
m = mmap(f.fileno(), 0) m = mmap(f.fileno(), 0)
p = 0 p = 0
psize = ceil(getsize(fromPath)/hlst['head'][1]) psize = ceil(getsize(fromPath)/hlst['head'][1])
print(str(psize))
while m.tell() < m.size(): while m.tell() < m.size():
self._splitPart(m,p,psize,hlst['data'][p]) self._splitPart(m,p,psize,hlst['data'][p])
p += 1 p += 1
@ -144,7 +105,10 @@ class FSplitter :
"""""" """"""
rt = RuTime(eval(__CALLER__('mmap,%s,%s,phlist' % (part,size)))) rt = RuTime(eval(__CALLER__('mmap,%s,%s,phlist' % (part,size))))
with open(self.DIR_OUTBOX+phlst[1]+'.ipr', mode='wb') as o: with open(self.DIR_OUTBOX+phlst[1]+'.ipr', mode='wb') as o:
#~ print(self.DIR_OUTBOX+phlst[1]+'.ipr')
#~ print(str(phlst[2])+' - '+str(size)+' - '+str(phlst[3])+' = '+str(phlst[2]+size+phlst[3]))
o.write(self.ck.noiser.getNoise(phlst[2])+mmap.read(size)+self.ck.noiser.getNoise(phlst[3])) o.write(self.ck.noiser.getNoise(phlst[2])+mmap.read(size)+self.ck.noiser.getNoise(phlst[3]))
rt.stop() rt.stop()
def deployFile(self, hlst, ext='', fake=False): def deployFile(self, hlst, ext='', fake=False):
@ -187,14 +151,14 @@ class ImpraConf:
save = False save = False
if self.ini.isEmpty(): if self.ini.isEmpty():
save = True save = True
rsa = Rsa() kg = crypt.KeyGen(256)
self.set('host','host','imap') self.set('host' ,'host','imap')
self.set('port','993','imap') self.set('port' ,'993','imap')
self.set('user','login','imap') self.set('user' ,'login','imap')
self.set('pass','password','imap') self.set('pass' ,'password','imap')
self.set('box' ,'__IMPRA','imap') self.set('box' ,'__IMPRA','imap')
self.set('pubKey',rsa.pubKey,'keys') self.set('key' ,kg.key,'keys')
self.set('prvKey',rsa.prvKey,'keys') self.set('mark' ,kg.mark,'keys')
self.set('salt' ,'-¤-ImpraStorage-¤-','keys') self.set('salt' ,'-¤-ImpraStorage-¤-','keys')
if not self.ini.hasSection(self.profile+self.SEP_SECTION+'catg'): if not self.ini.hasSection(self.profile+self.SEP_SECTION+'catg'):
save = True save = True
@ -244,23 +208,22 @@ class ImpraIndex:
"""Separator used for internal key such categories""" """Separator used for internal key such categories"""
def __init__(self, rsa, encdata='', dicCategory={}, id=0): def __init__(self, key, mark, encdata='', dicCategory={}, id=0):
"""Initialize the index with rsa and encoded data """Initialize the index with rsa and encoded data
:Parameters: :Parameters:
`rsa` : impra.Rsa `key` : str
Rsa instance initialized with appropriate private and public appropriate key to decrypt/encrypt data
keys to decrypt/encrypt data `mark` : str
appropriate mark to check correct key
`encdata` : str `encdata` : str
initial content of the index encrypted with rsa initial content of the index encrypted with rsa
""" """
self.ck = ConfigKey('b-gs_bv1qyb_UFUwPWhm8xM3KJU1k2UBNfjgRBQhvkY2KYI_BF0RBTiqoqDaJlaP') self.km = Kirmah(key, mark)
self.fspl = FSplitter(self.ck,join(rsa.dpath,'wk')+sep)
self.rsa = rsa
self.dic = {} self.dic = {}
self.id = id self.id = id
if encdata =='' : data = encdata if encdata =='' : data = encdata
else : data = self.rsa.decrypt(encdata) else : data = self.decrypt(encdata)
data = data.replace(self.QUOTE_REPL, '\'') data = data.replace(self.QUOTE_REPL, '\'')
ld = regsplit('\n?\r? ?'+self.SEP_CATEGORY+' ?\n\r??',data) ld = regsplit('\n?\r? ?'+self.SEP_CATEGORY+' ?\n\r??',data)
l = regsplit(self.SEP_ITEM,ld[0]) l = regsplit(self.SEP_ITEM,ld[0])
@ -321,8 +284,10 @@ class ImpraIndex:
data += str(i)+self.SEP_TOKEN data += str(i)+self.SEP_TOKEN
else : else :
data += str(v[6]).rjust(1+ceil(len(str(v[6]))/10),' ')+' ' data += str(v[6]).rjust(1+ceil(len(str(v[6]))/10),' ')+' '
for i in v[:-1]: data += str(v[0])[0:42]+'... '
data += str(i)+self.SEP_TOKEN data += str(v[1]).ljust(30,' ')+' '
for i in v[2:-1]:
data += str(i)+' '
data = data.rstrip(self.SEP_TOKEN)+self.SEP_ITEM data = data.rstrip(self.SEP_TOKEN)+self.SEP_ITEM
if not withoutCatg : if not withoutCatg :
data += self.SEP_CATEGORY+'\n'+cdata data += self.SEP_CATEGORY+'\n'+cdata
@ -330,66 +295,22 @@ class ImpraIndex:
def encrypt(self): def encrypt(self):
"""""" """"""
return self.rsa.encrypt(self.toString().replace('\'', self.QUOTE_REPL)) return self.km.encrypt(self.toString().replace('\'', self.QUOTE_REPL),'.index',22)
def impracrypt(self): def decrypt(self,data):
"""""" """"""
data = self.toString().replace('\'', self.QUOTE_REPL) if data!='': data = self.km.decrypt(data,'.index',22)
return data
with open(self.rsa.dpath+'.tmpdecd2', mode='w', encoding='utf-8') as o:
o.write(data)
hlst = self.fspl.addFile(self.rsa.dpath+'.tmpdecd2','.index',12)
print(hlst['head'])
hlst['data'] = sorted(hlst['data'], reverse=True, key=lambda lst: lst[4])
data = b''
encA = []
for row in hlst['data']:
data += get_file_binary(self.fspl.DIR_OUTBOX+row[1]+'.ipr')
encA.append(get_file_binary(self.fspl.DIR_OUTBOX+row[1]+'.ipr'))
print(row)
encData = b2a_base64(data)
with open(self.rsa.dpath+'.tmpencd2', mode='wb') as o:
o.write(encData)
print('-- enc DATA --')
#print(encData)
decData = a2b_base64(encData)
print(type(decData))
print(len(decData))
#print(str(decData))
encB = hlst['head'][1]*[None]
stpos = 0
tsize = 0
print('total size : '+str(len(decData)))
for row in hlst['data']:
thesize = row[2]+hlst['head'][4]+row[3]
print(str(row[4])+' - '+row[1]+' ('+str(thesize)+')')
print('spos = '+str(stpos))
print(stpos)
epos = stpos+row[2]+hlst['head'][4]+row[3]
print('epos = '+str(epos)+'('+str(row[2])+','+str(hlst['head'][4])+','+str(row[3])+') ['+str(thesize)+']')
print(epos)
dd = decData[stpos:epos]
stpos = epos+1
print('----------')
print(dd)
print('-----------------------------------')
tsize += thesize
with open(self.fspl.DIR_OUTBOX+row[1]+'.ipr2', mode='wb') as o:
o.write(dd)
print('total size : '+str(tsize))
print('-- decoding DATA2 --')
for row in hlst['data']:
print(row)
hlst['data'] = sorted(hlst['data'], reverse=False, key=lambda lst: lst[4])
self.fspl.deployFile(hlst, '.dec', True)
def print(self,withoutCatg=False, header=''): def print(self,withoutCatg=False, header=''):
"""Print index content as formated bloc""" """Print index content as formated bloc"""
data = self.toString(withoutCatg,True).split(';') data = self.toString(withoutCatg,True).split(';')
print(header) print(header)
print('id'+' '*2+'hash'+' '*43+'label'+' '*26+'part'+' '*2+'type'+' '*3+'from'+' '*11+'category')
print('-'*120)
for row in data: for row in data:
if row.rstrip('\n') != '': print(row) if row.rstrip('\n') != '': print(row)
print('-'*120)
@ -399,7 +320,7 @@ class ImpraIndex:
class ImpraStorage: class ImpraStorage:
"""""" """"""
def __init__(self, rsa, conf, remIndex=False, wkdir=None): def __init__(self, conf, remIndex=False, wkdir=None):
"""""" """"""
if wkdir == None : wkdir = abspath(join(dirname( __file__ ), '..', 'wk')) if wkdir == None : wkdir = abspath(join(dirname( __file__ ), '..', 'wk'))
self.wkdir = wkdir self.wkdir = wkdir
@ -409,7 +330,6 @@ class ImpraStorage:
iconf = ImapConfig(self.conf.get('host','imap'), self.conf.get('port','imap'), self.conf.get('user', 'imap'), self.conf.get('pass', 'imap')) iconf = ImapConfig(self.conf.get('host','imap'), self.conf.get('port','imap'), self.conf.get('user', 'imap'), self.conf.get('pass', 'imap'))
self.ih = ImapHelper(iconf,self.rootBox) self.ih = ImapHelper(iconf,self.rootBox)
self.mb = MailBuilder(self.conf.get('salt','keys')) self.mb = MailBuilder(self.conf.get('salt','keys'))
self.rsa = rsa
self.fsplit = FSplitter(ConfigKey(),self.wkdir) self.fsplit = FSplitter(ConfigKey(),self.wkdir)
self.delids = [] self.delids = []
if remIndex : self.removeIndex() if remIndex : self.removeIndex()
@ -457,14 +377,14 @@ class ImpraStorage:
self._getIdIndex() self._getIdIndex()
if self.idx : if self.idx :
# getFromFile # getFromFile
if int(self.idx) == int(uid) and file_exists(self.pathInd): if uid != None and int(self.idx) == int(uid) and file_exists(self.pathInd):
encData = get_file_content(self.pathInd) encData = get_file_content(self.pathInd)
print('cache') print('cache')
else: else:
encData = self._getCryptIndex() encData = self._getCryptIndex()
with open(self.pathInd, mode='w', encoding='utf-8') as o: with open(self.pathInd, mode='w', encoding='utf-8') as o:
o.write(encData) o.write(encData)
index = ImpraIndex(self.rsa, encData, {'catg':self.conf.get('types','catg')}, int(nid)) index = ImpraIndex(self.conf.get('key','keys'),self.conf.get('mark','keys'), encData, {'catg':self.conf.get('types','catg')}, int(nid))
rt.stop() rt.stop()
return index return index

316
impra/crypt.py Normal file

File diff suppressed because one or more lines are too long

View File

@ -165,14 +165,15 @@ def __CALLER__(args=''):
class Noiser: class Noiser:
"""""" """"""
KEY_LEN = 64 KEY_LEN = 256
"""""" """"""
def __init__(self, key, part=0): def __init__(self, key, part=0):
"""""" """"""
if len(key)!=self.KEY_LEN :
raise Exception('Invalid Pass length') #~ if len(key)!=self.KEY_LEN :
else : #~ raise Exception('Invalid Pass length')
#~ else :
self.key = key self.key = key
self.build(part) self.build(part)
@ -181,10 +182,9 @@ class Noiser:
if not part < self.KEY_LEN-1 : raise Exception('part exceed limit') if not part < self.KEY_LEN-1 : raise Exception('part exceed limit')
else : else :
self.part, v = part, 0 self.part, v = part, 0
for i in self.key[::-2] : v += i v = int(ceil((self.key[22]+v)/4.20583))
v = int(ceil(v/4.22)) self.lns = int(ceil(v/2))-self.key[self.part]+self.key[7]
self.lns = int(ceil(v/2))-self.key[self.part] self.lne = int(v-self.lns-self.key[self.part+2]-self.key[44]/2.1934)
self.lne = int(v-self.lns-self.key[self.part+2])
def getNoise(self, l): def getNoise(self, l):
"""""" """"""
@ -197,20 +197,21 @@ class Noiser:
class Randomiz: class Randomiz:
"""""" """"""
def __init__(self,count): def __init__(self,count,chl=None):
"""""" """"""
self.lst = list(range(0,count)) if chl ==None : self.lst = list(range(0,count))
else: self.lst = chl
self.count = len(self.lst) self.count = len(self.lst)
def new(self,count=None): def new(self,count=None, chl=None):
"""""" """"""
if count : self.count = count if count : self.count = count
self.__init__(self.count) self.__init__(self.count,chl)
def get(self): def get(self,single=True):
"""""" """"""
pos = choice(self.lst) pos = choice(self.lst)
del self.lst[self.lst.index(pos)] if single: del self.lst[self.lst.index(pos)]
return pos return pos
@ -400,3 +401,28 @@ class Rsa:
else : else :
decData = str(rs[1],'utf-8') decData = str(rs[1],'utf-8')
return decData return decData
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~ class StrIterator ~~
class StrIterator:
MAX_ITER = 1000
def __init__(self,data):
self.l = len(data)
self.p = ceil(self.l/self.MAX_ITER)
self.d = []
for x in range(self.p):
self.d.append(data[x*self.MAX_ITER:x*self.MAX_ITER+self.MAX_ITER])
def __iter__(self):
self.i = 0
return self
def __next__(self):
if self.i > len(self.d)-1 :
raise StopIteration
self.i += 1
return self.d[self.i-1]