JADE-S, a block cipher with authentication (integrity check) based on use of permutation p...

Have a question or want to start a discussion? Post it! No Registration Necessary.  Now with pictures!

JADE-S is a successor of JADE. It employs the same PRN generation
scheme as JADE but implements a novel idea of block encryption
processing which is inspired by the iterative solution of systems of
linear equations and is presented by me recently in a few Internet
forums. For comments and critiques I should be very grateful.

M. K. Shen

-----------------------------------------------------------------------
# JADE-S, a block cipher with authentication (integrity check) based on  
the use
# of permutation polynomials mod 2**n


# JADE-S is a block encryption scheme for securing the privacy of  
communications
# of the common people via encrypting text messages (with automatically
# performed authentication (integrity check)) sent over the Internet.  
Its novel
# design includes as a major component a sophistically designed  
pseudo-random
# number (PRN) generation scheme, involving a pool of constituent PRN  
generators
# (PRNGs) based on permutation polynomials mod 2**n that are pseudo-randomly
# activated (by themselves) with runtime dynamic renewal. Block lengths  
ranging
# from 128 to 1024 bits can be chosen by the user. Blocks of n bits are  
treated
# as n-bit integers with certain arithmetic operations being directly  
performed
# upon them. The PRNGs in the pool serve further the purpose of  
pseudo-random
# substitution (in the crypto sense) operations, since permutation  
polynomials
# can be employed for bijective mappings. Particular attention is paid  
to very
# thoroughly mixing together the entire set of blocks that constitute the
# user-given messages during encryption processing, thus resulting in  
superior
# avalanche effects. The very good readability of its open-source code  
enables
# the user to easily ensure the correctness of the code and that there  
can be no
# backdoors as could otherwise potentially be the case where commercial
# proprietary (blackbox) encryption software are employed. Speed competition
# with commercial software in processing huge volumes of materials, e.g.
# graphics files, is intentionally excluded from the design goals of  
JADE-S. On
# the other hand, extreme prudence is taken to ensure that the code is
# practically absolutely immune to all known attacks against block ciphers
# owing to the fact that their underlying assumptions simply don't hold for
# JADE-S from the very beginning. (JADE-S presumably will be secure as  
well in
# the forthcoming so-called post-quantum era.) Despite the trade-offs hereby
# forcefully being taken, JADE-S's processing efficiency, as benchmarking
# clearly shows, is nonetheless entirely acceptable for its targeted  
users (see
# result of running Ex. 2 in Sec.2, and Sec.3).

# JADE-S is a successor of JADE (latest Version 2.0.3 available from
# http://s13.zetaboards.com/Crypto/topic/6948465/1 /). It employs the  
same PRN
# generation scheme as JADE but implements a novel idea of block encryption
# processing which is taken from the iterative method of solutions of  
systems of
# equations in linear algegra and which is recently posted to a number  
of Usenet
# groups by the present author. A breif description of the major design  
features
# of JADE-S is as follows:
#
# 1. With the user-given key we build up in a bootstrap way from a PRNG  
based on
#    permutaton polynomial mod 2**n through an intermediate pool, i.e. a  
large
#    number, of PRNGs of the same kind to a final pool of such PRNGs. The
#    outputs of the final pool of PRNGs (which are pseudo-randomly  
chosen to be
#    activated by their own outputs) are post-processed through appropriate
#    summation and buffering such that the statistical qualities of the PRNs
#    ultimately being delivered are greatly improved and any attacks of the
#    analysts are rendered infeasible in practice.
#
# 2. Denoting the blocks of plainatext by x1, x2, ... xk, we perform the
#    following assignments sequentially for encryption processing:
#    x1 := f1(x1 + x2 ... + xk ^ r1)
#    x2 := f2(x1 + x2 ... + xk ^ r2)
#       ................
#    xk := fk(x1 + x2 ... + xk ^ rk)
#    where the f's are the permutation polynomials pseudo-randomly  
chosen from
#    those available in the final PRNG pool and the r's are PRNs  
generated by
#    the PRNG pool (see 1. above). Note that the f's are non-linear and  
that,
#    in obtaining the individual ciphertext blocks (the x's on the  
leftside of
#    the assignments) all blocks of the given message (some already  
processed,
#    some not yet) are directly involved, which clearly leads to a superior
#    avalanche effect. Compare however block-chaining that is commonly  
used in
#    running the other known block ciphers. (Note that sequential processing
#    means that e.g. in the 2nd assignment above x1 on the right-hand  
side has
#    already its new value obtained from the 1st assignment.)
#
# 3. For the purpose of authentication, we append a pseudo-random block  
to the
#    beginning of the given plaintext blocks such that it now takes the  
position
#    of x1 in the processing scheme sketched above. It is easily seen  
that x1
#    has strong influences on the results of all the other assignments. This
#    implies, conversely, that any manipulation of the ciphertext blocks  
will
#    with very high probability be reflected in the changed value of x1  
(with
#    respect to the one on encryption) obtained on decryption, which  
means that
#    x1 can serve well as a MAC for authentication. (JADE-S actually  
employs,
#    as an enhancement, also an additional pseudo-random block at the  
end of the
#    given plaintext blocks for authentication and the user may further  
specify
#    that more than one such authentication blocks be used.)


# Contents of this document:

# Section 1:  Python (http://www.python.org , Python 3.x) code of JADE-S with
# comments explaining the functionality of each function as well as the
# structuring of the entire program. Permissible values of system parameters
# and key materials are listed at the beginning of this section. Users  
with some
# programming experience and basic knowledge of Python should be able to  
read
# this section and understand how JADE-S exactly works without difficulties.

# Section 2:  Some examples demonstrating how JADE-S can be actually  
used for
# encryption/decryption as well as how Maurer's Universal Test can be  
done for
# getting informations on the statistical quality of the results obtained.

# Section 3:  Miscellaneous notes.


# Version 1.0, released on 24.06.2013. Comment lines last updated on  
29.06.2013.


# Code lines of documents with the same version number are always identical.
# The most recent document of JADE-S can be obtained from
# http://s13.zetaboards.com/Crypto/topic/7072208/1/


# This software may be freely used:

# 1. for all personal purposes unconditionally and

# 2. for all other purposes under the condition that its name, version  
number
#    and authorship are explicitly mentioned and that the author is  
informed of
#    all eventual code modifications done.


# The author is indebted to TPS for review and suggestions throughout  
JADE-S's
# development phase. Any remaining deficiencies of the software are  
however the
# sole responsibilty of the author.


# Concrete comments and constructive critiques are sincerely solicited  
either
# via the above thread or directly via email.


# Email address of the author: mok-kong.shen@t-online.de



################################################################################
################################################################################



#########   Section 1.  Python Code of JADE-S.



##### This section lists all functions defined in JADE-S. For each run  
of JADE-S
##### the user has to provide the appropriate system parameters and key
##### materials and invoke initjades(). See Sec.2 for examples.


# Permissible values of system parameters and key materials (limits chosen
# based on practical considerations) are as follows (the first 5 parameters
# of the list and ciphertextfilemode are essential, the rest could be more
# or less arbitrarily chosen, their variability has albeit the  
beneficial side
# effect of enhancing the the complexity facing the analyst):

# logn: log base 2 of the number of bits (n) in a block.
#       7 <= logn <= 10.

# baseprngm: Degree of polynomials + 1 of the PRNGs in baseprngpool.
#            baseprngm >= prngm.

# logbasepoolsize: log base 2 of the size of baseprngpool.
#                  7 <= logbasepoolsize <= 10

# prngm: Degree of polynomials + 1 of the PRNGs in prngpool.
#        3 <= prngm.

# logpoolsize: log base 2 of the size of prngpool.
#              7 <= logpoolsize <= 10

# maxprngusecount: Maxmal number of uses of a PRNG in prngpool to  
generate PRNs
#                  before it is automatically renewed.
#                  20 <= maxprngusecount

# initialrandompriming: Priming value of the PRNG geninitialrandom().
#                       0 <= initialrandompriming.

# baserandompriming: Priming value of the PRNG genbaserandom().
#                    0 <= baserandompriming.

# randompriming: Priming value of the PRNG genrandom().
#                0 <= randompriming.

# initvecblocknum: Number of authentication blocks at the begining of
#                  ciphertext.
#                  1 <= initvecblocknum.

# finalvecblocknum: Number of authentication blocks at the end of  
ciphertext.
#                  0 <= finalvecblocknum.

# ciphertextfilemode:  = 0: Outputfile is Python specific (not printable).
#                      = 1: Outputfile is in decimal integers (printable).
#                      = 2: Outputfile is in hexadecimal integers  
(printable).

# keydata: A list of 2 elements of (maximal) n/2 bits each.
#          Larger values given will be truncated mod 2**n.

# seeddata: 1 element of (maximal) n/2 bits.
#           Larger values given will be truncated mod 2**n.


# Loading three system modules of Python.

import math,time,pickle


##### All pseudo-random number generators (PRNGs) of JADE-S are based on
##### permutation polynomials mod 2**n. The user-given key materials are  
used to
##### establish the ultimate PRNG genrandom() through a bootstrapping  
process
##### via gennhrandom(), geninitialrandom() and genbaserandom().


##### The function fullperiodcriteria(), evalpermpoly(), invpermpoly() are
##### general functions required for computating with permutation  
polynomials
##### mod 2**n.


# Modify user-supplied coefficients of the polynomial poly so as to  
satisfy the
# full-period criteria of a permutation polynomial mod 2**n. The degree  
of poly
# is required to be at least 2. m denotes the number of coefficients of the
# polynomial, i.e. degree of polynomial plus 1. For the criteria see  
ref.[1],
# p.283.
# [1] V. Anashin, A. Khrennikov, Applied Algebraic Dynamics, Berlin, 2009.
#     http://www.degruyter.com/view/supplement/9783110203011_Errata.pdf
# We use for simplification of coding a restricted form of the criteria,  
namely:
#    c_0 = c_1 = 1  mod 4
#    c_i = 0  mod 4    for all other i

def fullperiodcriteria(poly,m):
   global logn,n,np1,nm1,nh,chnum
   global tpwn,tpwnm1,shfnrot,tpwnh,tpwnhm1,shfnhrot
   if m<3:
     print("Error in fullperiodcriteria")
     exit(1)
   gg=(tpwnm1<<2)&tpwnm1
   permpoly=poly[:]
   for i in range(2):
     permpoly[i]=(permpoly[i]&gg)|1
   for i in range(2,m):
     permpoly[i]&=gg
   return(permpoly)


# Evaluate permpoly with argument x with Horner's method.

def evalpermpoly(permpoly,m,x):
   global logn,n,np1,nm1,nh,chnum
   global tpwn,tpwnm1,shfnrot,tpwnh,tpwnhm1,shfnhrot
   y=permpoly[m-1]
   for i in range(m-2,-1,-1):
     y=(y*x+permpoly[i])&tpwnm1
   return(y)


# Inverse of evalpermpoly(). First derivative of permpoly(x) = 1 mod 2.  
Hensel's
# lifting lemma leads to the iteration: x_(i+1)=x_i-g(x_i) mod 2**(i+1),  
with
# g(x)=permpoly(x)-y. See ref.[1], p.306.

def invpermpoly(permpoly,m,y):
   global logn,n,np1,nm1,nh,chnum
   global tpwn,tpwnm1,shfnrot,tpwnh,tpwnhm1,shfnhrot
   if (((permpoly[0]-y)&tpwnm1)&1)==0:
     x=0
   else:
     x=1
   for i in range(2,np1,1):
     x=(x-(evalpermpoly(permpoly,m,x)-y))&tpwnm1
   return(x)


##### The user-given key (a list of 2 elements of n/2 bits) and seed (1  
element
##### of n/2 bits) are used to build a PRNG gennhrandom(), delivering  
PRNs of
##### n/2 bits, with the help of nhcombine() and buildinitialgenerator().
##### Concatenating 2 successive outputs gennhrandom() forms then the  
output of
##### n bits of the PRNG geninitialrandom(), which will be used in the next
##### higher level code of PRN generation.


# Combining two n/2 bit words with reciprocal rotation and xor.

def nhcombine(x,y):
   global logn,n,np1,nm1,nh,chnum
   global tpwn,tpwnm1,shfnrot,tpwnh,tpwnhm1,shfnhrot
   rotx=x>>shfnhrot
   roty=y>>shfnhrot
   rx=((x<<roty)&tpwnhm1)|(x>>(nh-roty))
   ry=((y<<rotx)&tpwnhm1)|(y>>(nh-rotx))
   r=rx^ry
   return(r)


# Build a linear congruential PRNG mod 2**(n/2), gennhrandom(), from the
# user-given keydata and seeddata.
# Full period criteria: c0 = 1 mod 2, c1 = 1 mod 4, see ref.[1].

def buildinitialgenerator():
   global keylen,keydata,seeddata,key,seed,basekeylen
   global tpwn,tpwnm1,shfnrot,tpwnh,tpwnhm1,shfnhrot
   key=keydata
   seed=seeddata
   if (len(key)!=2):
     print("Error in buildinitialgeneator")
     exit(2)
   gg=(tpwnhm1<<2)&tpwnhm1
   key[0]=(key[0]&tpwnhm1)|0x1
   key[1]=((key[1]&tpwnhm1)&gg)|0x1
   seed=seed&tpwnhm1


# Combine two outputs of the linear PRNG established in  
buildinitialgenerator()
# with nhcombine() to obtain one output of n/2 bits of gennhrandom().  
Function
# returns a list of veclen elements.

def gennhrandom(veclen):
   global keylen,keydata,seeddata,key,seed,basekeylen
   global tpwn,tpwnm1,shfnrot,tpwnh,tpwnhm1,shfnhrot
   nhrandom=[]
   for i in range(veclen):
     r1=seed=(key[0]+key[1]*seed)&tpwnhm1
     r2=seed=(key[0]+key[1]*seed)&tpwnhm1
     nhrandom+=[nhcombine(r1,r2)]
   return(nhrandom)


# Concatenate two outputs from gennhrandom() to be one of n bits. Function
# returns a list of veclen elements.

def geninitialrandom(veclen):
   global logn,n,np1,nm1,nh,chnum
   global keylen,keydata,seeddata,key,seed,basekeylen
   global tpwn,tpwnm1,shfnrot,tpwnh,tpwnhm1,shfnhrot
   random=[]
   for i in range(veclen):
     r=gennhrandom(2)
     random+=[(r[0]<<nh)|r[1]]
   return(random)


##### Outputs of geninitialrandom() are used to build a pool of PRNGs  
based on
##### permutation polynomials mod 2**n of degree baseprngm-1, designated as
##### baseprngpool, with the help of ncombine() and  
buildbasegeneratorpool().
##### genbaserandom() then delivers PRNs from this pool, which will be  
used for
##### the next higher level code of PRN generation.


# Combining two n bit words with reciprocal rotation and xor.

def ncombine(x,y):
   global logn,n,np1,nm1,nh,chnum
   global tpwn,tpwnm1,shfnrot,tpwnh,tpwnhm1,shfnhrot
   rotx=x>>shfnrot
   roty=y>>shfnrot
   rx=((x<<roty)&tpwnm1)|(x>>(n-roty))
   ry=((y<<rotx)&tpwnm1)|(y>>(n-rotx))
   r=rx^ry
   return(r)


# Use geninitialrandom() to build a PRNG (consisting of two internal  
PRNGs of
# degree baseprngm-1, with keys gbasekey1 and gbasekey2 and seeds  
gbaseseed1 and
# gbaseseed2) to build a pool of PRNGs of degree baseprngm-1, designated as
# baseprngpool.

def buildbasegeneratorpool():
   global baseprngm,logbasepoolsize,basepoolsize,baseprngpool,baseprngseed
   global basebuffer,basebufpt
   global baseprn,baseindex,baseprngsum,shfbaseindex,shfbasebegin
   global initialrandompriming,baserandompriming,randompriming
   buildinitialgenerator()
# Priming of geninitialrandom().
   geninitialrandom(initialrandompriming)
   rr1=geninitialrandom(baseprngm+1)
   gbasekey1=rr1[:-1]
   gbaseseed1=rr1[-1]
   rr2=geninitialrandom(baseprngm+1)
   gbasekey2=rr2[:-1]
   gbaseseed2=rr2[-1]
   gbasekey1=fullperiodcriteria(gbasekey1,baseprngm)
   gbasekey2=fullperiodcriteria(gbasekey2,baseprngm)
   baseprngpool=[]
   baseprngseed=[]
   basebuffer=[]
   for i in range(basepoolsize):
     randtmp=[]
     for j in range(baseprngm+2):
       r1=gbaseseed1=evalpermpoly(gbasekey1,baseprngm,gbaseseed1)
       r2=gbaseseed2=evalpermpoly(gbasekey2,baseprngm,gbaseseed2)
       randtmp+=[ncombine(r1,r2)]
     permpoly=fullperiodcriteria(randtmp[:-2],prngm)
     baseprngpool+=[permpoly]
     baseprngseed+=[randtmp[-2]]
     basebuffer+=[randtmp[-1]]
   basebufpt=0
   baseprn=0
   baseindex=0
   baseprngsum=0


# Generate a sequence of PRNs (a list of veclen elements) from the  
baseprngpool.
# The consituent PRNG in the pool currently indexed by baseindex is  
activated
# and outputs baseprn. baseprn is summed into an accumulator  
(baseprngsum) and
# the sums are passed through a buffer (basebuffer) to result in the  
elements
# of the desired sequence. The pseudo-radnom nature of the activation of the
# constituent PRNGs in the pool, together with the post-processing of their
# outputs, which introduces indeterminancies for the analysis, effectively
# thwart the analyst's sequence prediction attempts. For, given an  
output value
# from this function, he is blocked all along the path that would lead  
backwards
# to the one particular constituent PRNG that mainly contributed to that  
value.
# Note also that there are moreover no statistical biases in the output
# sequences of JADE-S's genbaserandom() (this applies also to  
genrandom() of the
# next higher final level of PRN generation further below) to be  
exploited in
# practice, as test results with Maurer's Universal Test have shown.  
(Decades
# ago someone published a PRN generation scheme in a journal of  
statistics where
# a number of PRNGs are activated in a round-robin fashion in order to  
obtain
# better statistical properties. The present author later independently  
proposed
# in Internet forums to use a similar scheme where the activation of the
# consituent PRNGs is albeit not in a fixed serial order but pseudo-random,
# which is apparently to be preferred for crypto security purposes.)  
Note that
# below both baseindex and basebufpt are obtained from bits of the  
accumulator
# baseprngsum, which is pseudo-random. For the use of buffers, cf.  
Algorithm B
# in ref.[2], p.34.
# [2] D. E. Knuth, The Art of Computer Programming, vol. 2, 3rd ed.,  
Reading,
# 1998.

def genbaserandom(veclen):
   global tpwn,tpwnm1,shfnrot,tpwnh,tpwnhm1,shfnhrot
   global baseprngm,logbasepoolsize,basepoolsize,baseprngpool,baseprngseed
   global basebuffer,basebufpt
   global baseprn,baseindex,baseprngsum,shfbaseindex,shfbasebegin
   random=[]
   for i in range(veclen):
     k=baseprngsum>>shfbasebegin
     basebufpt=k&logbasepoolsize
     baseindex=(k>>logbasepoolsize)
     baseprn=baseprngseed[baseindex]\
            =evalpermpoly(baseprngpool[baseindex],baseprngm,\
                          baseprngseed[baseindex])
     baseprngsum=(baseprngsum+baseprn)&tpwnm1
     basebf=basebuffer[basebufpt]
     basebuffer[basebufpt]=basebf
     random+=[basebf]
   return(random)


##### Outputs of genbaserandom() are used to build a pool of PRNGs based on
##### permutation polynomials mod 2**n of degree prngm-1, designated as
##### prngpool, with the help of buildgeneratorpool(). genrandom() then  
delivers
##### outputs from this pool, which will be used for the proper
##### encryption/decryption processing of JADE-S.


# Use genbaserandom() to build a pool of PRNGs, designated as prngpool.

def buildgeneratorpool():
   global logn,n,np1,nm1,nh,chnum
   global prngm,logpoolsize,poolsize,maskpool
   global prngpool,prngseed,prngusecount,maxprngusecount
   global prn,index,shfindex,shfbegin,prngfeedback
   global initialrandompriming,baserandompriming,randompriming
   global prngsum,buf1sum,buffer1,buffer2,buf1pt,buf2pt
   buildbasegeneratorpool()
# Priming of genbaserandom().
   genbaserandom(baserandompriming)
   prngpool=[]
   prngseed=[]
   prngusecount=[]
   buffer1=[]
   buffer2=[]
   for i in range(poolsize):
     randtmp=genbaserandom(prngm+3)
     permpoly=fullperiodcriteria(randtmp[:-3],prngm)
     prngpool+=[permpoly]
     prngseed+=[randtmp[-3]]
     buffer1+=[randtmp[-2]]
     buffer2+=[randtmp[-1]]
     prngusecount+=[0]
   prn=0
   index=0
   buf1pt=buf2pt=0
   prngsum=buf1sum=0
   prngfeedback=0


# Renew the PRNG in the prngpool currently indexed by index using
# genbaserandom(). This function is called by genrandom().

def renewal():
   global prngm,logpoolsize,poolsize,maskpool
   global prngpool,prngseed,prngusecount,maxprngusecount
   global prn,index,shfindex,shfbegin,prngfeedback
   randtmp=genbaserandom(prngm)
   prngpool[index]=fullperiodcriteria(randtmp,prngm)


# Generate a sequence of PRNs (a list of veclen elements) from the prngpool,
# similar to genbaserandom() but employing two summations (prngsum and  
buf1sum)
# and two buffers (buffer1 and buffer2). If prngfeedback is 1, index is  
reset
# to a pseudo-random new value. If the usecount of the PRNG at index exceeds
# maxprngusecount, it is renewed with renewal(). User may employ  
genrandom(),
# after calling initjades(), to generate PRNs for use in applications
# independent of JADE-S's encryption/decryption. In such cases benefits of
# dynamics/variability could be obtained via appropriate use of the variable
# prngfeedback and the function renewal().

def genrandom(veclen):
   global prngm,logpoolsize,poolsize,maskpool
   global prngpool,prngseed,prngusecount,maxprngusecount
   global prn,index,shfindex,shfbegin,prngfeedback
   global prngsum,buf1sum,buffer1,buffer2,buf1pt,buf2pt
   random=[]
   for i in range(veclen):
     k=prngsum>>shfbegin
     buf2pt=k&maskpool
     k>>=logpoolsize
     buf1pt=k&maskpool
     if prngfeedback==1:
# index arbitrarily determined by rightmost logn bits of prngsum.
       index=prngsum&maskpool
       prngfeedback=0
     else:
       index=(k>>logpoolsize)
     if prngusecount[index]>=maxprngusecount:
       renewal()
       prngusecount[index]=1
     else:
       prngusecount[index]+=1
     prn=prngseed[index]\
        =evalpermpoly(prngpool[index],prngm,prngseed[index])
     prngsum=(prngsum+prn)&tpwnm1
     bf1=buffer1[buf1pt]
     buffer1[buf1pt]=prngsum
     buf1sum=(buf1sum+bf1)&tpwnm1
     bf2=buffer2[buf2pt]
     buffer2[buf2pt]=buf1sum
     random+=[bf2]
   return(random)


##### The user has to initialize the system with initjades() for each run of
##### JADE-S.


# Check the user-given system parameters for conformance to constraints  
given
# further above and compute the corresponding values of all system variables
# required for running JADE-S.

def initjades():
   global logn,n,np1,nm1,nh,chnum
   global tpwn,tpwnm1,shfnrot,tpwnh,tpwnhm1,shfnhrot
   global baseprngm,logbasepoolsize,basepoolsize,baseprngpool,baseprngseed
   global baseprn,baseindex,baseprngsum,shfbaseindex,shfbasebegin
   global initialrandompriming,baserandompriming,randompriming
   global prngm,logpoolsize,poolsize,maskpool
   global prngpool,prngseed,prngusecount,maxprngusecount
   global prn,index,shfindex,shfbegin,prngfeedback
   global initvecblocknum,finalvecblocknum,initvector,finalvector
   global ciphertextfilemode,formatstr,digitnum,hexnum,base,fileext
   global shfchoice
   if logn<7 or logn>10 or baseprngm<prngm or logbasepoolsize<7 or\
      logbasepoolsize>10 or prngm<3 or logpoolsize<7 or logpoolsize>10 or\
      maxprngusecount<20 or initialrandompriming<0 or  
baserandompriming<0 or\
      randompriming<0 or initvecblocknum<1 or finalvecblocknum<0 or\
      ciphertextfilemode<0 or ciphertextfilemode>2:
     print("Error in initjades")
     exit(3)
   n=2**logn
   np1=n+1
   nm1=n-1
   tpwn=2**n
   tpwnm1=tpwn-1
   shfnrot=n-logn
   nh=n//2
   tpwnh=2**nh
   tpwnhm1=tpwnh-1
   shfnhrot=nh-(logn-1)
   basepoolsize=2**logbasepoolsize
   shfbaseindex=n-logbasepoolsize
   shfbasebegin=n-(2*logbasepoolsize)
   poolsize=2**logpoolsize
   shfindex=n-logpoolsize
   shfbegin=n-(3*logpoolsize)
   maskpool=poolsize-1
   shfchoice=shfindex-1
   chnum=n//8
   buildgeneratorpool()
# System priming of genrandom(), value arbitrarily determined.
   genrandom(3*poolsize)
# User priming of genrandom().
   genrandom(randompriming)
# Initialize initvector and finalvector with some arbitrary pseudo-random
# values.
   initvector=genrandom(initvecblocknum)
   finalvector=genrandom(finalvecblocknum)
   if ciphertextfilemode==0:
     formatstr=""
     fileext=".bin"
   elif ciphertextfilemode==1:
     digitnum=int(math.log(tpwnm1,10))
     if 10**digitnum<tpwnm1:
       digitnum+=1
     formatstr=""
     base=10
     fileext=".txt"
   else:
     hexnum=2*chnum
     formatstr=""
     base=16
     fileext=".txt"


##### The following functions do the proper work of  
encryption/decryption using
##### the PRNG genrandom() developed above.

##### enc() and dec() are basic functions that will be used in the  
higher level
##### functions encrypt() and decrypt().

##### Filler of user-given plaintext to block boundary is 'z'.


# The elements in nplist are integer values that result from byte-wise  
encoding
# of plaintext characters in a block (of chnum characters). We compute  
for the
# elements x1, x2, ... xk of the list the following, where the f's are
# invertible non-linear functions, the r's are pseudo-random numbers and the
# assignments are performed sequentially:
#    x1 := f1(x1 + x2 ... + xk ^ r1)
#    x2 := f2(x1 + x2 ... + xk ^ r2)
#       ................
#    xk := fk(x1 + x2 ... + xk ^ rk)
# (The scheme, suggested for block encryption processing by the present  
author
# recently in a few Internet forums ,is inspired by the iterative  
solution of
# systems of linear equations as given in V. N. Faddeeva, Computational  
Methods
# of Linear Algebra, p.117, Dover Publ., 1959.) The f's are pseudo-randomly
# selected from the pool of permutation polynomials mod 2**n on which
# genrandom() is based and the r's are obtained from genrandom(). We  
employ for
# an f either evalpermpoly() or invpermpoly() depending on the pseudo-random
# value choice. This renders the processing time of encryption and  
decryption
# equal, since the inverse computation takes more time. Note that the
# block-chaining effect in the use of the other known common block  
ciphers is
# intrinsically present in our scheme, as in every step all blocks are  
(equally)
# involved in the argument of f, with the consequence that a far  
superior mixing
# together and hence degree of interdependence of all blocks involved during
# processing is achieved. For the purpose of authentication, we append a
# pseudo-random block to the beginning of the sequence of given  
plaintext blocks
# such that it now takes the position of x1 in the processing scheme  
sketched
# above. It is easily seen that x1 has strong influences on the results  
of all
# the other assignments. This implies, conversely, that any manipulation  
of the
# ciphertext blocks will with very high probability be reflected in the  
changed
# value of x1 (with respect to the one on encryption) obtained on  
decryption,
# which means that x1 can serve well as a MAC for authentication. JADE-S
# actually employs, as an enhancement, also an additional pseudo-random  
block at
# the end of the given plaintext blocks for authentication and the user may
# further specify that more than one such authentication blocks be used.  
See the
# system parameters initvecblocknum and finalvecblocknum. Note that after
# execution of enc() nclist is also available globally (in particular, the
# encrypted finalvector can be obtained with nclist[-finalvecblocknum:]  
for use
# as a kind of hash value).

def enc(nplist):
   global logn,n,np1,nm1,nh,chnum
   global tpwn,tpwnm1,shfnrot,tpwnh,tpwnhm1,shfnhrot
   global prngm,logpoolsize,poolsize,maskpool
   global prngpool,prngseed,prngusecount,maxprngusecount
   global prn,index,shfindex,shfbegin,prngfeedback
   global shfchoice
   global nclist
   nclist=nplist[:]
   lenlist=len(nclist)
   choice=[]
   polyindex=[]
   random1=genrandom(lenlist)
# random2 provides the PRNs in the scheme sketched above.
   random2=genrandom(lenlist)
   for i in range(lenlist):
# Leading bits of random1 provide polyindex and choice.
     k=random1[i]>>shfchoice
     choice+=[k&1]
     polyindex+=[k>>1]
   sigmax=0
   for i in range(lenlist):
     sigmax+=nclist[i]
   sigmax=sigmax&tpwnm1
   for i in range(lenlist):
     if choice[i]==0:
       tt=evalpermpoly(prngpool[polyindex[i]],prngm,sigmax^random2[i])
     else:
       tt=invpermpoly(prngpool[polyindex[i]],prngm,sigmax^random2[i])
     sigmax=(sigmax-nclist[i]+tt)&tpwnm1
     nclist[i]=tt
   return(nclist)


# Inverse of enc().

def dec(nclist):
   global logn,n,np1,nm1,nh,chnum
   global tpwn,tpwnm1,shfnrot,tpwnh,tpwnhm1,shfnhrot
   global prngm,logpoolsize,poolsize,maskpool
   global prngpool,prngseed,prngusecount,maxprngusecount
   global prn,index,shfindex,shfbegin,prngfeedback
   global shfchoice
   nplist=nclist[:]
   lenlist=len(nclist)
   choice=[]
   polyindex=[]
   random1=genrandom(lenlist)
   random2=genrandom(lenlist)
   for i in range(lenlist):
     k=random1[i]>>shfchoice
     choice+=[k&1]
     polyindex+=[k>>1]
   sigmax=0
   for i in range(lenlist):
     sigmax+=nplist[i]
   sigmax=sigmax&tpwnm1
   for i in range(lenlist-1,-1,-1):
     if choice[i]==0:
       tt=invpermpoly(prngpool[polyindex[i]],prngm,nplist[i])
     else:
       tt=evalpermpoly(prngpool[polyindex[i]],prngm,nplist[i])
     vv=(sigmax-nplist[i])&tpwnm1
     nplist[i]=((tt^random2[i])-vv)&tpwnm1
     sigmax=(vv+nplist[i])&tpwnm1
   return(nplist)


##### pack() and unpack() are auxiliary functions needed in encrypt() and
##### decrpyt().


# Convert a string s to a binary integer representation.

def pack(s):
   b=s.encode('latin1')
   k=0
   for i in range(len(b)):
     k<<=8
     k|=b[i]
   return(k)


# The inverse of pack(). blen is the length of the original string that was
# previously processed by pack().

def unpack(k,blen):
   b=bytearray(blen)
   for i in range(blen-1,-1,-1):
     b[i]=k&0xff
     k>>=8
   s=b.decode('latin1')
   return(s)


##### encrypt() encrpyts the user-given plaintext and writes the  
ciphertext into
##### a file with name ciphertextname and file extension bin/txt  
according to
##### ciphetextfilemode=0/1/2, i.e. whether the file is to be in Python  
specific
##### format or consisting of a list of decimal or hexadecimal integers.
##### decrpyt() decrypts a file thus obtained back into the plaintext.


# If the length of the plaintext string is not a multiple of block  
length (chnum
# characters), a filling with the character 'z' is done. Divide the  
plaintext
# string into a number of blocks. Each block is then converted into one  
integer
# by pack(), resulting thus in a list of integers, nplist. The PRN  
initvector
# and finalvector, generated in initjades(), are appended to the  
beginning and
# and end of nplist respectively for purpose of authentication in decrypt().
# nplist is encrypted with enc() to nclist and is written to ciphertextfile
# according to the system parameter ciphertextfilemode. (If the plaintext is
# given in an external file, see comments in Ex.1 of Sec.2 on how to  
read it in
# for processing.)

def encrypt(plaintext,ciphertextname):
   global logn,n,np1,nm1,nh,chnum
   global tpwn,tpwnm1,shfnrot,tpwnh,tpwnhm1,shfnhrot
   global initvecblocknum,finalvecblocknum,initvector,finalvector
   global ciphertextfilemode,formatstr,digitnum,hexnum,base,fileext
   print("Processing string plaintext")
   k=len(plaintext)%chnum
   if k!=0:
     for i in range(chnum-k):
       plaintext+="z"
     print("Plaintext is extended at end with",chnum-k,"'z' "\
           "for satisfying processing requirement")
   k=0
   nplist=[]
   for i in range(len(plaintext)//chnum):
     nplist+=[pack(plaintext[k:k+chnum])]
     k+=chnum
# Append initvector and finalvector.
   nplist=initvector+nplist+finalvector
   lenlist=len(nplist)
# Encryption processing with the function enc().
   nclist=enc(nplist)
# Output to ciphertextfile.
   ciphertextfile=ciphertextname+fileext
   if ciphertextfilemode==0:
     fp=open(ciphertextfile,"wb")
     pickle.dump(nclist,fp)
     print("File is not printable and has to be sent as such")
   else:
     fp=open(ciphertextfile,"w")
     for i in range(lenlist):
       fp.write(formatstr.format(nclist[i])+"\n")
     if ciphertextfilemode==1:
       print("File consists of",lenlist,"integers (maximum size for each",\
             "integer:",digitnum,"digits)")
     else:
       print("File consists of",lenlist,"integers (maximum size for each",\
             "integer:",hexnum,"hexadecimal\ndigits with prefix '0x')")
   fp.close()
   print("Ciphertext has been written to file:",ciphertextfile)
   print()


# Inverse of encrypt(). If the first initvecblocknum and last  
finalvecblocknum
# elements of nplist obtained are identical to initvector and finalvector
# respectively, the authentication (integrity check) is ok. An integer to
# characters conversion is then done with unpack(). The recovered plaintext
# string is returned. Note that this may contain filling characters 'z'  
added
# by encrypt(). (If the plaintext is to be written out to an external  
file, see
# comments in Ex.1 of Sec. 2 on how to do that.)

def decrypt(ciphertextname):
   global logn,n,np1,nm1,nh,chnum
   global tpwn,tpwnm1,shfnrot,tpwnh,tpwnhm1,shfnhrot
   global initvecblocknum,finalvecblocknum,initvector,finalvector
   global ciphertextfilemode,formatstr,digitnum,hexnum,base,fileext
   ciphertextfile=ciphertextname+fileext
   print("Processing file",ciphertextfile)
   if ciphertextfilemode==0:
     fp=open(ciphertextfile,"rb")
     nclist=pickle.load(fp)
   else:
     fp=open(ciphertextfile,"r")
     ncliststrlist=fp.read().split()
     nclist=[]
     for i in range(len(ncliststrlist)):
       nclist+=[int(ncliststrlist[i],base)]
   fp.close()
   lenlist=len(nclist)
# Decryption processing with the function dec().
   nplist=dec(nclist)
# Check whether initvector and finalvecter are correctly recovered and
# exclude them from nplist.
   authen1=nplist[:initvecblocknum]
   if finalvecblocknum>0:
     authen2=nplist[-finalvecblocknum:]
     nplist=nplist[initvecblocknum:-finalvecblocknum]
   else:
     authen2=[]
     nplist=nplist[initvecblocknum:]
   if authen1!=initvector or authen2!=finalvector:
     print("######### Authentication (intgegrity check) failed #########")
     exit(5)
   plaintextrecovered=""
   for i in range(len(nplist)):
     plaintextrecovered+=unpack(nplist[i],chnum)
   print("Plaintext has been recoverd from",ciphertextfile)
   print("Authentication (integrity check) ok")
   print()
   return(plaintextrecovered)



################################################################################
################################################################################



#########   Section 2.  Examples of Applications of JADE-S.



##### The following code does not belong to JADE-S in the proper sense  
but serves
##### only to illustrate with examples further below how the user may apply
##### JADE-S.


# Maurer's Universal Test, see [3].
# [3] J-S. Coron, D. Naccache, An Accurate Evaluation of Maurer's  
Universal Test.
#     http://www.jscoron.fr/publications/universal.pdf


qq=2560
qqp1=qq+1
kk=256000
qqkkp1=qq+kk+1


def maurertest(bb):
   global qq,qqp1,kk,qqkkp1
   eftu=7.1836656
# y1 and y2 are for rho=0.01 and rho=0.001 respectively.
   y1=2.5758
   y2=3.2905
   t=[0 for i in range(256)]
   for i in range(1,qqp1,1):
     t[bb[i]]=i
   sum=0.0
   for i in range(qqp1,qqkkp1,1):
     sum+=math.log10(i-t[bb[i]])
     t[bb[i]]=i
   tu=(sum/kk)/math.log10(2.0)
   c=math.sqrt(0.3732189+(0.3730195*256)/kk)
   sigma=c*math.sqrt(3.2386622/kk)
   t11=eftu-y1*sigma
   t12=eftu+y1*sigma
   t21=eftu-y2*sigma
   t22=eftu+y2*sigma
   return(tu,t11,t12,t21,t22)


def maurertestresult(h,gg):
   global logn,n,np1,nm1,nh,chnum
   global qq,qqp1,kk,qqkkp1
   if h*chnum<qqkkp1:
     print("Error in maurertestresult")
     exit(6)
   bb=[0 for k in range(h*chnum)]
   u=0
   k1=-1
   k2=chnum-1
   for i in range(h):
     g=gg[i]
     for k in range(k2,k1,-1):
       bb[u]=g&0xff
       g>>=8
       u+=1
     k1+=chnum
     k2+=chnum
   tu,t11,t12,t21,t22 = maurertest(bb)
   print("Maurer's Universal Test for L=8, rho=0.01 (Middle value is the "\
         "test statistic\nand should lie between the other two values):")
   print(t11,tu,t12)


################################################################################


# User specified system parameters and key materials are assumed to be the
# following for the examples below:

logn=8
baseprngm=4
logbasepoolsize=7
prngm=3
logpoolsize=8
maxprngusecount=50
initialrandompriming=10
baserandompriming=20
randompriming=50
initvecblocknum=1
finalvecblocknum=1
ciphertextfilemode=0

# keydata is a list of 2 elements of n/2 bits (n/8 hexs) each, seeddata 1
# element of n/2 bits (here they are arbitrary apparently 'non-random'
# values chosen for the convenience of illustration only).

keydata=[ 0x11111111111111111111111111111111,\
           0x22222222222222222222222222222222 ]
seeddata= 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa


###################################################################################


# Example 1. Normal encryption and decryption.

print()
print("Example 1:")
print()

print("Normal encryption and decryption")
print()

# We assume the sender has the following character string pt as plaintext:

pt="Was sich ueberhaupt sagen laesst, laesst sich klar sagen; und "\
    "wovon man\nnicht reden kann, darueber muss man schweigen."

print("Original plaintext:")
print(pt)
print()

# The sender intializes the system,

initjades()

# encrypts pt, obtaining a ciphertext file ciphermessage.bin  
(ciphertextfilemode
# is chosen above to be 0, thus the file cannot be printed and has to be  
sent as
# such to the recipient.)

encrypt(pt,"ciphermessage")

# and sends it to the recipient.

# The recipient initializes the system,

initjades()

# decrypts the received ciphertextfile ciphermessage.bin  
(ciphertextfilemode is
# 0 as chosen by the sender), assigns the result to pt1 and prints it out.
# Result of authentication check will be automatically reported.

pt1=decrypt("ciphermessage")

print("Plaintext recovered:")
print(pt1)

# If the plaintext message to be encrypted is in an external file (last line
# preferably without 'return'), it can be read into pt with:
# f=open("messagetobesent.txt","r"))
# pt=f.read()
# f.close()
# Similarly the received plaintext message (after decryption is  
performed) can
# be stored into an external file from pt1 with:
# f=open("messagereceived.txt","w")
# f.write(pt1)
# f.close()


# Example 2: Measuring time of encryption/decryption.

print()
print("Example 2:")
print()

nnumb=10000
pt=""
for i in range(nnumb):
   pt+="a"

print("Measuring time of encryption/decryption of a message of",nnumb,\
       "characters")
print()

start=time.clock()
initjades()
encrypt(pt,"ciphertext")
print("encrypt time:",time.clock()-start,"sec")
start=time.clock()
initjades()
pt1=decrypt("ciphertext")
print("decrypt time:",time.clock()-start,"sec")


# Example 3. Perform Maurer's Universal Test on genrandom().

# User may like to employ JADE-S's function genrandom() for other  
usages, e.g.
# for common numerical computations or obtaining PRNs (eventually in  
combination
# with other sources) to generate key streams for other encryption  
schemes, and
# may want to know their statistical properties. Hence the present example.

print()
print("Example 3:")
print()

# Note that theoretically there is a 0.01 chance for the test statistic  
tu to go
# outside of the interval [t11, t12] (under the assumption that the sequence
# being tested is random).

print("Testing pseudo-radnom numbers generated by genrandom()")
print()

# Initialize the system.

initjades()

# Determine number of PRNs (words) needed for the test.

h=qqkkp1//chnum
if h*chnum<qqkkp1:
   h+=1

# Obtain the PRNs.

gg=genrandom(h)

#Perform the test.

maurertestresult(h,gg)


# Example 4. Perform Maurer's Universal Test on ciphertext obtained from
# a plaintext of the form "aaa........".

# This is intended to show the randomness of the result of encrypting an
# absolutely non-random plaintext. (A perfectly random plaintext on the  
other
# hand would have had the same frequency, 1/26, of occurence for all  
characters
# of the alphabet.)

print()
print("Example 4:")
print()

print("Testing the result of encrypting an absolutely non-random plaintext")
print()

# Since ciphertext in decimal integers will be needed, we have to reset the
# parameter ciphertextfilemode to 1 (it was chosen above to be 0).

ciphertextfilemode=1

# Initialize the system.

initjades()

# Determine number of words of the form "aaa..." needed for the test.

h=qqkkp1//chnum
if h*chnum<qqkkp1:
   h+=1

# Obtain the plaintext.

r=""
for i in range(chnum):
   r+="a"
pt=""
for i in range(h):
   pt+=r

# Perform encryption.

encrypt(pt,"aaamessage")

# Obtain the corresponding ciphertext (decimal integers in nclist).

ciphertextfile="aaamessage.txt"
fp=open(ciphertextfile,"r")
ncliststrlist=fp.read().split()
nclist=[]
for i in range(len(ncliststrlist)):
   nclist+=[int(ncliststrlist[i])]

# Perform the test.

maurertestresult(h,nclist)



################################################################################
################################################################################



#########   Section 3.  Miscellaneous Notes.



# The code of JADE-S assumes that the sender supplies his message in a  
variable
# of Python and the recipient retrieves the same also from a variable of  
Python.
# See commments in Sec.2. Ex.1 for situations where the sender has his  
message
# in a file or the recepient needs to obtain the same in a file.

# The user-given key materials, keydata and seeddata, are numerical integer
# values, i.e. decimal or, as we prefer, hexadecimal integers, as shown  
in Ex.1
# of Sec.2. If text, i.e. alphanumerical, key materials are given, these  
may be
# converted to the formats required by JADE-S in the following way:
# initjades()
# str="abc123"
# g=pack(str)
# print(g,hex(g))

# In case arbitrary binary information is to be processed, this may be  
supplied
# in n-bit blocks as elements of the list nplist to be encrypted to the list
# nclist by JADE-S. The code modification necessary for this is evident, see
# encrypt() and decrypt().

# Users employing non-English keyboards may obtain with input of non-English
# symbols a message from Python: "... IDLE will convert it to UTF-8".  
Click on
# OK in this case. Though not tested, there seems to be no reason why JADE-S
# shouldn't work also with non-European languages. Note that JADE-S  
needs Python
# 3.x.

# To obtain a binary file of m PRNs generated by genrandom() one could use:
# initjades()
# g=genrandom(m)
# fp=open("mfile.bin","wb")
# for i in range(m):
#   fp.write(g[i].to_bytes(chnum,byteorder='big'))
# fp.close()

# For a chosen block size of n bits, the key material (keydata and  
seeddata) has
# a total size 1.5*n bits. However, if keydata (of n bits) has enough  
entropy to
# defeat brute-forcing, then seeddata evidently need not necessarily be  
secret.
# (That for the larger values of n allowed in JADE-S the key material  
generally
# needs only a correspondingly lower entropy density is clearly of  
advantage in
# practice.) In fact it could be favourable in practice for the key  
management
# work to have a well-guarded keydata of sufficient entropy and use it  
for some
# longer time period, while the seeddata is always variable accross the  
sessions
# and depends in some rather simple way on certain session specific data,
# including date, time, message serial number, etc. One could use JADE-S  
and a
# master-keydata (with the corresponding seeddata e.g. involving a certain
# month, if the keydata to be used in that month is to be obtained) to  
process
# an agreed upon text and use the value of nclist[-finalvecblocknum:]  
(see enc()
# with the system parameter finalvecblocknum set to the desired length)  
after
# execution of encrypt() to supply the keydata needed, since it is by  
nature a
# good hash value of the plaintext for fixed values of system parameters and
# key materials employed. Further there could be a hierarchy of  
master-keydata,
# depending on usage, validity time, etc. and stemming all from a grand
# master-keydata in the way described. A master-keydata could be  
obtained by our
# targeted users, if necessary, through throwing 8-sided dice, this  
being only a
# one-time drudgery, and exchanged with the communication partners via
# steganography, employing the present author's EMAILSTEGANO (available from
# http://s13.zetaboards.com/Crypto/topic/6939954/1 /). (With 6-sided dice one
# could get 2 bits from [1,4] and 1 bit from [5,6].) For gathering  
entropy from
# hardware, see  
https://www.irisa.fr/caps/projects/hipsor/old/files/HAVEGE.pdf
# Evidently there can exist no single general recipe of best performing key
# management that is applicable in all different concrete situations in
# practice and the user must exercise his own prudence, vigilence and  
ingenuity.

# The present author has a code TEXTMIXING (available from
# http://s13.zetaboards.com/Crypto/topic/6936496/1 /) that mixes several  
pieces
# of given texts to a resulting text of higher entropy density.

# JADE-S treats the bits of an entire block of e.g. 256 bits as a single  
integer
# and directly performs certain arithmetic and bit operations on it. See  
enc()
# and dec(). This incurs essential trade-offs in terms of efficiency.  
Further,
# Python code is not compiled but interpreted and in the present coding  
priority
# has always been given to readability rather than to runtime efficiency.
# Benchmarking shows nevertheless that a message of 10000 characters,  
which is
# sufficiently long for normal communications of common private persons  
(who are
# our targeted users), can be processed on a common modern PC (with all  
variants
# of the system parameters logn and logpoolsize) in less than 0.5 sec.,  
which is
# clearly acceptable.

# JADE-S uses a scheme of PRN generation that distinguishes itself from the
# common schemes in that it makes use not of a single PRNG but of a pool of
# constituent PRNGs that are pseudo-randomly selected (by themselves) for
# activation, thus rendering its analysis inherently hard. The outputs  
of these
# constituent PRNGs are post-processed in a sophisticated way to further  
block
# any sequence prediction attempts of the analyist, see genrandom().  
genrandom()
# accepts feedback signals so that functions employing it could through  
feedback
# (via setting the global variable prngfeedback) dynamically influence the
# sequence of PRNs obtained and thus indirectly achieve dynamics in the  
results
# computed by the functions. (JADE-S doesn't make use of prngfeedback,  
though.)
# Use-counts are kept so that one can limit the life-time of the PRNGs  
in the
# pool to deliberately enhance the hardness of analysis. Note also that in
# JADE-S all PRNs are only indirectly used so that these are never directly
# accessible to the analyst to work on. (Contrast this with the common  
stream
# encryption).

# The present author experimentally found that the use of an accumulator
# improves the statistical qualities of the output of the PRNGs of the  
type used
# in JADE-S. The combination of an accumulator and a buffer (which is also
# beneficial statistically) has the additional effect of rendering the  
analysis
# hard. See genbaserandom() and genrandom(). In genrandom(), which  
ultimately
# delivers the PRNs for application use, a cascade of an accumulator and two
# buffers is employed for achieving superior performance.

# JADE-S is very richly parametrized, in particular the user can choose  
block
# lengths ranging from 128 to 1024 bits. Check for authentication  
(integrity) is
# natively integrated and always performed, with the number of  
authentication
# blocks arbitrarily specifiable by the user. While the common block ciphers
# have a number of rounds in order to attain their desired strength,  
JADE-S has
# only one round, iterations of our kind of computations (see enc()) being
# considered superfluous for gaining security.

# JADE-S shares with JADE 2.0.3 the same elaborate PRN generation scheme  
but is
# simpler in design concepts in the proper encryption/decryption processing
# part. It is thus easier to be understood and consequently to be preferred.

# It is important to be always conscious of the fact that in general a  
cipher is
# only one component in the entire chain of computer processing that is
# destined/meant to protect user's privacy and that unfortunately a chain is
# only as strong as its weakest link. In fact IT security risks are  
omnipresent.
# Thus, depending on the actual environment, one may have to consider  
also, for
# instance, human factors and potential backdoors in proprietary
# (non-opensource, blackbox) software that are involved in the  
management and
# processing of digital signatures, sophisticated malware (e.g. Stuxnet and
# its descendents, trojans introduced by governmental agencies) that steal
# plaintext files, WLAN insecurities, key loggers, Tempest attacks, etc.  
etc.
# The book Security Engineering of R. Anderson covers a lot of practical IT
# security issues. There is, among others, an entire chapter on emission
# security.

# That backdoors can be implanted into RSA-key generation could be shown  
with
# elementary number theory. The present author has repeatedly attempted to
# call the attention of a number of responsible persons and authorities  
to this
# serious source of potential risks intimidating our society, but  
absolutely to
# no avail to date. It seems that these are all taking the strategy of  
"burying
# one's head in the sand". On the other hand, this issue, though extremely
# grave, is of course of no direct concern for our targeted users, whose
# communications are secured by JADE-S through authenticated strong  
end-to-end
# symmetric encryption without involving the public key infrastructure  
(PKI) at
# all, assuming that the transfer of encrypted messages via emails  
functions.

# Note that backdoors (in both software and hardware) implanted by mafias or
# foreign secret agencies may remain dormant (thus undectable from the  
outside)
# until the moment arrives that is favourable for the bad guys to create a
# devasticating chaos (via either "time-bomb" or, more sophistically, remote
# commands) to e.g. the critical infrastructures of a nation. In his book
# Cyberwar (in German, ISBN 978-3-941841-23-9) S. Gayken convincingly  
argues for
# "Entnetzung" ("de-networking") as a necessary defense measure for  
protecting
# the computer networks of sensible critical systems. (He also writes:
# "Commercially produced components cannot be trusted. Especially not,  
if that's
# from global enterprises or firms from abroad".) By simple logic, if  
one's home
# network is "really" to be well protected, then the same rigorous measure
# certainly should be taken. That would imply in our understanding  
having one
# extra computer that is permanently isolated from the Internet and  
transferring
# data to and from it via printouts/scanning (since USB devices are  
presumably
# hard to to be protected from malware infections) and taking care of  
risks from
# eventually conceivable emission attacks from the environment as well.

# That information privacy needs active and careful protection measures  
is once
# again stressed by recent news from The Guardian about Prism, Tempora, etc.

# Another encryption software of the present author is SHUFFLE2,  
obtainable from
# http://s13.zetaboards.com/Crypto/topic/6925232/1/

Site Timeline