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
import sys
import impra.crypt as crypt
import impra.util as util
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)
to ensure privacy and exclude easy merge without the corresponding key.
An index of files stored is encrypt (rsa 1024) and regularly updated.
Once decrypt, it permit to perform search on the server and
download each part.
An index of files stored is encrypt (with the symmetric-key algorithm
Kirmah) and regularly updated. Once decrypt, it permit to perform search
on the server and download each part.
transfert process is transparent. Just vizualize locally the index of
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('-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('-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 ')
parser.add_option_group(gpConf)
@ -203,9 +204,9 @@ data command Examples:
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.gen_keys:
rsa = util.Rsa(None,None,path,True)
self.ini.set('prvKey',rsa.prvKey,o.active_profile+'.keys')
self.ini.set('pubKey',rsa.pubKey,o.active_profile+'.keys')
kg = crypt.KeyGen(256)
self.ini.set('key' ,kg.key,o.active_profile+'.keys')
self.ini.set('mark',kg.mark,o.active_profile+'.keys')
self.ini.set('salt','-¤-ImpraStorage-¤-',o.active_profile+'.keys')
if self.check_profile(o.active_profile):
self.ini.set('profile', o.active_profile)
@ -224,10 +225,9 @@ data command Examples:
if self.check_profile(o.active_profile):
conf = core.ImpraConf(self.ini,o.active_profile)
rsa = util.Rsa(conf.get('prvKey','keys'),conf.get('pubKey','keys'))
impst = None
try:
impst = core.ImpraStorage(rsa, conf)
impst = core.ImpraStorage(conf)
except util.BadKeysException as e :
print('Error : ')
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')))
remIndex = input('remove index ? (yes/no)')
if remIndex.lower()=='yes':
impst = core.ImpraStorage(rsa, conf, True)
impst = core.ImpraStorage(conf, True)
else :
print('bye')
sys.exit(1)
if o.list :
if impst.index != None:
impst.index.print(True,'-'*120+'\n -- INDEX '+impst.rootBox+'\n'+'-'*120)
impst.index.impracrypt()
impst.index.print(True,'-'*120+'\n -- INDEX(`'+conf.get('uid','index')+'`) boxname :`'+impst.rootBox+'` '+conf.get('date','index')+'\n'+'-'*120)
#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 :
impst.addFile(o.add[0],o.add[1],o.user,o.category)

View File

@ -29,7 +29,7 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~ package core ~~
from base64 import urlsafe_b64encode
from base64 import urlsafe_b64encode, b64decode
from binascii import b2a_base64, a2b_base64
from email.encoders import encode_base64
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 re import split as regsplit
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
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~ 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 ~~
@ -131,6 +91,7 @@ class FSplitter :
m = mmap(f.fileno(), 0)
p = 0
psize = ceil(getsize(fromPath)/hlst['head'][1])
print(str(psize))
while m.tell() < m.size():
self._splitPart(m,p,psize,hlst['data'][p])
p += 1
@ -144,7 +105,10 @@ class FSplitter :
""""""
rt = RuTime(eval(__CALLER__('mmap,%s,%s,phlist' % (part,size))))
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]))
rt.stop()
def deployFile(self, hlst, ext='', fake=False):
@ -187,14 +151,14 @@ class ImpraConf:
save = False
if self.ini.isEmpty():
save = True
rsa = Rsa()
kg = crypt.KeyGen(256)
self.set('host' ,'host','imap')
self.set('port' ,'993','imap')
self.set('user' ,'login','imap')
self.set('pass' ,'password','imap')
self.set('box' ,'__IMPRA','imap')
self.set('pubKey',rsa.pubKey,'keys')
self.set('prvKey',rsa.prvKey,'keys')
self.set('key' ,kg.key,'keys')
self.set('mark' ,kg.mark,'keys')
self.set('salt' ,'-¤-ImpraStorage-¤-','keys')
if not self.ini.hasSection(self.profile+self.SEP_SECTION+'catg'):
save = True
@ -244,23 +208,22 @@ class ImpraIndex:
"""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
:Parameters:
`rsa` : impra.Rsa
Rsa instance initialized with appropriate private and public
keys to decrypt/encrypt data
`key` : str
appropriate key to decrypt/encrypt data
`mark` : str
appropriate mark to check correct key
`encdata` : str
initial content of the index encrypted with rsa
"""
self.ck = ConfigKey('b-gs_bv1qyb_UFUwPWhm8xM3KJU1k2UBNfjgRBQhvkY2KYI_BF0RBTiqoqDaJlaP')
self.fspl = FSplitter(self.ck,join(rsa.dpath,'wk')+sep)
self.rsa = rsa
self.km = Kirmah(key, mark)
self.dic = {}
self.id = id
if encdata =='' : data = encdata
else : data = self.rsa.decrypt(encdata)
else : data = self.decrypt(encdata)
data = data.replace(self.QUOTE_REPL, '\'')
ld = regsplit('\n?\r? ?'+self.SEP_CATEGORY+' ?\n\r??',data)
l = regsplit(self.SEP_ITEM,ld[0])
@ -321,8 +284,10 @@ class ImpraIndex:
data += str(i)+self.SEP_TOKEN
else :
data += str(v[6]).rjust(1+ceil(len(str(v[6]))/10),' ')+' '
for i in v[:-1]:
data += str(i)+self.SEP_TOKEN
data += str(v[0])[0:42]+'... '
data += str(v[1]).ljust(30,' ')+' '
for i in v[2:-1]:
data += str(i)+' '
data = data.rstrip(self.SEP_TOKEN)+self.SEP_ITEM
if not withoutCatg :
data += self.SEP_CATEGORY+'\n'+cdata
@ -330,66 +295,22 @@ class ImpraIndex:
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)
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)
if data!='': data = self.km.decrypt(data,'.index',22)
return data
def print(self,withoutCatg=False, header=''):
"""Print index content as formated bloc"""
data = self.toString(withoutCatg,True).split(';')
print(header)
print('id'+' '*2+'hash'+' '*43+'label'+' '*26+'part'+' '*2+'type'+' '*3+'from'+' '*11+'category')
print('-'*120)
for row in data:
if row.rstrip('\n') != '': print(row)
print('-'*120)
@ -399,7 +320,7 @@ class ImpraIndex:
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'))
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'))
self.ih = ImapHelper(iconf,self.rootBox)
self.mb = MailBuilder(self.conf.get('salt','keys'))
self.rsa = rsa
self.fsplit = FSplitter(ConfigKey(),self.wkdir)
self.delids = []
if remIndex : self.removeIndex()
@ -457,14 +377,14 @@ class ImpraStorage:
self._getIdIndex()
if self.idx :
# 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)
print('cache')
else:
encData = self._getCryptIndex()
with open(self.pathInd, mode='w', encoding='utf-8') as o:
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()
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:
""""""
KEY_LEN = 64
KEY_LEN = 256
""""""
def __init__(self, key, part=0):
""""""
if len(key)!=self.KEY_LEN :
raise Exception('Invalid Pass length')
else :
#~ if len(key)!=self.KEY_LEN :
#~ raise Exception('Invalid Pass length')
#~ else :
self.key = key
self.build(part)
@ -181,10 +182,9 @@ class Noiser:
if not part < self.KEY_LEN-1 : raise Exception('part exceed limit')
else :
self.part, v = part, 0
for i in self.key[::-2] : v += i
v = int(ceil(v/4.22))
self.lns = int(ceil(v/2))-self.key[self.part]
self.lne = int(v-self.lns-self.key[self.part+2])
v = int(ceil((self.key[22]+v)/4.20583))
self.lns = int(ceil(v/2))-self.key[self.part]+self.key[7]
self.lne = int(v-self.lns-self.key[self.part+2]-self.key[44]/2.1934)
def getNoise(self, l):
""""""
@ -197,20 +197,21 @@ class Noiser:
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)
def new(self,count=None):
def new(self,count=None, chl=None):
""""""
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)
del self.lst[self.lst.index(pos)]
if single: del self.lst[self.lst.index(pos)]
return pos
@ -400,3 +401,28 @@ class Rsa:
else :
decData = str(rs[1],'utf-8')
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]