- Posts:
- 1,874
- Group:
- Members
- Member
- #3,310
- Joined:
- December 12, 2009
|
- Code:
-
#[space]LOTUS,[space]a[space]block[space]cipher[space]with[space]authentication[space](integrity[space]check)[space]based[space]on[space]the[space]use #[space]of[space]permutation[space]polynomials[space]mod[space]2**n
#[space]Prologue.[space][space][space]
#[space]LOTUS[space]is[space]a[space]block[space]encryption[space]scheme[space]employing[space]as[space]its[space]major[space]constituent[space]a #[space]substitution[space]based[space]on[space]permutation[space]polynomials[space]mod[space]2**n.[space](By[space]definition[space]such #[space]polynomials[space]preform[space]bijective[space]mappings[space]for[space][0,[space]2**n-1].)[space]The[space]present[space]author #[space]has[space]earlier[space]posted[space]the[space]source[space]codes[space]of[space]two[space]software,[space]JADE[space]and[space]JADE-S,[space]that #[space]also[space]exploit[space]the[space]substitution[space]properties[space]of[space]such[space]permutation[space]polynomials. #[space]However,[space]in[space]these[space]software[space]an[space]essential[space]part[space]of[space]the[space]codes[space]is[space]destined[space]to[space]the #[space]construction[space]of[space]a[space]compound[space]PRNG[space]consisting[space]of[space]a[space]number[space]of[space]constituent[space]PRNGs #[space]built[space]also[space]with[space]permutation[space]polynomials,[space]which[space]renders[space]the[space]whole[space]software #[space]design[space]rather[space]complicated.[space]LOTUS[space]however[space]is[space]designed[space]with[space]the[space]realization[space]that #[space]it[space]is[space]in[space]fact[space]convenient[space]and[space]profitable[space]to[space]use[space]instead[space]Python's[space]built-in[space]PRNG, #[space]which[space]has[space]very[space]good[space]statistical[space]properties[space]and[space]whose[space]use[space]for[space]the[space]current #[space]crypto[space]processing[space]purposes[space]is[space]deemed[space]justifiable[space]even[space]though[space]the[space]PRNG[space]is[space]a #[space]publically[space]accessible[space]one,[space]since[space]its[space]outputs[space]are[space]only[space]involved[space]in[space]the[space]internal #[space]computational[space]operations[space]underlying[space]the[space]encryption[space]scheme[space](i.e.[space]unlike #[space]situations[space]in[space]stream[space]encryption[space]where[space]the[space]plaintext[space]is[space]xor-ed[space]with[space]PRNs[space]to #[space]directly[space]yield[space]the[space]ciphertext)[space]so[space]that[space]the[space]analyst[space]is[space]barely[space]feasible[space]to[space]gain #[space]and[space]hence[space]exploit[space]any[space]knowledge[space]of[space]the[space]direct[space]outputs[space]from[space]Python's[space]PRNG #[space](which[space]is[space]seeded[space]by[space]user's[space]secret[space]key).[space]See[space]lotusencrypt()[space]further[space]below, #[space]where[space]most[space]PRNs[space]are[space]used[space]not[space]only[space]at[space]locations[space]far[space]from[space]the[space]location[space]of[space]the #[space]final[space]output[space]of[space]the[space]ciphertext[space]from[space]the[space]function[space]but[space]are[space]also[space]employed[space]in #[space]operations[space]much[space]more[space]complex[space]than[space]straightforward[space]bit[space]xor-ing,[space]e.g.[space]serving[space]as[space]the #[space]coefficients[space]of[space]the[space]permutation[space]polynomials[space]for[space]computing[space]the[space]entities[space]being #[space]transformed[space]by[space]them.[space](Note[space]that[space]each[space]such[space]entity[space]is[space]transformed[space]by[space]a[space]different #[space]set[space]of[space]PR[space]coefficients[space]of[space]a[space]polynomial[space]--[space]involving[space]not[space]merely[space]1[space]PRN[space]as[space]in[space]the #[space]case[space]of[space]stream[space]encryption[space]with[space]simple[space]bit[space]xor-ing[space]but[space]3[space]PRNs[space]for[space]the[space]3 #[space]coefficients[space]in[space]the[space]illustrative[space]example[space]further[space]below[space]--[space]forming[space]thus[space]a #[space]separate[space]specific[space]permutation[space]polynomial[space]to[space]process[space]it.)
#[space]For[space]processing[space]each[space]block[space]of[space]plaintext,[space]PRNs[space]are[space]generated[space]to[space]build[space]a[space]specific #[space]permutation[space]polynomial[space]to[space]serve[space]the[space]purpose[space]of[space]substitution.[space]Block[space]chaining #[space]is[space]used[space]with[space]a[space]chaining[space]value[space](designated[space]sigma)[space]that[space]is[space]in[space]a[space]sense[space]a #[space]summation[space]of[space]plaintext[space]and[space]ciphertext[space]of[space]all[space]preceding[space]blocks[space](noting[space]though #[space]that[space]it[space]is[space]not[space]the[space]externally[space]accessible[space]final[space]ciphertext[space]but[space]instead[space]an #[space]internal[space]value[space]that[space]is[space]involved[space]in[space]the[space]computation[space]of[space]sigma).[space][space]There[space]is[space]an #[space]xor-ing[space]with[space]a[space]PRN[space]and[space]two[space]transpositions[space]of[space]the[space]bytes[space]of[space]the[space]block. #[space]Authentication[space]is[space]done[space]through[space]appending[space]a[space]number[space]of[space]blocks[space]of[space]PRNs[space]to[space]the #[space]user-given[space]plaintext.[space]For[space]details,[space]including[space]rotation[space]of[space]bits[space](to[space]achieve #[space]better[space]avalanche)[space]and[space]skipping[space]of[space]outputs[space]from[space]the[space]PRNG[space]employed[space](to[space]achieve #[space]dynamics/variability[space]in[space]the[space]processing),[space]see[space]the[space]very[space]richly[space]annotated #[space]function[space]lotusencrypt()[space]further[space]below.
#[space]This[space]software[space]is[space]very[space]fast[space]in[space]practice[space]for[space]encryption[space]of[space]moderate-sized #[space]materials[space]that[space]are[space]common[space]for[space]the[space]communications[space]of[space]our[space]targeted[space]users,[space]the #[space]common[space]people.[space]For[space]a[space]message[space]of[space]1000[space]characters[space]a[space]CPU[space]time[space]of[space]0.09[space]sec[space]was #[space]measured[space]on[space]a[space]common[space]PC[space]with[space]the[space]system[space]parameters[space]identical[space]to[space]those[space]used #[space]in[space]the[space]illustrative[space]example[space]further[space]below.
#[space]Users[space]who[space]desire[space]to[space]employ[space]several[space]alternative[space]algorithms[space](including[space]for #[space]multiple[space]encryptions)[space]may[space]also[space]consider[space]the[space]following[space]software[space]of[space]the[space]author: #[space]NEOCLASSIC,[space]http://s13.zetaboards.com/Crypto/topic/7115671/1/ #[space]PREFIXCODING,[space]http://s13.zetaboards.com/Crypto/topic/7164646/1/
#[space]Version[space]1.1,[space]released[space]on[space]14.03.2014.
#[space]Update[space]notes:
#[space]Version[space]1.0:[space]Released[space]on[space]07.03.2014.
#[space]Version[space]1.0.1:[space]11.03.2014:[space]In[space]lotusinit()[space]the[space]in[space]Version[space]1.0[space]implemented, #[space]arbitrarily[space]defined,[space]choicebit[space]didn't[space]correspond[space]to[space]its[space]verbal[space]description. #[space]This[space]formal[space]inconsistency,[space]though[space]without[space]security[space]significance,[space]is[space]corrected.
#[space]Version[space]1.1.:[space]14.03.2014:[space]The[space]algorithm[space]in[space]ncombine()[space]is[space]replaced[space]by[space]a[space]better #[space]one[space]in[space]respect[space]of[space]avalanche.
#[space]Code[space]lines[space]of[space]documents[space]with[space]the[space]same[space]version[space]number[space]are[space]always[space]identical. #[space]There[space]may[space]be[space]interim[space]modifications[space]of[space]comment[space]lines.[space]The[space]most[space]recent[space]document #[space]of[space]LOTUS[space]can[space]be[space]obtained[space]from: #[space]http://s13.zetaboards.com/Crypto/topic/7166985/1/
#[space]This[space]software[space]may[space]be[space]freely[space]used:
#[space]1.[space]for[space]all[space]personal[space]purposes[space]unconditionally[space]and
#[space]2.[space]for[space]all[space]other[space]purposes[space]under[space]the[space]condition[space]that[space]its[space]name,[space]version[space]number[space] #[space][space][space][space]and[space]authorship[space]are[space]explicitly[space]mentioned[space]and[space]that[space]the[space]author[space]is[space]informed[space]of #[space][space][space][space]all[space]eventual[space]code[space]modifications[space]done.
#[space]The[space]author[space]is[space]indebted[space]to[space]TPS[space]for[space]review[space]and[space]suggestions[space]throughout[space]LOTUS's #[space]development[space]phase.[space]Any[space]remaining[space]deficiencies[space]of[space]the[space]software[space]are[space]however[space]the #[space]sole[space]responsibilty[space]of[space]the[space]author.
#[space]Constructive[space]critiques[space]and[space]comments[space]are[space]sincerely[space]solicited.[space]
#[space]Email[space]address[space]of[space]the[space]author:[space]mok-kong.shen@t-online.de
################################################################################
import[space]random
#[space]The[space]following[space]3[space]function[space]fullperiodcriteria(),[space]evalpermpoly(),[space]invpermpoly() #[space]are[space]general[space]functions[space]required[space]for[space]computating[space]with[space]permutation[space]polynomials #[space]mod[space]2**n.[space]They[space]were[space]posted[space]earlier[space]by[space]the[space]author[space]in[space]e.g.[space]JADE-S #[space]http://s13.zetaboards.com/Crypto/topic/7072208/1/.[space](Note[space]that[space]some[space]of[space]the #[space]global[space]variables[space]declared[space]in[space]them[space]are[space]no[space]longer[space]used[space]in[space]LOTUS.)
#[space]Modify[space]user-supplied[space]coefficients[space]of[space]the[space]polynomial[space]poly[space]so[space]as[space]to[space]satisfy[space]the #[space]full-period[space]criteria[space]of[space]a[space]permutation[space]polynomial[space]mod[space]2**n.[space]The[space]degree[space]of[space]poly #[space]is[space]required[space]to[space]be[space]at[space]least[space]2.[space]m[space]denotes[space]the[space]number[space]of[space]coefficients[space]of[space]the #[space]polynomial,[space]i.e.[space]degree[space]of[space]polynomial[space]plus[space]1.[space]For[space]the[space]criteria[space]see[space]ref.[1], #[space]p.283. #[space][1][space]V.[space]Anashin,[space]A.[space]Khrennikov,[space]Applied[space]Algebraic[space]Dynamics,[space]Berlin,[space]2009. #[space][space][space][space][space]http://www.degruyter.com/view/supplement/9783110203011_Errata.pdf #[space]We[space]use[space]for[space]simplification[space]of[space]coding[space]a[space]restricted[space]form[space]of[space]the[space]criteria,[space]namely: #[space][space][space][space]c_0[space]=[space]c_1[space]=[space]1[space][space]mod[space]4 #[space][space][space][space]c_i[space]=[space]0[space][space]mod[space]4[space][space][space][space]for[space]all[space]other[space]i
def[space]fullperiodcriteria(poly,m): [space][space]global[space]logn,n,np1,nm1,nh,chnum [space][space]global[space]tpwn,tpwnm1,shfnrot,tpwnh,tpwnhm1,shfnhrot [space][space]if[space]m<3: [space][space][space][space]print("Error[space]in[space]fullperiodcriteria") [space][space][space][space]exit(1) [space][space]gg=(tpwnm1<<2)&tpwnm1 [space][space]permpoly=poly[:] [space][space]for[space]i[space]in[space]range(2): [space][space][space][space]permpoly[i]=(permpoly[i]&gg)|1 [space][space]for[space]i[space]in[space]range(2,m): [space][space][space][space]permpoly[i]&=gg [space][space]return(permpoly)
#[space]Evaluate[space]permpoly[space]with[space]argument[space]x[space]with[space]Horner's[space]method.
def[space]evalpermpoly(permpoly,m,x): [space][space]global[space]logn,n,np1,nm1,nh,chnum [space][space]global[space]tpwn,tpwnm1,shfnrot,tpwnh,tpwnhm1,shfnhrot [space][space]y=permpoly[m-1] [space][space]for[space]i[space]in[space]range(m-2,-1,-1): [space][space][space][space]y=(y*x+permpoly[i])&tpwnm1 [space][space]return(y)
#[space]Inverse[space]of[space]evalpermpoly().[space]First[space]derivative[space]of[space]permpoly(x)[space]=[space]1[space]mod[space]2.[space]Hensel's #[space]lifting[space]lemma[space]leads[space]to[space]the[space]iteration:[space]x_(i+1)=x_i-g(x_i)[space]mod[space]2**(i+1),[space]with #[space]g(x)=permpoly(x)-y.[space]See[space]ref.[1],[space]p.306.[space]
def[space]invpermpoly(permpoly,m,y): [space][space]global[space]logn,n,np1,nm1,nh,chnum [space][space]global[space]tpwn,tpwnm1,shfnrot,tpwnh,tpwnhm1,shfnhrot [space][space]if[space](((permpoly[0]-y)&tpwnm1)&1)==0: [space][space][space][space]x=0 [space][space]else: [space][space][space][space]x=1 [space][space]for[space]i[space]in[space]range(2,np1,1): [space][space][space][space]x=(x-(evalpermpoly(permpoly,m,x)-y))&tpwnm1 [space][space]return(x)
#[space]The[space]following[space]3[space]functions[space]initbitcount()[space]bm()[space]and[space]bitcount()[space]are[space]for[space]fast #[space]counting[space]of[space]1-bits[space]of[space]variables[space]of[space]n[space]bits[space](n[space]=[space]2**logn).[space]They[space]were[space]earlier #[space]posted[space]by[space]the[space]author[space]in[space]http://s13.zetaboards.com/Crypto/topic/7129099/1.
def[space]initbitcount(): [space][space]global[space]logn,byten,tpwi,mk [space][space]assert(logn>=4) [space][space]byten=2**logn//8 [space][space]tpwi=[2**i[space]for[space]i[space]in[space]range(logn)] [space][space]b55=0x55 [space][space]b33=0x33 [space][space]b00=0x00 [space][space]b0f=0x0f [space][space]bff=0xff [space][space]mk=[] [space][space]mk.append(bm(1,b55,b55)) [space][space]mk.append(bm(1,b33,b33)) [space][space]mk.append(bm(1,b0f,b0f)) [space][space]for[space]i[space]in[space]range(logn-3): [space][space][space][space]mk.append(bm(tpwi[i],b00,bff)) [space][space]return
def[space]bm(nb,b1,b2): [space][space]global[space]logn,byten,tpwi,mk [space][space]u=0 [space][space]for[space]i[space]in[space]range(nb): [space][space][space][space]u<<=8 [space][space][space][space]u|=b1 [space][space]for[space]i[space]in[space]range(nb): [space][space][space][space]u<<=8 [space][space][space][space]u|=b2 [space][space]c=byten//(2*nb) [space][space]h=2*nb*8 [space][space]v=0 [space][space]for[space]i[space]in[space]range(c): [space][space][space][space]v<<=h [space][space][space][space]v|=u [space][space]return(v)
#[space]Delivers[space]number[space]of[space]1-bits[space]of[space]a[space]n-bit[space]variable[space]x[space](n=2**logn). #[space]logn[space](>=[space]4)[space]is[space]to[space]be[space]defined[space]and[space]initbitcount()[space]invoked[space]before[space]first[space]use #[space]of[space]bitcount().
def[space]bitcount(x): [space][space]global[space]logn,byten,tpwi,mk [space][space]for[space]i[space]in[space]range(logn): [space][space][space][space]x=(x&mk[i])+((x>>tpwi[i])&mk[i]) [space][space]return(x)
#[space]Convert[space]a[space]byte[space]sequence[space]to[space]an[space]integer.
def[space]pack(byarray): [space][space]k=0 [space][space]for[space]i[space]in[space]range(len(byarray)): [space][space][space][space]k<<=8 [space][space][space][space]k|=byarray[i] [space][space]return(k)
#[space]Convert[space]an[space]integer[space]to[space]a[space]nbytes[space]byte[space]sequence.
def[space]unpack(k,nbytes): [space][space]list=[0[space]for[space]i[space]in[space]range(nbytes)] [space][space]for[space]i[space]in[space]range(nbytes-1,-1,-1): [space][space][space][space]list[i]=k&0xff [space][space][space][space]k>>=8 [space][space]return(bytearray(list))[space][space]
#[space]Initialization[space]of[space]LOTUS[space]for[space]the[space]following[space]currently[space]valid[space]global[space]system #[space]parameters[space](for[space]their[space]meaning,[space]see[space]the[space]illustrative[space]example[space]further[space]below): #[space]secretkey #[space]sessionkeyextension #[space]logn #[space]fillerchar #[space]natuhenblock #[space]polynomm #[space]skipbits
def[space]initlotus(): [space][space]global[space]secretkey,[space]sessionkeyextension [space][space]global[space]logn,blockbits,blockbytes,fillerchar,fillerbyte [space][space]global[space]nauthenblock,polynomm [space][space]global[space]blockmask,skipbits,skipmask,prrotmasklen,prrotmask,choicebit [space][space]global[space]n,np1,tpwn,tpwnm1 [space][space]global[space]tpwnd4,mk0,mk1,mk2,mk3,sf0,sf1,sf2,sf3 #[space]Enforcing[space]some[space]plausibility[space]constraints: [space][space]assert(7[space]<=[space]logn[space]<=[space]9[space]and[space]1[space]<=[space]nauthenblock[space]<=[space]3[space]and[space]3[space]<=[space]polynomm[space]<=[space]5\ [space][space][space][space][space][space][space][space][space]and[space]1[space]<=[space]skipbits[space]<=[space]2) #[space]np1[space]and[space]tpwnm1[space]are[space]needed[space]by[space]the[space]functions[space]for[space]permutation[space]polynomials. [space][space]n=2**logn [space][space]np1=n+1 [space][space]tpwn=2**n [space][space]tpwnm1=tpwn-1 [space][space]k=n//4 #[space]The[space]following[space]are[space]needed[space]by[space]ncombine() [space][space]tpwnd4=2**k [space][space]mk3=2**k-1 [space][space]mk2=mk3<<k [space][space]mk1=mk2<<k [space][space]mk0=mk1<<k [space][space]sf3=0 [space][space]sf2=k [space][space]sf1=2*k [space][space]sf0=3*k #[space]The[space]following[space]are[space]needed[space]by[space]prepareplaintextstr(),[space]lotusencrypt()[space]and #[space]lotusdecrypt(). [space][space]blockbits=n [space][space]blockbytes=blockbits//8 [space][space]blockmask=tpwnm1 [space][space]fillerbyte=bytearray(fillerchar,"latin-1")[space] #[space]Mask[space]to[space]determine[space]prrot. [space][space]prrotmask=blockbits-1 #[space]Length[space]of[space]prrotmask. [space][space]prrotmasklen=logn #[space]Mask[space]to[space]determine[space]skip. [space][space]skipmask=2**skipbits-1 #[space]choicebit[space]is[space]used[space]for[space]a[space]0/1[space]choice,[space]it[space]is[space]arbitrarily[space]chosen[space]to[space]be[space]one[space]in[space]the #[space]middle[space]of[space]the[space]block. [space][space]choicebit=2**(n//2) #[space]Initialization[space]for[space]the[space]bit[space]counting[space]functions. [space][space]initbitcount() #[space]Seed[space]Python's[space]built-in[space]PRNG.[space]Both[space]secretkey[space]and[space]sessionkeyextension[space]are #[space]treated[space]as[space]strings.[space] [space][space]random.seed(str(secretkey)+str(sessionkeyextension)) [space][space]return
#[space]Combining[space]two[space]n-bit[space]words[space]x[space]and[space]y[space](optimally[space]in[space]the[space]sense[space]of[space]avalanche). #[space]See[space]http://s13.zetaboards.com/Crypto/topic/7169100/1/
def[space]ncombine(x,y): [space][space]global[space]n,np1,tpwn,tpwnm1 [space][space]global[space]tpwnd4,mk0,mk1,mk2,mk3,sf0,sf1,sf2,sf3 [space][space]g=(2*x*y+x+y)%tpwn [space][space]g0=(g&mk0)>>sf0 [space][space]g1=(g&mk1)>>sf1 [space][space]g2=(g&mk2)>>sf2 [space][space]g3=(g&mk3) [space][space]s=g0+g1+g2+g3 [space][space]z0=(2*g0+s)%tpwn [space][space]z1=(2*g1+s)%tpwn [space][space]z2=(2*g2+s)%tpwn [space][space]z3=(2*g3+s)%tpwn [space][space]z=(z0<<sf0)|(z1<<sf1)|(z2<<sf2)|z3 [space][space]return(z)
#[space]Read[space]a[space]byte[space]sequence[space]from[space]a[space]binary[space]file.
def[space]readbinaryfile(binaryfilename): [space][space]fp=open(binaryfilename+".bin","rb") [space][space]byarray=bytearray(fp.read()) [space][space]fp.close() [space][space]return(byarray)
#[space]Write[space]a[space]byte[space]sequence[space]to[space]a[space]binary[space]file.
def[space]writebinaryfile(byarray,binaryfilename): [space][space]fp=open(binaryfilename+".bin","wb") [space][space]fp.write(byarray) [space][space]fp.close()
#[space]It[space]is[space]assumed[space]that[space]initialization[space]with[space]lotusinit()[space]has[space]been[space]done.[space]If[space]the #[space]user-given[space]plaintext[space]is[space]in[space]the[space]form[space]of[space]a[space]string,[space]this[space]function[space]transforms[space]it #[space]to[space]a[space]binary[space]file[space]of[space]the[space]format[space]needed[space]by[space]lotusencrypt()[space]for[space]encryption #[space]processing.[space]It[space]is[space]assumed[space]that[space]the[space]characters[space]of[space]plaintextstr[space]are[space]in[space]latin-1. #[space](In[space]case[space]the[space]user-given[space]material[space]is[space]binary[space](as[space]a[space]sequence[space]of[space]bytes[space]in[space]a[space]file), #[space]this[space]function[space]is[space]of[space]course[space]not[space]used[space]and[space]one[space]proceeds[space]directly[space]with #[space]lotusencrypt().)
def[space]prepareplaintextstr(plaintextstr,plaintextfilename): [space][space]global[space]logn,blockbits,blockbytes,fillerchar,fillerbyte #[space]Transform[space]the[space]plaintextstr[space]to[space]a[space]sequence[space]of[space]bytes. [space][space]byarray=bytearray(plaintextstr,"latin-1")[space] [space][space]numbytes=len(byarray) [space][space]r=numbytes%blockbytes #[space]Fill[space]to[space]whole[space]block[space]boundary[space]with[space]the[space]filler[space]character. [space][space]if[space]r!=0: [space][space][space][space]byarray+=(blockbytes-r)*fillerbyte [space][space][space][space]print(blockbytes-r,"bytes[space]of","'"+fillerchar+"'", [space][space][space][space][space][space][space][space][space][space]"are[space]appended[space]as[space]filler[space]to[space]the[space]given[space]plaintextstr") #[space]Write[space]the[space]result[space]to[space]a[space]binary[space]file. [space][space]writebinaryfile(byarray,plaintextfilename) [space][space]print("Plaintext[space]written[space]to[space]file[space]with[space]name:",plaintextfilename, [space][space][space][space][space][space][space][space]"(extension[space].bin)") [space][space]return
[space] #[space]This[space]function[space]serves[space]to[space]transform[space]the[space]binary[space]file[space]delivered[space]by[space]lotusdecrypt() #[space]to[space]a[space]text[space]string.[space]It[space]is[space]assumed[space]that[space]the[space]bytes[space]in[space]the[space]binaryfile[space]are[space]in #[space]latin-1[space]so[space]that[space]textstr[space]returned[space]can[space]be[space]printed.
def[space]gettextstrfrombinaryfile(binaryfilename): [space][space]fp=open(binaryfilename+".bin","rb") [space][space]byarray=fp.read() [space][space]fp.close() [space][space]leng=len(byarray) [space][space]textstr="" [space][space]for[space]i[space]in[space]range(leng): [space][space][space][space]textstr+=chr(byarray[i]) [space][space]print(leng,"bytes[space]read[space]from[space]file[space]with[space]name:",binaryfilename, [space][space][space][space][space][space][space][space]"(extension[space].bin)[space]and") [space][space]print("transformed[space]to[space]textstr") [space][space]return(textstr)
#[space]It[space]is[space]assumed[space]that[space]initialization[space]with[space]lotusinit()[space]has[space]been[space]done.[space]The #[space]plaintext[space]file[space](binary,[space]a[space]sequence[space]of[space]bytes[space]whose[space]length[space]must[space]be[space]a[space]multiple[space]of #[space]blockbytes)[space]is[space]processed[space]to[space]result[space]in[space]the[space]ciphertext[space]file.[space]For[space]meaning[space]of #[space]some[space]of[space]the[space]global[space]variables,[space]see[space]also[space]lotusinit()[space]and[space]the[space]illustrative #[space]example[space]further[space]below.
def[space]lotusencrypt(plaintextfilename,ciphertextfilename): [space][space]global[space]logn,blockbits,blockbytes,fillerchar,fillerbyte [space][space]global[space]nauthenblock,polynomm [space][space]global[space]blockmask,skipbits,skipmask,prrotmasklen,prrotmask,choicebit #[space]Initialize[space]sigma,[space]the[space]block[space]chaining[space]value,[space]with[space]a[space]PRN. [space][space]sigma=random.getrandbits(blockbits) #[space]Read[space]in[space]the[space]plaintext[space](or[space]in[space]multiple[space]encryption[space]the[space]intermediate[space]input)[space]file. [space][space]byarray=readbinaryfile(plaintextfilename) [space][space]numbytes=len(byarray) [space][space]assert(numbytes%blockbytes==0) [space][space]print(numbytes,"of[space]plaintext[space]read[space]from[space]file[space]with[space]name:",plaintextfilename, [space][space][space][space][space][space][space][space]"(extension[space].bin)") #[space]Generate[space]nauthenblock[space]blocks[space]of[space]random[space]bytes[space]for[space]the[space]purpose[space]of #[space]authentication. [space][space]authenblockslen=nauthenblock*blockbytes [space][space]authenblocks=bytearray([random.getrandbits(8)[space]\ [space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space]for[space]i[space]in[space]range(authenblockslen)]) [space][space]byarray+=authenblocks [space][space]numbytes=len(byarray) [space][space]numblocks=numbytes//blockbytes #[space]Generate[space]index[space]sequences[space]for[space]performing[space]transpositions. [space][space]permseq1=[i[space]for[space]i[space]in[space]range(numbytes)] [space][space]permseq2=permseq1[:] [space][space]random.shuffle(permseq1) [space][space]random.shuffle(permseq2) #[space]Transpose[space]byarray[space]according[space]to[space]permseq1. [space][space]list1=[byarray[permseq1[i]][space]for[space]i[space]in[space]range(numbytes)] [space][space]byarray=bytearray(list1) [space][space]cipherbyarray=bytearray("","latin-1") [space][space]k=0 [space][space]for[space]blk[space]in[space]range(numblocks): [space][space][space][space]t=sigma #[space]Obtain[space]prrot[space]to[space]be[space]used[space]further[space]below. [space][space][space][space]prrot=t&prrotmask #[space]Skip[space]nskip[space]PRNs[space]output[space]by[space]the[space]PRNG[space]to[space]render[space]the[space]process[space]dynamic/variable[space]and #[space]hence[space]hard[space]to[space]analyse. [space][space][space][space]t>>=prrotmasklen [space][space][space][space]nskip=t&skipmask [space][space][space][space]for[space]i[space]in[space]range(nskip): [space][space][space][space][space][space]random.getrandbits(blockbits) #[space]Obtain[space]prn,[space]a[space]PRN,[space]to[space]be[space]used[space]further[space]below. [space][space][space][space]prn=random.getrandbits(blockbits) #[space]Generate[space]PRNs[space]for[space]the[space]coefficients[space]of[space]a[space]permutation[space]polynomial. [space][space][space][space]permpoly=[random.getrandbits(blockbits)[space]for[space]i[space]in[space]range(polynomm)] #[space]Modify[space]permpoly[space]to[space]satisfy[space]the[space]fullperiod[space]criteria. [space][space][space][space]permpoly=fullperiodcriteria(permpoly,polynomm) #[space]Obtain[space]an[space]integer[space]from[space]the[space]bytes[space]of[space]the[space]block. [space][space][space][space]k1=k+blockbytes [space][space][space][space]plainint=pack(byarray[k:k1]) [space][space][space][space]k=k1 #[space]xor[space]plainint[space]with[space]prn[space]and[space]the[space]chaining[space]value[space]sigma. [space][space][space][space]blockint1=plainint^prn^sigma #[space]Dynamic[space]choice[space]of[space]using[space]either[space]evalpermpoly()[space]or[space]invpermpoly()[space]to[space]do[space]the #[space]substitution.[space]This[space]means[space]a[space]complexity[space]for[space]analysis[space]and[space]also[space]has[space]the #[space]beneficial[space]effect[space]of[space]rendering[space]lotusencrypt()[space]and[space]lotusdecrypt()[space]running[space]at #[space]roughly[space]the[space]same[space]speed,[space]since[space]invpermpoly()[space]runs[space]longer[space]than[space]evalpermpoly(). [space][space][space][space]choice=(sigma&choicebit)==0 [space][space][space][space]if[space]choice:[space][space][space][space][space][space] [space][space][space][space][space][space]blockint2=evalpermpoly(permpoly,polynomm,blockint1) [space][space][space][space]else: [space][space][space][space][space][space]blockint2=invpermpoly(permpoly,polynomm,blockint1) #[space]Do[space]a[space]rotation[space]of[space]the[space]bits.[space]The[space]amount[space]of[space]rotation[space]has[space]2[space]components,[space]the[space]one, #[space]bitcount(),[space]serves[space]to[space]achieve[space]better[space]avalanche,[space]see #[space]http://s13.zetaboards.com/Crypto/topic/7131993/1/,[space]the[space]other,[space]prrot,[space]is #[space]pseudo-random[space](being[space]from[space]sigma,[space]which[space]is[space]dynamic[space](processing[space]dependent)), #[space]which[space]hinders[space]attempts[space]to[space]reverse[space]the[space]rotation[space]without[space]knowledge[space]of[space]that #[space]value. [space][space][space][space]rot=(bitcount(blockint2)+prrot)%blockbits [space][space][space][space]cipherint=((blockint2<<rot)&blockmask)|(blockint2>>(blockbits-rot)) #[space]Update[space]sigma[space]for[space]chaining[space]of[space]the[space]following[space]block.[space]Note[space]that,[space]in[space]distinction #[space]to[space]CBC,[space]sigma[space]is[space]dependent[space]on[space]both[space]plaintext[space]and[space]ciphertext[space]of[space]all[space]preceding #[space]blocks,[space]which[space]is[space]deemed[space]desirable[space]for[space]our[space]purposes.[space]We[space]choose[space]to[space]combine #[space]plainint[space]and[space]cipherint[space]with[space]the[space]function[space]ncombine()[space]and[space]xor[space]the[space]result[space]to #[space]the[space]current[space]sigma.[space](+[space]is[space]used[space]in[space]ncombine(),[space]hence[space]xor[space]here[space]to[space]result[space]in[space]a #[space]diversity[space]of[space]operators[space]facing[space]the[space]analyst.)[space]Note[space]that[space]cipherint[space]is[space]further #[space]processed[space]with[space]a[space]transposition[space]before[space]becoming[space]cipherarray[space]to[space]be[space]output[space]by[space]the #[space]function,[space]hence[space]it[space]is[space]not[space]an[space]externally[space]accessible[space]value. [space][space][space][space]sigma=(sigma^ncombine(plainint,cipherint))&blockmask #[space]Transform[space]cipherint[space]to[space]a[space]sequence[space]of[space]bytes[space]and[space]accumulate[space]that[space]in #[space]cipherbyarray. [space][space][space][space]cipherbyarray+=unpack(cipherint,blockbytes) #[space]Transpose[space]cipherarray[space]according[space]to[space]permseq2. [space][space]list2=[cipherbyarray[permseq2[i]][space]for[space]i[space]in[space]range(numbytes)] [space][space]cipherbyarray=bytearray(list2) #[space]Write[space]the[space](final)[space]ciphertext[space]in[space]cipherbyarray[space]to[space]a[space]binary[space]file. [space][space]writebinaryfile(cipherbyarray,ciphertextfilename) [space][space]print("Ciphertext[space]written[space]to[space]file[space]with[space]name:",ciphertextfilename, [space][space][space][space][space][space][space][space]"(extension[space].bin)") [space][space]return()
#[space]The[space]reverse[space]of[space]lotusencrypt().[space]It[space]is[space]assumed[space]that[space]initialization[space]with #[space]lotusinit()[space]has[space]been[space]done.
def[space]lotusdecrypt(ciphertextfilename,decryptedtextfilename): [space][space]global[space]logn,blockbits,blockbytes,fillerchar,fillerbyte [space][space]global[space]nauthenblock,polynomm [space][space]global[space]blockmask,skipbits,skipmask,prrotmasklen,prrotmask,choicebit [space][space]sigma=random.getrandbits(blockbits) [space][space]authenblockslen=nauthenblock*blockbytes [space][space]authenblocks=bytearray([random.getrandbits(8)[space]\ [space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space][space]for[space]i[space]in[space]range(authenblockslen)]) [space][space]cipherbyarray=readbinaryfile(ciphertextfilename) [space][space]print("Ciphertext[space]read[space]from[space]file[space]with[space]name:",ciphertextfilename, [space][space][space][space][space][space][space][space]"(extension[space].bin)")[space][space] [space][space]numbytes=len(cipherbyarray) [space][space]assert(numbytes%blockbytes==0) [space][space]numblocks=numbytes//blockbytes [space][space]permseq1=[i[space]for[space]i[space]in[space]range(numbytes)] [space][space]permseq2=permseq1[:] [space][space]random.shuffle(permseq1) [space][space]random.shuffle(permseq2) [space][space]list2=[0[space]for[space]i[space]in[space]range(numbytes)] [space][space]for[space]i[space]in[space]range(numbytes): [space][space][space][space]list2[permseq2[i]]=cipherbyarray[i] [space][space]cipherbyarray=bytearray(list2) [space][space]byarray=bytearray(b"") [space][space]k=0 [space][space]for[space]blk[space]in[space]range(numblocks): [space][space][space][space]t=sigma [space][space][space][space]prrot=t&prrotmask [space][space][space][space]t>>=prrotmasklen [space][space][space][space]nskip=t&skipmask [space][space][space][space]for[space]i[space]in[space]range(nskip): [space][space][space][space][space][space]random.getrandbits(blockbits) [space][space][space][space]prn=random.getrandbits(blockbits) [space][space][space][space]permpoly=[random.getrandbits(blockbits)[space]for[space]i[space]in[space]range(polynomm)] [space][space][space][space]permpoly=fullperiodcriteria(permpoly,polynomm) [space][space][space][space]k1=k+blockbytes [space][space][space][space]cipherint=pack(cipherbyarray[k:k1]) [space][space][space][space]k=k1 [space][space][space][space]rot=(bitcount(cipherint)+prrot)%blockbits [space][space][space][space]blockint2=(cipherint>>rot)|((cipherint<<(blockbits-rot))&blockmask) [space][space][space][space]choice=(sigma&choicebit)==0 [space][space][space][space]if[space]choice: [space][space][space][space][space][space]blockint1=invpermpoly(permpoly,polynomm,blockint2) [space][space][space][space]else: [space][space][space][space][space][space]blockint1=evalpermpoly(permpoly,polynomm,blockint2) [space][space][space][space]plainint=blockint1^prn^sigma [space][space][space][space]sigma=(sigma^ncombine(plainint,cipherint))&blockmask [space][space][space][space]byarray+=unpack(plainint,blockbytes) [space][space]list1=[0[space]for[space]i[space]in[space]range(numbytes)] [space][space]for[space]i[space]in[space]range(numbytes): [space][space][space][space]list1[permseq1[i]]=byarray[i] [space][space]byarray=bytearray(list1) [space][space]authenblocksrecovered=byarray[-authenblockslen:] #[space]Check[space]whether[space]the[space]authenblock[space]recovered[space]is[space]correct. [space][space]if[space]authenblocksrecovered==authenblocks: [space][space][space][space]print("Authentication[space](integrity[space]check)[space]o.k.") [space][space]else: [space][space][space][space]print("Authentication[space](integrity[space]check)[space]failed") [space][space][space][space]exit(222) #[space]Write[space]the[space]decrypted[space]text[space]in[space]byarray[space]to[space]a[space]binary[space]file. [space][space]writebinaryfile(byarray[:-authenblockslen],decryptedtextfilename) [space][space]print("Decrypted[space]text[space]written[space]to[space]file[space]with[space]name:",decryptedtextfilename, [space][space][space][space][space][space][space][space]"(extension[space].bin)") [space][space]return
###################[space]End[space]of[space]Part[space]1[space]of[space]LOTUS,[space]Version[space]1.1[space]######################## ################################################################################ ################################################################################
|
- Posts:
- 1,874
- Group:
- Members
- Member
- #3,310
- Joined:
- December 12, 2009
|
- Code:
-
################################################################################ ##################[space]Begin[space]of[space]Part[space]2[space]of[space]LOTUS,[space]Version[space]1.1[space]#######################
#[space]Installation[space]of[space]the[space]software.
#[space]Both[space]communication[space]partners[space]have[space]to[space]download[space]the[space]same[space]version[space]3x[space]of[space]Python #[space]from[space]http://www.python.org.[space](Employing[space]the[space]same[space]version[space]of[space]Python[space]ensures #[space]against[space]any[space]potentially[space]possible[space]incompatibilities[space]among[space]different[space]versions.) #[space]The[space]present[space]code[space]can[space]be[space]stored[space]in[space]a[space]file[space]named[space]e.g.[space]lotus.py[space]and[space]the[space]example #[space]given[space]below[space]run[space]in[space]Python's[space]GUI[space]IDLE.[space](File[space]-->[space]Open[space]to[space]find[space]and[space]open[space]the #[space]file[space]then[space]in[space]the[space]window[space]showing[space]the[space]code[space]Run[space]-->[space]Run[space]Module[space]to[space]run[space]it.[space]One #[space]could[space]also[space]type[space]lotus.py[space]in[space]a[space]DOS-window.)[space]Modifications[space]of[space]the[space]code[space]in[space]the #[space]code[space]window,[space]e.g.[space]the[space]plaintext[space]string,[space]can[space]be[space]done[space]online[space]and[space]the[space]code #[space]re-run.
################################################################################
#[space]Appendix.
#[space]This[space]appendix[space]contains[space]an[space]illustrative[space]example[space]of[space]encryption[space]and[space]decryption, #[space]a[space]number[space]of[space]useful[space]utility[space]functions[space]and[space]a[space]test[space]of[space]Python's[space]built-in[space]PRNG.
#[space]Users[space]running[space]his[space]own[space]code[space]lines[space]may[space]desire[space]to[space]deactivate[space]a[space]certain[space]region #[space](or[space]the[space]whole)[space]of[space]the[space]appendix.[space]This[space]may[space]be[space]done[space]through[space]placing[space]3[space]successive #[space]quotes[space](i.e.[space]""")[space]to[space]the[space]line[space]before[space]as[space]well[space]as[space]to[space]the[space]line[space]following[space]that #[space]region.
[space] #[space]An[space]illustrative[space]example.
#[space]Note[space]that[space]appropriate[space]choice[space]of[space]the[space]system[space]parameters[space]and[space]proper[space]management #[space]of[space]the[space]secret[space]key[space]materials[space]are[space]evidently[space]user's[space]own[space]responsibility[space]in[space]order #[space]to[space]be[space]able[space]to[space]obtain[space]the[space]required[space]security[space]for[space]his[space]applications.
#[space]The[space]following[space]code[space]lines[space]specifying[space]the[space]system[space]parameters[space]are[space]to[space]be[space]the[space]same #[space]for[space]both[space]communication[space]partners.
#[space]A[space]secret[space]key.[space]This[space]should[space]have[space]sufficient[space]entropy[space](i.e.[space]number[space]of[space]bits[space]of #[space]randomness)[space]for[space]the[space]application[space]concerned.
secretkey="4a98717c70e997c2715e87c3fa1ef559"
#[space]A[space]dynamic[space](variable)[space]session-dependent[space]supplementary[space]key,[space]being[space]dependent #[space]e.g.[space]on[space]subject,[space]date,[space]message[space]serial[space]number,[space]etc.[space]Its[space]use[space]enables[space]secretkey #[space]to[space]be[space]used[space]for[space]a[space]longer[space]time,[space]while[space]rendering[space]different[space]sessions[space]have #[space]different[space]effective[space]keys,[space]which[space]is[space]desirable.
sessionkeyextension="JJJ[space]07.03.2014[space]TM099"
#[space]Let[space]n[space]denote[space]the[space]number[space]of[space]bits[space]in[space]a[space]block,[space]logn[space]specifies[space]the[space]log[space]of[space]n. #[space]7[space]<=[space]logn[space]<=[space]9.[space]Here[space]we[space]specify[space]that[space]each[space]block[space]has[space]2**7[space]=[space]128[space]bits.
logn=7
#[space]If[space]the[space]user-given[space]plaintext[space]doesn't[space]end[space]at[space]a[space]block[space]boundary,[space]it[space]will[space]be #[space]appended[space]with[space]filler[space]characters.[space]Here[space]we[space]specify[space]that[space]"z"[space]is[space]to[space]be[space]the[space]filler.
fillerchar='z'
#[space]Number[space]of[space]authentication[space]blocks.[space]1[space]<=[space]nauthenblock[space]<=[space]3.
nauthenblock=1
#[space]Degree[space]of[space]permutation[space]polynormials[space]to[space]be[space]used[space]plus[space]1.[space]3[space]<=[space]polynomm[space]<=[space]5. #[space]We[space]choose[space]to[space]use[space]second[space]degree[space]polynomials[space](2[space]+[space]1[space]=[space]3).
polynomm=3
#[space]To[space]achieve[space]some[space]dynamics/variability[space]of[space]processing[space]of[space]a[space]block,[space]a[space]number #[space](skipbits)[space]of[space]bits[space]are[space]taken[space]from[space]sigma[space]to[space]determine[space]the[space]number[space]of[space]outputs #[space]from[space]Python's[space]built-in[space]PRNG[space]that[space]are[space]to[space]be[space]skipped.[space]1[space]<=[space]skipbits[space]<=[space]2.
skipbits=1
#[space]Sender[space]side[space]coding:
print("Sender[space]side[space]system[space]messages:") plaintextstr="Should[space]not[space]we,[space]then,[space]exert[space]ourselves[space]to[space]do[space]good?[space]--[space]"\ [space][space][space][space][space][space][space][space][space][space][space][space][space][space]"from[space]Kan[space]Ying[space]Pien[space](The[space]Book[space]of[space]Rewards[space]and[space]Punishments,[space]"\ [space][space][space][space][space][space][space][space][space][space][space][space][space][space]"translated[space]by[space]J.[space]Webster)" initlotus() prepareplaintextstr(plaintextstr,"plaintext") lotusencrypt("plaintext","ciphertext") print()
#[space]File[space]ciphertext.bin[space]obtained[space]is[space]to[space]be[space]transmitted[space]to[space]the[space]recipient.
[space] #[space]Recipient[space]side[space]coding:
print("Recipient[space]side[space]system[space]messages:") initlotus() lotusdecrypt("ciphertext","plaintextrecovered") recoveredplaintextstr=gettextstrfrombinaryfile("plaintextrecovered") print()
#[space]The[space]following[space]lines[space]serve[space]to[space]check[space]whether[space]our[space]code[space]has[space]correctly[space]functioned #[space]in[space]the[space]above[space]example.
print("Result:") print() print("Plaintext[space]sent:") print(plaintextstr) print() print("Possibly[space]end-filled[space]recovered[space]plaintext:") print(recoveredplaintextstr) print() print("Comparison:") print(plaintextstr==recoveredplaintextstr[:len(plaintextstr)]) print() print()
#[space]It[space]may[space]be[space]mentioned[space]that[space]for[space]key[space]management[space]a[space]master[space]secretkey[space]may[space]be[space]kept #[space]and[space]secretkey[space]that[space]is[space]to[space]be[space]used,[space]say,[space]in[space]a[space]certain[space]month,[space]be[space]obtained[space]through #[space]encryption[space]of[space]a[space]chosen[space]secret[space]text[space]string[space]that[space]contains[space]the[space]designation[space]of[space]the #[space]month[space]and[space]the[space]year[space]with[space]the[space]master[space]key[space]and[space]take[space]an[space]appropriate[space]section[space]from #[space]the[space]returned[space]ciphertext[space]bytes.[space]The[space]following[space]function[space]may[space]be[space]of[space]use[space]thereby.
#[space]Obtain[space]a[space]hexadecimal[space]sequence[space](without[space]the[space]"0x"[space]at[space]the[space]front)[space]from[space]the[space]content #[space]of[space]a[space]binary[space]file.
def[space]gethexstrfrombinaryfile(binaryfilename): [space][space]fp=open(binaryfilename+".bin","rb") [space][space]byarray=fp.read() [space][space]fp.close() [space][space]hexstr="" [space][space]for[space]i[space]in[space]range(len(byarray)): [space][space][space][space]h=hex(byarray[i])[2:] [space][space][space][space]if[space]len(h)<2: [space][space][space][space][space][space]h="0"+h [space][space][space][space]hexstr+=h [space][space]return(hexstr)
#[space]The[space]master[space]secret[space]key[space](and[space]preferably[space]also[space]another[space]one[space]in[space]reserve[space]for[space]the #[space]emergency[space]case[space]that[space]the[space]former[space]is[space]no[space]longer[space]usable)[space]must[space]evidently[space]be #[space]carefully[space]created[space]to[space]have[space]sufficient[space]entropy[space]and[space]hence[space]difficult[space]for[space]the #[space]analyst[space]to[space]determine[space]it[space]via[space]brute-forcing.[space]Commonly[space]it[space]is[space]deemed[space]desirable[space]to #[space]have[space]one[space]that[space]is[space]equivalent[space]to[space]at[space]least[space]128[space]bits[space]of[space]randomness.[space]The[space]present #[space]author[space]suggested[space]for[space]this[space]purpose[space]to[space]mix[space]a[space]number[space]of[space]secretly[space]chosen[space]natural #[space]language[space]text[space]strings,[space]since[space]the[space]English[space]language[space]texts[space]are[space]estimated[space]to[space]have #[space]from[space]0.6[space]to[space]1.6[space]bits[space]of[space]entropy[space]pro[space]character[space]such[space]that[space]employing[space]a[space]medium #[space]sized[space]string[space]resulting[space]from[space]such[space]a[space]mixture[space]would[space]be[space]sufficient.[space]Note[space]that,[space]if #[space]the[space]communication[space]partner[space]is[space]able[space]to[space]do[space]the[space]same[space]mixing[space](from[space]the[space]same[space]texts), #[space]then[space]a[space]transfer[space]of[space]the[space]resulting[space]secret[space]key[space]string[space]is[space]not[space]necessary.[space]For[space]a #[space]code[space]to[space]perform[space]the[space]mixing,[space]see #[space]http://s13.zetaboards.com/Crypto/topic/6936496/1/.[space]Users[space]of[space]LOTUS[space]may #[space]preferably[space]instead[space]encrpyt[space]a[space]pair[space]of[space]text[space]strings[space]with[space]LOTUS,[space]combine[space]the #[space]resulting[space]binary[space]files[space]using[space]the[space]following[space]function[space]and[space]obtain[space]a[space]hex[space]string #[space]with[space]the[space]function[space]gethexstrfrombinaryfile()[space]above.[space](In[space]case[space]of[space]more[space]than[space]two #[space]text[space]strings[space]this[space]processing[space]may[space]be[space]repeated.)
#[space]Combine[space]two[space]binary[space]files[space]with[space]the[space]function[space]ncombine().[space]A[space]prior[space]invocation[space]of #[space]initlotus()[space]is[space]assumed.[space]If[space]the[space]input[space]files[space]are[space]not[space]of[space]the[space]same[space]length,[space]the #[space]smaller[space]one[space]determines[space]the[space]size[space]of[space]the[space]output[space]file.
def[space]combinefiles(binaryfilename1,binaryfilename2,combinedbinaryfilename): [space][space]global[space]logn,blockbits,blockbytes,fillerchar,fillerbyte[space][space] [space][space]byarray1=readbinaryfile(binaryfilename1) [space][space]byarray2=readbinaryfile(binaryfilename2) [space][space]leng=min(len(byarray1),len(byarray2)) [space][space]byarray=bytearray("","latin-1") [space][space]k=0 [space][space]k1=blockbytes [space][space]while[space]k1<=leng: [space][space][space][space]int1=pack(byarray1[k:k1]) [space][space][space][space]int2=pack(byarray2[k:k1]) [space][space][space][space]int3=ncombine(int1,int2) [space][space][space][space]byarray+=unpack(int3,blockbytes) [space][space][space][space]k=k1 [space][space][space][space]k1=k+blockbytes [space][space]writebinaryfile(byarray,combinedbinaryfilename) [space][space]return
#[space]A[space]different[space]approach[space]to[space]obtain[space]a[space]good[space]secret[space]key[space]that[space]in[space]practice[space]is[space]also #[space]easily[space]available[space]to[space]the[space]common[space]users,[space]is[space]to[space]throw[space]dice.[space]There[space]are[space]different #[space]sorts[space]of[space]dice[space]purchasable[space]in[space]game[space]shops.[space]The[space]8-sided[space]ones[space]are[space]most[space]simple[space]for #[space]the[space]computaton[space]of[space]the[space]bit[space]strings[space]to[space]be[space]derived[space]from[space]each[space]throw.[space]But[space]dice[space]with #[space]larger[space]number[space]of[space]sides[space]needs[space]less[space]number[space]of[space]dice[space]and/or[space]number[space]of[space]throws.[space]For #[space]a[space]12-sided[space]die,[space]for[space]example,[space]a[space]throw[space]results[space]in[space]a[space]number[space]t[space]in[space][1,[space]12].[space]We[space]can #[space]commpute[space]the[space]corresponding[space]pseudo-random[space]bits[space]as[space]follows,[space]denoting[space]by #[space]bits(s,n)[space]the[space]bit[space]string[space]of[space]size[space]s[space]for[space]the[space]integer[space]n,[space]e.g.[space]bits(3,2)[space]is[space]"010": #[space]if[space]1[space]<=[space]t[space]<=[space]8[space]:[space][space]bstr[space]=[space]bits(3,t-1)[space] #[space]if[space]9[space]<=[space]t[space]<=[space]12:[space][space]bstr[space]=[space]bits(2,t-9) #[space]The[space]accumulated[space]bit[space]string[space]of[space]sufficient[space]length[space]can[space]finally[space]be[space]expressed[space]as #[space]a[space]hexadecimal[space]sequence[space]for[space]convenience[space]of[space]use.[space]Note[space]that[space]a[space]tiny[space]simplification #[space]of[space]computation[space]is[space]to[space]use[space]only[space]the[space]first[space]relation[space]above,[space]i.e.[space]ignoring[space]all #[space]t[space]>[space]8[space]but[space]that[space]means[space]a[space]larger[space]number[space]of[space]throws.[space](It[space]seems[space]in[space]fact[space]that[space]the #[space]possiblity[space]of[space]additionally[space]employing[space]the[space]second[space]relation[space]above[space]to[space]optimally #[space]extract[space]the[space]entropies[space]from[space]dice[space]throws[space]is[space]not[space]popularly[space]noticed.)[space]For[space]dice #[space]with[space]other[space]number[space]of[space]sides[space]a[space]similar[space]computation[space]can[space]be[space]done.[space]The[space]bit[space]string #[space]thus[space]obtained[space]can[space]be[space]expressed[space]as[space]a[space]hexadecimal[space]string[space](without[space]0x[space]at[space]the #[space]front)[space]with[space]the[space]following[space]function:[space]
def[space]gethexstrfrombitstr(bitstr): [space][space]hexlist=[] [space][space]bitlist=[] [space][space]for[space]i[space]in[space]range(16): [space][space][space][space]st=bin(i)[2:] [space][space][space][space]df=4-len(st) [space][space][space][space]if[space]df>0: [space][space][space][space][space][space]bitlist+=[df*'0'+st] [space][space][space][space]else: [space][space][space][space][space][space]bitlist+=[st] [space][space][space][space]hexlist+=hex(i)[2:] [space][space]hexstr="" [space][space]leng=len(bitstr) [space][space]k=0 [space][space]k1=4 [space][space]while[space]k1<=leng: [space][space][space][space]bs=bitstr[k:k1] [space][space][space][space]hexstr+=hexlist[bitlist.index(bs)] [space][space][space][space]k=k1 [space][space][space][space]k1=k+4 [space][space]return(hexstr)
#[space]A[space]utility[space]program[space]for[space]convenient[space]conversion[space]of[space]dice[space]throws[space]to[space]hexadecimal #[space]strings[space]is[space]available[space]at:[space]http://s13.zetaboards.com/Crypto/topic/7126796/1/
#[space]It[space]may[space]be[space]noted[space]that,[space]since[space]both[space]lotusencrypt()[space]and[space]lotusdecrypt()[space]work[space]with #[space]files,[space]it[space]is[space]convenient,[space]if[space]desired,[space]to[space]do[space]multiple[space]encryption[space]with[space]LOTUS #[space](with[space]different[space]system[space]parameter[space]values)[space]or[space]to[space]accept[space]encrypted[space]stuffs[space]from #[space]other[space]algorithms[space]for[space]further[space]processing[space](e.g.[space]from[space]author's[space]PREFIXCODING #[space]http://s13.zetaboards.com/Crypto/topic/7164646/1/).[space]In[space]such[space]cases[space]all[space]file #[space]lengths[space]must[space]however[space]be[space]multiples[space]of[space]one[space]and[space]the[space]same[space]value[space]of[space]blockbytes, #[space]i.e.[space]eventually[space]necessitating[space]appending[space]a[space]required[space]number[space]of[space]arbitrary[space]chosen #[space]filler[space]bytes[space]to[space]the[space]files[space]to[space]be[space]input[space]to[space]LOTUS[space]to[space]satisfy[space]its[space]processing #[space]requirement.[space]In[space]case[space]file[space]lenthening[space]is[space]required[space]it[space]may[space]be[space]done[space]with[space]the #[space]following[space]function[space]lengthenfile().[space]The[space]recipient[space](who[space]has[space]to[space]be[space]informed[space]of #[space]the[space]number[space]of[space]added[space]bytes)[space]will[space]then[space]need[space]a[space]file[space]shortening[space]operation[space]which #[space]may[space]be[space]performed[space]with[space]the[space]function[space]shortenfile()[space]further[space]below.
#[space]Lengthen[space]a[space]binary[space]file[space]with[space]numbytes[space]pseudo-random[space]bytes.[space]seed[space]is[space]an[space]arbitrary #[space]seed[space]used[space]to[space]seed[space]Python's[space]built-in[space]PRNG.[space]Note[space]that[space]call[space]of[space]this[space]function[space]may #[space]NOT[space]be[space]positioned[space]between[space]lotusinit()[space]and[space]the[space]corresponding[space]encryption[space]or #[space]decryption[space]function[space]calls[space](due[space]to[space]conflict[space]in[space]seeding[space]the[space]PRNG).
def[space]lengthenfile(seed,binaryfilename,numbytes): [space][space]byarray=readbinaryfile(binaryfilename) [space][space]random.seed(seed) [space][space]byarray+=bytearray([random.getrandbits(8)[space]for[space]i[space]in[space]range(numbytes)]) [space][space]writebinaryfile(byarray,binaryfilename) [space][space]return
#[space]Shorten[space]a[space]binary[space]file[space]by[space]numbytes[space]bytes.
def[space]shortenfile(binaryfilename,numbytes): [space][space]byarray=readbinaryfile(binaryfilename) [space][space]writebinaryfile(byarray[:-numbytes],binaryfilename) [space][space]return
#[space]Users[space]who[space]are[space]new[space]to[space]Python[space]or[space]who[space]begin[space]to[space]use[space]a[space]new[space]version[space]of[space]the[space]Python #[space]software[space]may[space]like[space]to[space]know[space]a[space]little[space]bit[space]about[space]the[space]statistical[space]qualities[space]of[space]its #[space]built-in[space]PRNG[space]which[space]is[space]employed[space]in[space]LOTUS.[space]The[space]following[space]code[space]is[space]intended[space]to #[space]serve[space]for[space]that[space]purpose.[space]prnbitn[space]is[space]the[space]number[space]of[space]bits[space]of[space]the[space]PRNs[space]to[space]be #[space]generated[space]and[space]must[space]be[space]a[space]multiple[space]of[space]8.[space]testseed[space]is[space]any[space]arbitrary[space]seed[space]chosen #[space]for[space]running[space]the[space]test.[space]One[space]may[space]like[space]to[space]try[space]a[space]number[space]of[space]different[space]prnbitn[space]and #[space]testseed.
import[space]math,random
#[space]Maurer's[space]Universal[space]Test,[space]see[space][2]. #[space][2][space]J-S.[space]Coron,[space]D.[space]Naccache,[space]An[space]Accurate[space]Evaluation[space]of[space]Maurer's[space]Universal[space]Test. #[space][space][space][space][space]http://www.jscoron.fr/publications/universal.pdf
qq=2560 qqp1=qq+1 kk=256000 qqkkp1=qq+kk+1
def[space]maurertest(bb): [space][space]global[space]qq,qqp1,kk,qqkkp1 [space][space]eftu=7.1836656 #[space]y1[space]and[space]y2[space]are[space]for[space]rho=0.01[space]and[space]rho=0.001[space]respectively. [space][space]y1=2.5758 [space][space]y2=3.2905 [space][space]t=[0[space]for[space]i[space]in[space]range(256)] [space][space]for[space]i[space]in[space]range(1,qqp1,1): [space][space][space][space]t[bb[i]]=i [space][space]sum=0.0 [space][space]for[space]i[space]in[space]range(qqp1,qqkkp1,1): [space][space][space][space]sum+=math.log10(i-t[bb[i]]) [space][space][space][space]t[bb[i]]=i [space][space]tu=(sum/kk)/math.log10(2.0) [space][space]c=math.sqrt(0.3732189+(0.3730195*256)/kk) [space][space]sigma=c*math.sqrt(3.2386622/kk) [space][space]t11=eftu-y1*sigma [space][space]t12=eftu+y1*sigma [space][space]t21=eftu-y2*sigma [space][space]t22=eftu+y2*sigma [space][space]return(tu,t11,t12,t21,t22)
def[space]maurertestresult(h,gg): [space][space]global[space]chnum [space][space]global[space]qq,qqp1,kk,qqkkp1 [space][space]if[space]h*chnum<qqkkp1: [space][space][space][space]print("Error[space]in[space]maurertestresult") [space][space][space][space]exit(6) [space][space]bb=[0[space]for[space]k[space]in[space]range(h*chnum)] [space][space]u=0 [space][space]k1=-1 [space][space]k2=chnum-1 [space][space]for[space]i[space]in[space]range(h): [space][space][space][space]g=gg[i] [space][space][space][space]for[space]k[space]in[space]range(k2,k1,-1): [space][space][space][space][space][space]bb[u]=g&0xff [space][space][space][space][space][space]g>>=8 [space][space][space][space][space][space]u+=1 [space][space][space][space]k1+=chnum [space][space][space][space]k2+=chnum [space][space]tu,t11,t12,t21,t22[space]=[space]maurertest(bb) [space][space]print("Maurer's[space]Universal[space]Test[space]for[space]L=8,[space]rho=0.01[space](Middle[space]value[space]is[space]the[space]"\ [space][space][space][space][space][space][space][space]"test[space]statistic\nand[space]should[space]lie[space]between[space]the[space]other[space]two[space]values):") [space][space]print(t11,tu,t12)
def[space]randtest(prnbitn,testseed): [space][space]global[space]chnum [space][space]if[space]prnbitn<8[space]or[space](prnbitn%8)!=0: [space][space][space][space]print("Error[space]randtext:[space]Wrong[space]prnbitn") [space][space][space][space]exit(55555) [space][space]chnum=prnbitn//8 [space][space]h=qqkkp1//chnum [space][space]if[space]h*chnum<qqkkp1: [space][space][space][space]h+=1 [space][space]random.seed(testseed) [space][space]tpwbitnm1=2**prnbitn-1
[space][space]print("PRNs[space]generated[space]with[space]random.randint():") [space][space]gg=[random.randint(0,tpwbitnm1)[space]for[space]i[space]in[space]range(h)] [space][space]maurertestresult(h,gg) [space][space]print("PRNs[space]generated[space]with[space]random.getrandbits():") [space][space]gg=[random.getrandbits(prnbitn)[space]for[space]i[space]in[space]range(h)] [space][space]maurertestresult(h,gg) [space][space]return
#[space]User[space]chosen[space]test[space]parameters:
prnbitn=128 testseed="My[space]arbitrarily[space]chosen[space]seed"
#[space]Run[space]the[space]test.
print("Test[space]of[space]Python's[space]PRNG,[space]parameters[space]used:") print("prnbitn:",prnbitn) print("testseed:",testseed) randtest(prnbitn,testseed)
|