Cryptography-Digest Digest #815, Volume #8 Wed, 30 Dec 98 09:13:07 EST
Contents:
WEAK4-EX -- Another Poorman's 56-bit Data Encryption Algorithm (long) (Mok-Kong Shen)
New Book "The Unknowable" ([EMAIL PROTECTED])
----------------------------------------------------------------------------
From: Mok-Kong Shen <[EMAIL PROTECTED]>
Subject: WEAK4-EX -- Another Poorman's 56-bit Data Encryption Algorithm (long)
Date: Wed, 30 Dec 1998 13:49:07 +0100
Recently I have designed two 56-bit algorithms, WEAK2-EX and WEAK3-EX,
with which the user can arbitrarily scale up the processing time and
the algorithm initialization time respectively such that the expected
average time for brute forcing can be rendered beyond any practically
infeasible bounds. (The number of rounds in these algorithms can be
suitably chosen such that brute forcing would be the only viable means
of analysis.) Thus, in exchange for some tolerable higher time
expenditure, the user can manage to obtain adequate security despite
the severe limitation posed by the forthcoming 56-bit key length
restriction.
The present algorithm, WEAK4-EX, is based on the same paradox-sounding
paradigm 'security through inefficiency' as its two predecessors but
extends the 'inefficiency' into an additional 'dimension', namely the
volume of the ciphertext. It has in total three user choosable scaling
factors of processing time. The first is the same as one of the two
employed in WEAK2-EX and controls the time rate of pseudo-random
number generation of the PRNG used. The second scaling factor
determines the number of pseudo-random bits thus obtained that are to
be XORed with each single bit of the plaintext. (In WEAK4-EX the
plaintext is treated as a bit stream.) The third scaling factor
determines (approximately) by how much the ciphertext is to be
expanded through filling it with pseudo-random bits at positions that
are determined by the PRNG.
Let input() designate the function delivering the next bit from the
plaintext and scf2 and scf3 be the second and third scaling factor
mentioned above. Then the encryption with WEAK4-EX can be conceptually
(not 'strictly speaking', see below) described by the following very
simple probabilistic automaton, where the function pbit(m) denotes the
result of XORing of m*32 pseudo-random bits obtained from the PRNG,
i.e. their parity:
do
with probability 1/scf2:
output( input() XOR pbit(scf3) );
with probability 1 - 1/scf2:
output( pbit(1) );
od;
In the implementation we use our PRNG (not a TRNG) to determine the
transition of the automaton. Thus the actual process is not random
but only a 'simulation' and is in fact deterministic, being governed
by the seed of the PRNG. For otherwise the receiver of the message
would have a hard task to do the decryption. Thus WEAK4-EX is a
pseudo-randomized encryption. It is not a (true) randomized
encryption such as the time-honoured but apparently now disfavoured
homophone cipher, where the decision of the choice of the homophones
can be made e.g. through casting of dices. (I suggested recently
though that homophones could once again be interesting in the light
of the 56-bit restriction.)
Through the (simulated) probabilistic nature of the algorithm the
analyst has the essential difficulty to identify which bits of the
ciphertext are information-bearing, i.e. encrypted plaintext bits,
and which are the filling nonsense bits. Since the information-bearing
bits are themselves obtained through XORing the plaintext bit with a
large number (some multiples of 32) of pseudo-random bits, brute
forcing would be the only viable method of attack if the factors scf2
and scf3 are adequately chosen. The price that the user has to pay
through the scaling factor scf3 is that the ciphertext is about scf3
times as large as the plaintext and hence incurs correspondingly
higher transmission expenditure. However, if the plaintext is fairly
short, which is very often likely to be the case in a poorman's
environment, such expansion of the ciphertext, if not carried to the
extreme, may well be sensible. In other cases, one can simply set
scf3=1 and exclusively employ the other two scaling factors to achieve
a sufficient level of security.
An implementation in Fortran 90 is attached below. A binary
executable file for PC can be downloaded via my main Web page.
I am indebted to TPS for discussions leading to the present work.
Constructive critiques, comments and suggestions for improvements
are sincerely solicited.
M. K. Shen
=============
NOTE: The program codes of WEAK2-EX and WEAK3-EX have been revised
(with an error reported by CWL and CK corrected). In the zip-file
for download, all three encryption programs and their binaries are
included.
==================================================================
c The design of WEAK4-EX is explained in the text of the article
c introducing the present program code:
c
c http://www.stud.uni-muenchen.de/~mok-kong.shen/#paper16
c
c See also:
c
c http://www.stud.uni-muenchen.de/~mok-kong.shen/#paper13
c
c http://www.stud.uni-muenchen.de/~mok-kong.shen/#paper15
c
c
c Notes:
c
c 1. This program has been designed to be fairly simple in programming
c logic. It should be independently implementable from scratch in
c 2 to 5 hours with average programming experience.
c
c 2. Pseudo-random generation in WEAK4-EX is the same as that of
c the standard PRNG in WEAK3-EX. See
c http://www.stud.uni-muenchen.de/~mok-kong.shen/#paper13
c
c 3. The implementation is scalable. The arbitrarily chosen maximum
c value settings (Fortran parameter statements) may be trivially
c changed, if needed. Also the file record length may be changed
c if a couple of Fortran format statements are correspondingly
c modified. The parameter statement for mgnseed, however, cannot
c be modified.
c
c 4. This is a pure stream encoding scheme. The user is reminded of
c the critical importance of good key management.
c
c 5. For the buffer length etc. the brackets in input prompts
c indicate the valid ranges. The user should choose values
c suitable for his applications. It is advisable not to always use
c the same set of such input values but to vary the configuration
c of the system over time. For processing time scaling factors see
c the text of the article introducing this program.
c
c 6. The implementation is for 32 bit processors. A check should be
c be made in case communication partners use 32 bit processors
c of different architechture.
c
c 7. The user is strongly advised (not to blindly trust the integrity
c of codes written by third persons and therefore) to read and
c critically examine our code before using it.
c
c Program written (copyright) by M. K. Shen on 30th December 1998.
c Tested on PC with INTEL Pentium II using the NAG FTN90 compiler.
c
c
c This program may be freely copied (but only in its entirety),
c distributed and used for any civil (i.e. personal, academic or
c commercial) purposes conforming to the law, subject to the single
c condition that in no case the author is to be held responsible for
c any eventual damages in connection with its use. Any other usage is
c herewith explicitly disallowed.
c
c
c Critiques, comments and suggestions for improvements are sincerely
c solicited. Author's addresses:
c Postal: M. K. Shen, Postfach 340238, D-80099 Muenchen, Germany
c e-mail: [EMAIL PROTECTED] (subject to change)
c
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c
program weak4ex
c
implicit integer(a-z)
c
parameter(maxint=2147483647)
c
c Number of words, number of bytes and number of hexadecimal digits
c in a record (of file type 1)
parameter(nword=20,nbyte=nword*4,nhex=nword*8)
c
c Dimension of array randb
c randbdim must be divisible by 3.
parameter(randbdim=900)
c
parameter(mgnseed=2)
c
c
common /rbblk/randb(randbdim),rbi
integer gseeds(mgnseed)
c
integer aa(nbyte),bb(nword),cc(nword)
character *12 filein,fileout
character *(nbyte) rec
character *(nhex) rec1
character *14 key
character kc
real t0,t1
real sprng,rscf3
c
c
print *, "WEAK4-EX --- ",
1 "Another Poorman's 56-bit Data Encryption Algorithm "
print *,'Version : 30th December 1998'
print *,'Copyright : Mok-Kong Shen, Munich, Germany'
print *,' '
c
print *,'give mode (1 = encryption, 2 = decryption)'
read *,mode
call rgcheck('mode ',mode,1,2)
c
c Plaintext file has
c type 1 if 80 ASCII characters per record
c type 2 if 80 hexadecimal digits ([0,9],[A,F]) per record and
c there are even number of records
c Ciphertext file always has type 2
c Thus information in one record of file type 1 corresponds to two
c records of file type 2. It is an error if the record number of file
c type 2 is odd.
c Note that, if the input file is not generated by a program but, as
c is normally the case, prepared with a text editor, then the last
c line must be terminated by pressing the return key (but nothing else
c following that, including further pressing of the return key).
c Otherwise, the procesing will be in error.
c Note that file type 1 is restricted generally to contain printable
c characters only (because of possible difficulties caused by some
c non-printable byte values) while file type 2 can contain any binary
c information.
c Thus both types of files can, for example, be directly transported
c via e-mail without requiring additional transformations.
c The file type of plaintext file in encryption and decryption
c should be the same.
c Validity of content of input file is not checked.
c
print *,'give input file name'
read *,filein
if (mode .eq. 1) then
print *,'give input file type [1, 2] ',
1 '(1 = ASCII, 2 = hexadecimals)'
read *,ftype
call rgcheck('ftype ',ftype,1,2)
end if
print *,'give output file name'
read *,fileout
if (mode .eq. 2) then
print *,'give output file type [1, 2] ',
1 '(1 = ASCII, 2 = hexadecimals)'
read *,ftype
call rgcheck('ftype ',ftype,1,2)
end if
c Range check of gnseed, gseeds, gbufflen, gwichs is
c taken care of by the subprogram initsprng
print *,'give 56-bit key in 14 hexadecimal digigts',
1 ' (0-9 or A-F in upper case)'
read *,key
do i=1,14
kc=key(i:i)
if (.not. ((lge(kc,'0') .and. lle(kc,'9')) .or.
1 (lge(kc,'A') .and. lle(kc,'F')))) then
print *,'Error : key digit ',kc,
1 ' is out of ranges [0-9] and [A-F]'
stop
end if
end do
read(key,260) gseeds(1),gseeds(2)
gnseed=2
print *,'give buffer length of standard PRNG [1, 2000]'
read *,gbufflen
print *,'give first processing time scaling factor ',
1 '[2, 2147483646]'
print *,'(this determines the number of times to perform ',
1 'addition mod 1'
print *,' operations in the standard PRNG. larger value leads ',
1 'to correspondingly'
print *,' longer processing time)'
c gwichs determines the number of times to perform addition mod 1
c operations (device of Wichmann and Hill).
read *,gwichs
print *,'give second processing time scaling factor ',
1 '[2, 2147483646]'
print *,'(this determines the number of multiples of 32 ',
1 'pseudo-random bits to be'
print *,' XORed with an information bit. larger value leads to ',
1 'correspondingly'
print *,' longer processing time)'
read *,scf2
call rgcheck('scf2 ',scf2,2,maxint-1)
print *,'give third processing time scaling factor ',
1 '[1, 5000]'
print *,'(this determines the (approximate) ratio of volume of ',
1 'ciphertext to'
print *,' plaintext, based on plaintext type = 2. (doubled for ',
1 'plaintext type = 1)'
print *,' larger value leads to',
1 ' correspondingly longer processing time)'
read *,scf3
call rgcheck('scf3 ',scf3,1,5000)
rscf3=1.0/scf3
c
c Subprogram clock@ is specific to NAG FTN 90 compiler
c Substitution with another name may be needed for other compilers
call clock@(t0)
c
c
c Initialization of PRNG
call initsprng(gseeds,mgnseed,gnseed,gbufflen,gwichs)
c Open files
open(10,file=filein)
open(20,file=fileout)
c Initialize index to array randb for call of cmprnword
rbi=randbdim
c Number of records processed
recn=0
c
210 format(a)
220 format(80z2.2)
230 format(20z8.8)
260 format(2z7.7)
c
c
c Set number of records written, clear first word for output and
c initialize pointers to cc
wrecn=0
cc(1)=0
cwi=1
cbi=31
goto (300,400) mode
c
c
c Encryption
c
c
c Input 1 or 2 plain text record depending on ftype
300 if (ftype .eq. 1) then
c Read 1 record of ASCII characters
read(10,210,err=810,end=310) rec
recn=recn+1
c Convert to integers
do i=1,nbyte
aa(i)=iachar(rec(i:i))
end do
c Convert to hexadecimal digits
write(rec1,220) aa
else
c Read 2 records of hexadecimal digits
read(10,210,err=810,end=310) rec1(1:nbyte)
read(10,210,err=810,end=820) rec1(nbyte+1:nhex)
recn=recn+2
end if
c
c Convert to binary words
read(rec1,230) bb
c Initialize pointers to word and bit of bb to be processed
bwi=1
bbi=31
c
c With probability of 1/scf3 will a bit from plaintext get processed,
c otherwise some pseudo-random bit is output.
do
if (sprng() .lt. rscf3) then
c Encrypt the information bit with the parity of scf2*32 pseudo-random
c bits from array randb
u=ieor(ibits(bb(bwi),bbi,1),pbit(scf2))
infb=1
else
c Get the parity of 32 pseudo-random bits from array randb
u=pbit(1)
infb=0
end if
if (u .ne. 0) cc(cwi)=ibset(cc(cwi),cbi)
cbi=cbi-1
if (cbi .lt. 0) then
if (cwi .eq. nword) then
c Convert to hexadecimal digits in rec1
write(rec1,230) cc
c Write out 2 cipher text records in hexadecimal format from rec1
write(20,210) rec1(1:nbyte)
write(20,210) rec1(nbyte+1:nhex)
wrecn=wrecn+2
cwi=1
else
cwi=cwi+1
end if
cc(cwi)=0
cbi=31
end if
if (infb .ne. 0) then
bbi=bbi-1
if (bbi .lt. 0) then
if (bwi .eq. nword) goto 300
bwi=bwi+1
bbi=31
end if
end if
end do
c
310 if (.not. (cwi .eq. 1 .and. cbi .eq. 31)) then
c Filling the rest of array cc with bits consisting of the parity of
c groups of 32 pseudo-random bits from array randb and output cc
do j=cbi,0,-1
u=pbit(1)
if (u .ne. 0) cc(cwi)=ibset(cc(cwi),j)
end do
do i=cwi+1,nword
cc(i)=0
do j=31,0,-1
u=pbit(1)
if (u .ne. 0) cc(i)=ibset(cc(i),j)
end do
end do
c Convert to hexadecimal digits in rec1
write(rec1,230) cc
c Write out 2 cipher text records in hexadecimal format from rec1
write(20,210) rec1(1:nbyte)
write(20,210) rec1(nbyte+1:nhex)
wrecn=wrecn+2
end if
c
print *,recn,' records processed and ',wrecn,' records ',
1 'written to ',fileout
goto 900
c
c
c Decryption
c
c
c Input 2 cipher text records in hexadecimal format into rec1
400 read(10,210,err=810,end=410) rec1(1:nbyte)
read(10,210,err=810,end=820) rec1(nbyte+1:nhex)
recn=recn+2
c
c Convert to binary word
read(rec1,230) bb
c Initialize pointers to word and bit of bb to be processed
bwi=1
bbi=31
c
c See comments for encryption at the corresponding location
do
if (sprng() .lt. rscf3) then
c Decrypt the information bit with the parity of scf2*32 pseudo-random
c bits from array randb
u=ieor(ibits(bb(bwi),bbi,1),pbit(scf2))
if (u .ne. 0) cc(cwi)=ibset(cc(cwi),cbi)
cbi=cbi-1
if (cbi .lt. 0) then
if (cwi .eq. nword) then
c Convert to hexadecimal digits in rec1
write(rec1,230) cc
c
c Write out 1 or 2 plain text record depending on ftype
if (ftype .eq. 1) then
C Convert to integers
read(rec1,220) aa
C Convert to ASCII characters
do i=1,nbyte
rec(i:i)=achar(aa(i))
end do
C Write out 1 record of ASCII characters
write(20,210) rec
wrecn=wrecn+1
else
c Write out 2 records of hexadecimal digits
write(20,210) rec1(1:nbyte)
write(20,210) rec1(nbyte+1:nhex)
wrecn=wrecn+2
end if
c
cwi=1
else
cwi=cwi+1
end if
cc(cwi)=0
cbi=31
end if
else
c Discard 32 bits (1 word) from array randb
c (we don't need to compute the parity)
if (rbi .eq. randbdim) then
call randblock
rbi=1
else
rbi=rbi+1
end if
end if
bbi=bbi-1
if (bbi .lt. 0) then
if (bwi .eq. nword) goto 400
bwi=bwi+1
bbi=31
end if
end do
c
410 print *,recn,' records processed and ',wrecn,' records ',
1 'written to ',fileout
goto 900
c
c
810 print *,'error in reading ',filein
goto 900
820 print *,'error: ',filein,' does not have even number of records'
c
c
900 call clock@(t1)
print *,'processing time = ',t1-t0,' sec'
end
c
c
cccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccc
c
c This is adapted from WEAK3-EX with uprng replaced by sprng and
c change of parameters.
c
c Filling the array randb with pseudo-random bits.
c
subroutine randblock
implicit integer(a-z)
parameter(randbdim=900)
parameter(cc=2**24,ms3=255,ms2=ms3*256,ms1=ms2*256)
common /rbblk/randb(randbdim),rbi
real sprng
k=0
c randbdim is divisible by 3
do i=1,randbdim/3
c Obtain 24 bits from each call to uprng. 4 calls are needed to
c get 3 words of 32 bits.
c There are 24 bits in the mantissa part of a real number of 32 bit
c processors. Hence it is not sensible to obtain more than 24 bits
c from a pseudo-random number delivered by sprng.
h1=sprng()*cc
h2=sprng()*cc
h3=sprng()*cc
h4=sprng()*cc
randb(k+1)=ior(ishft(h1,8),ishft(h2,-16))
randb(k+2)=ior(ishft(h2,16),ishft(h3,-8))
randb(k+3)=ior(ishft(h3,24),h4)
k=k+3
end do
end
cccccccccccccccccccccccccccccc
c
c Obtaining the parity (i.e. XOR of all bits) of scf*32 bits from the
c array randb
c The global varialbe rbi is to be initialized to randbdim before
c first call of this function.
c
integer function pbit(scf)
implicit integer(a-z)
parameter(randbdim=900)
common /rbblk/randb(randbdim),rbi
s=-1
do i=1,scf
if (rbi .eq. randbdim) then
call randblock
rbi=1
else
rbi=rbi+1
end if
u=randb(rbi)
do j=0,31
if (btest(u,j)) s=-s
end do
end do
if (s .lt. 0) then
pbit=0
else
pbit=1
end if
end
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c The following set of subprograms are taken from the implementation
c of WEAK3-EX.
c
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c Check whether k is in [k1, k2].
c
subroutine rgcheck(string,k,k1,k2)
character (*) string
if (k .lt. k1 .or. k .gt. k2) then
print *,'Error : ',string,k,' is out of range [',k1,',',k2,']'
stop
end if
end
cccccccccccccccccccccccccccccc
c
c Copying of seeds and initialization of pointers and filling of the
c shuffling buffer of the output of the multiple seed PRNG parkms.
c After this is called, the standard PRNG sprung can be used.
c Copying is done to render the set of Fortran subprograms independent
c of the main program, thus facilitating their employment by main
c programs written in other languages than Fortran.
c This subprogram is not directly called by the user.
c
subroutine initsprng(gseeds,mgnseed,gnseed,gbufflen,gwichs)
implicit integer(a-z)
parameter(maxint=2147483647)
parameter(mbufflen=2000)
integer gseeds(mgnseed)
common /msp/seeds(3),sqi
common /bds/buffer,bufflen,buffi,wichs
real buffer(0:mbufflen-1)
real parkecuyer
c Exactly 2 elements required in gseeds
call rgcheck('gnseed ',gnseed,2,2)
bufflen=gbufflen
call rgcheck('gbufflen ',bufflen,1,mbufflen)
wichs=gwichs
c We require that wichs be at least 2
call rgcheck('gwichs ',wichs,2,maxint-1)
c Check that each element in gseeds is 28 bits
do i=1,gnseed
call rgcheck('gseeds ',gseeds(i),1,2**28-1)
end do
c In parkecuyer the PRNG of Park and Miller needs 1 seed while that
c of L'Ecuyer needs 2 seeds. These are arbitrarily obtained from
c gseeds as follows:
seeds(1)=gseeds(1)
seeds(2)=gseeds(1)
seeds(3)=gseeds(2)
c Initialization of pointer used in parkecuyer
sqi=0
c Initialization of pointer of buffer used in sprng
buffi=0
c Filling of buffer
do i=0,bufflen-1
buffer(i)=parkecuyer()
end do
end
cccccccccccccccccccccccccccccc
c
c Standard PRNG.
c This corresponds to sprng of WEAK3-EX
c
c Algorithm of Bays and Durham is used to shuffle the output of parkms.
c Method of Wichmann and Hill is used to combine wichs successive
c numbers output from the shuffling buffer to form the output of sprng.
c Returns a pseudo-random number in [0,1).
c Requires initialization by initsprng.
c
real function sprng()
implicit integer(a-z)
parameter(mbufflen=2000)
common /bds/buffer,bufflen,buffi,wichs
real buffer(0:mbufflen-1)
real parkecuyer,rr,rr2
c Obtain one number from the shuffling buffer
c Algorithm of Bays and Durham
rr=buffer(buffi)
buffer(buffi)=parkecuyer()
buffi=rr*bufflen
c Obtain further numbers from the shuffling buffer and combine
do i=2,wichs
c Algorithm of Bays and Durham
rr2=buffer(buffi)
buffer(buffi)=parkecuyer()
buffi=rr2*bufflen
c Addition of rr and rr2 mod 1 (device of Wichmann and Hill)
rr=rr+rr2
if (rr .ge. 1.0) rr=rr-1.0
end do
c Avoid rounding to 1.0.
if (rr .ge. 0.999999) rr=0.999999
sprng=rr
end
cccccccccccccccccccccccccccccc
c
c If sqi=0 the PRNG of Park and Miller is called (seed(1))
c If sqi=1 the PRNG of L'Ecuyer is called (seed(2) and seed(3))
c sqi ensures that the two PENGs are called alternatingly.
c
c This is not directly called by the user.
c
c Returns a pseudo-random number in [0,1)
c The global variable sqi is to be initialized to 0 before first
c call of this function.
c All seeds must be in [1, 2^31-2].
c
real function parkecuyer()
implicit integer(a-z)
parameter(mbufflen=2000)
common /msp/seeds(3),sqi
real random
c
if (sqi .eq. 0) then
sqi=1
c Use PRNG of Park and Miller
seed=seeds(1)
c
c Algorithm of Park and Miller
hi=seed/127773
lo=mod(seed,127773)
test=16807*lo-2836*hi
if (test .gt. 0) then
seed=test
else
seed=test+2147483647
end if
random=real(seed)/2147483647
c Avoid rounding to 1.0.
if (random .ge. 0.999999) random=0.999999
c
c Store back new seed value
seeds(1)=seed
else
sqi=0
c Use PRNG of L'Ecuyer
s1=seeds(2)
s2=seeds(3)
c
c Algorithm of L'Ecuyer
a1=53668
a2=52774
b1=40014
b2=40692
c1=12211
c2=3791
m1=2147483563
m2=2147483399
q1=s1/a1
s1=b1*(s1-a1*q1)-c1*q1
if (s1 .lt. 0) s1=s1+m1
q2=s2/a2
s2=b2*(s2-a2*q2)-c2*q2
if (s2 .lt. 0) s2=s2+m2
z=s1-s2
if (z .lt. 1) z=z+2147483562
random=z*4.656613e-10
c Avoid rounding to 1.0.
if (random .ge. 0.999999) random=0.999999
c
c Store back new seed value
seeds(2)=s1
seeds(3)=s2
end if
c
c Return random to caller.
parkecuyer=random
end
------------------------------
From: [EMAIL PROTECTED]
Subject: New Book "The Unknowable"
Date: Wed, 30 Dec 1998 12:42:21 GMT
Hi folks, this is to let everyone know that I've
just finished a new book, "The Unknowable".
It's a prequel/sequel to my book on "The Limits
of Mathematics". "The Unknowable" is available
in html and in postscript at these two URL's:
http://www.umcs.maine.edu/~chaitin/unknowable
http://www.cs.auckland.ac.nz/CDMTCS/chaitin/unknowable
Best wishes for 1999,
GJC
============= Posted via Deja News, The Discussion Network ============
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
------------------------------
** FOR YOUR REFERENCE **
The service address, to which questions about the list itself and requests
to be added to or deleted from it should be directed, is:
Internet: [EMAIL PROTECTED]
You can send mail to the entire list (and sci.crypt) via:
Internet: [EMAIL PROTECTED]
End of Cryptography-Digest Digest
******************************