Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.programming > #3623

NEOCLASSIC, An encryption scheme based largely on use of well-known classical crypto techniques

Path csiph.com!usenet.pasdenom.info!news.albasani.net!.POSTED!not-for-mail
From Mok-Kong Shen <mok-kong.shen@t-online.de>
Newsgroups comp.programming
Subject NEOCLASSIC, An encryption scheme based largely on use of well-known classical crypto techniques
Date Thu, 11 Jul 2013 11:41:41 +0200
Organization albasani.net
Lines 494
Message-ID <krlukd$js2$1@news.albasani.net> (permalink)
Mime-Version 1.0
Content-Type text/plain; charset=ISO-8859-15; format=flowed
Content-Transfer-Encoding 7bit
X-Trace news.albasani.net g91aSSQ3DaZ1xy5Wn4RP7aupEYnOkrB1ihL0VzFlhbkBubKRa8VOHZNvW9EJEG/taGq3c3ckXm8qQ97tT85oxOzXFFmdxDdVO/BREiLPywwb1z0v14uknkiWVtS1Sx1T
NNTP-Posting-Date Thu, 11 Jul 2013 09:41:33 +0000 (UTC)
Injection-Info news.albasani.net; logging-data="CmoM48rw1YYRIbDxXMl02VCpncS5zTxzAPofnIRdQwIBZZt3e3K78ZIWUavcFXz7XvFxnBm32upD2YBsxwaAY+VtE3O6xhmS63sP4j6s38ORkagwNBeCDEGoA0mUbMlC"; mail-complaints-to="abuse@albasani.net"
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20130620 Thunderbird/17.0.7
Cancel-Lock sha1:vsQa6D5PrinVfiLP41lDqbzLeBg=
Xref csiph.com comp.programming:3623

Show key headers only | View raw


# NEOCLASSIC, A simple versatile encryption scheme (with authentication) 
based
# largely on the straightforward use of well-known classical crypto 
techniques.


# Prologue:

# Having during the years designed a small number of encryption 
algorithms, I
# am increasingly convinced that no practical encryption algorithm could be
# "absolutely" secure in the "strict" sense of the word and hence the 
quest for
# such is futile from the very beginning. In fact, there exist rather strong
# critiques [1] on the so-called proofs of crypto-security. Thus what 
seems to
# be desirable in practice will be the availability of a sufficiently large
# number of diverse kinds of sufficiently strong (preferably also easy for
# the common users to understand, verify and use) encryption algorithms 
that,
# when appropriately employed (eventually in combinations, i.e. with 
different
# ciphers working in tandem), are intuitively safe with a satisfactory 
"factor
# of safety" in relationship to the power of attacks that one's opponent
# "presumably" has in hand. One is IMHO therefore defacto always doing some
# gambling in the crypto practice. But this is actually also the case 
everywhere
# in real life, e.g. in the practice of medicine. In releasing the present
# software to the public, I am certainly conscious that it is definitely not
# absolutely secure but can only be hopefully practically secure, namely 
when
# the user chooses sufficiently conservative values for its system 
parameters.
# A deplorable dilemma I am facing as designer is however that, in 
distinction
# to e.g. pharmacy, there are in crypto barely any practical tests of the
# nature of those pertaining to drugs to determine the right dosage for
# administration to the patients. Since I could hardly provide any sensible,
# ubiquitously valid, guidances to the selection of the system parameters, I
# am obliged to warn the potential users of my software at the very 
beginning:
# The user is himslef responsible for the appropriate choice of the system
# parameters of this software in any actual applications. On the other hand,
# it is intuitively clear that higher values of the system parameters chosen
# should, in general, imply higher security, assuming that the user also 
take
# sufficient care to ensure the fulfillment of all other security measures
# that are required in practice of the applications in which NEOCLASSIC is
# selected to be utilised.

# [1] N. Koblitz, The uneasy relationship between mathematics and 
cryptology.
# Notices AMS, vol.54, 2007, pp.972-979, 1454-1456, vol.55, 2008, pp.6-7.


# NEOCLASSIC is a Python code for encryption processing that performs an
# arbitrary user-chosen number of rounds of pseudo-random transposition and
# substitution determined by a user-given session-key utilizing Python's
# built-in pseudo-random number generator (PRNG). Excepting the use of 
PRNG (and
# the use of computer), everything in NEOCLASSIC is straightforward 
application
# of well-known techniques in classical cryptography, hence the name of the
# scheme. It is the latest member of a set of (to date) 4 members of 
encryption
# algorithms first published by the present author in
# http://s13.zetaboards.com/Crypto/index/ (the other 3 are JADE-S, JADE,
# SHUFFLE2). With appropriate setting of parameters, its strength is 
considered
# to be comparable to the other members of the set. It may however be 
preferred
# by the user because of the comparatively smaller number of its code 
lines and
# consequently presumably also less time required to understand its 
design and
# verify the coding for correctness and freedom from malicious backdoors. In
# fact, NEOCLASSIC has been developed primarily in view of the evidently
# enhanced needs of the common people to choose and employ sufficiently 
strong
# encryption software to protect the privacy of their innocent 
communications
# against the appallingly huge-scale international secret surveillance 
done by
# certain mighty countries of the world as recently revealed by the 
apparently
# highly convincing reports of the British newspaper The Guardian.

# Details of how the code parts work are given in the comment lines 
preceding
# the respective functions further below. Here we present for the 
convenience of
# those users who may prefer to postpone a detailed examination of the 
code for
# a later time a brief sketch of what is in essence done in one round on
# encryption, namely in the function process(), neglecting, initially, 
for ease
# of explanation, the authentication block:
#
#   Perform a pseudo-random transposition of the given plaintext characters.
#
#   With a variable sigma (initialized pseudo-randomly) do to each plaintext
#   character the following:
#
#     1. Find the index (idx) of that plaintext character in the alphabet.
#     2. Generate a pseudo-random number (rr).
#     3. Determine the "intermediate" ciphertext character corresponding 
to the
#        index gg in the alphabet, with gg=(idx+sigma+rr) (modulo alphabet
#        size), i.e. one does a "shift" of amount sigma+rr as is done in the
#        ancient Caesar cipher (our shift is albeit not a constant value but
#        pseudo-random).
#     4. Update sigma according to sigma=sigma+idx (modulo alphabet 
size), i.e.
#        sigma gets an addend idx, which is a value (dynamically) 
dependent on
#        the plaintext character that has just been processed.
#
#   Perform a mono-alphabetical substitution on all the intermediate 
ciphertext
#   characters, yielding the ciphertext characters (to be similarly 
processed in
#   the next following round, if there is one).
#
# For purpose of authentication we extend the user-given plaintext with 
a number
# of characters that are pseudo-randomly generated (termed the 
authentication
# block). It is the thus extended plaintext that is actually subjected 
to the
# kind of processing described above. Due to sigma, the processing of one
# character has influence on the processing of the next following one. Thus,
# additionally owing to the transpositions done in the number of rounds, the
# final ciphertext resulted is such that each character is highly correlated
# (the very opposite of being independent) with all the others. It is not
# difficult to see that, conversely, in case the ciphertext characters that
# correspond to the user-given plaintext are somehow manipulated/altered 
by the
# opponent, the authentication block recovered on decryption by the 
recipient
# will (with a very high probability) not be identical to the authentication
# block that the sender generates on encryption. In this way we achieve our
# intended goal of authentication (integrity check), the necessity of which,
# we note, is often neglected/underestimated in practical applications of
# cryptography.

# The function to be invoked by the user for encryption/decryption is
# neoclassic(). An example given further below illustrates its usage.

# Competition with established modern ciphers in processing speed is 
from the
# very beginning not a design goal of NEOCLASSIC (since message volumes of
# communications of common people (who are our targeted users) are as a rule
# fairly limited anyway and hence the difference in processing times 
would be
# entirely negligible) but rather in ease of code understanding and 
verification
# and in flexibility (of specification of system parameters, note also 
that the
# length of sessionkey is not fixed) and ease of use to perform
# encryption/decryption of intuitively/presumably (since we can offer no
# crypto-"proof") of equivalent, if not superior, strength (depending on 
choice
# of system parameters) in practice.

# Although the author has only tested (with Python 3.2.3) the software 
on texts
# in English, there seems to be no reason why NEOCLASSIC shouldn't well 
function
# on texts in other languages that have an alphabet. For Chinese, use of the
# Unicode or telegraphic codes to transcribe the logograms into decimal 
digits
# and an alphabet for English appears to be a viable possibility for 
employing
# NEOCLASSIC in practical applications.

# It may be noted that outputs of Python't built-in PRNG are only used
# indirectly and not directly as would have been the case for stream 
encryption
# processing. Further, there is processing-dependent dynamics/variability
# provided by the feedback operations (skipping of PRNs output from the 
PRNG,
# see the function process()). Thus the question concerning extremely high
# quality of the PRNG being used isn't a critical one to be examined for
# applications of NEOCLASSIC in practice.

# Communication partners should ensure having installed the same version of
# Python, since NEOCLASSIC depends on Python's built-in PRNG. We like to 
mention
# that, besides the evident requirement of keeping session-keys (and 
preferably
# also the chosen system parameters) secret, it may be under circumstances
# prudent (because of possible malware infections) to do 
encryption/decryption
# processing exclusively on physically secure computers isolated from the
# Internet and transfer the processed materials manually, i.e. on papers, to
# computers connected to the Internet, noting possible insecurity of USB 
sticks.
# Risks of electromagnetic emanations may eventually have to be 
considered as
# well (see R. Anderson, Security Engineering, chap. 15, Emission Security).


# Version 1.0, released on 07.07.2013. Comment lines last updatd on 
11.07.2013.


# Code lines of documents with the same version number are always identical.
# There may be interim modifications of comment lines. The most recent 
document
# of NEOCLASSIC can be obtained from
# http://s13.zetaboards.com/Crypto/topic/7077275/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
# NEOCLASSIC'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



# Loading a system module of Python that provides functionalities of its
# built-in PRNG.

import random


# The following string defines the alphabet to be used by NEOCLASSIC and 
may be
# arbitrarily modified (altered, shortened or lengthened) by the user, if
# needed. Plaintext may only use a subset of alphabet, but ciphertext 
will as
# a rule nonetheless involve the entire set of characters in alphabet. 
If space
# is included in alphabet, user should note that the last character of the
# ciphertext obtained may happen to be a space and consequently could be 
easily
# overlooked on subsequent handling of the ciphertext.

alphabetstr="ABCDEFGHIJKLMNOPQRSTUVWXYZ"\
             "abcdefghijklmnopqrstuvwxyz"\
             "0123456789()-?/=%&"

# Alphabet defined.
alphabet=list(alphabetstr)

# Alphabet size.
lenalpha=len(alphabet)


# Perform one round of pseudo-random transposition and substitution on
# textstring with Python's built-in PRNG seeded by roundkey. 
Transposition is
# done in the straightforward classical sense by Python's function 
shuffle() on
# textstring. Substitution is done in two stages. First, each 
character's index
# in alphabet is added by sigma and a pseudo-random value from Python's 
built-in
# PRNG (modulo alphabet size). This kind of addition goes back to the 
ancient
# Caesar cipher in classical cryptography. The variable sigma is initialized
# with a pseudo-random value from Python's built-in PRNG and updated 
with the
# index of the character being processed as the addend, thus resulting in
# processing-dependent dynamics/variability which is beneficial for security
# (albeit lacking in most other modern ciphers). Then there is a global
# substitution with Python's function translate(), with a substitution 
alphabet
# determined by Python's function shuffle(). This is mono-alphabetical
# substitution in the straightforward classical sense. Note that the varying
# value of sigma has the effect of block-chaining known in modern block
# encryption and is thus of particular significance to the performance of
# authentication achieved via the authentication block (i.e. the MAC in 
modern
# crypto terminology). If the updated sigma equals feedbackval, then the 
next
# PRN from the PRNG is skipped. This feedback to the PRNG provides further
# dynamics/variability that renders the cryptanalysis by the opponent hard.
# process() is called by neocalssic() (which is directly invoked by the 
user)
# numround times.

def process(roundkey,textstring,feedbackval,kn):
   global alphabet,lenalpha
   lenalpham1=lenalpha-1
   lentext=len(textstring)
   random.seed(roundkey)
   cipheralphabet=alphabet[:]
   random.shuffle(cipheralphabet)
   cipheralphabetstr="".join(cipheralphabet)
   ciphersequence=[i for i in range(lentext)]
   random.shuffle(ciphersequence)
   sigma=random.randint(0,lenalpham1)
   if kn==0:
# Begin of encryption processing for this round:
     newstring=""
     for i in range(lentext):
# This does transposition of the characters of textstring.
       tt=textstring[ciphersequence[i]]
# This does a substitution of the individual character.
       idx=alphabet.index(tt)
       rr=random.randint(0,lenalpham1)
       gg=(idx+sigma+rr)%lenalpha
       newstring+=alphabet[gg]
# Update sigma.
       sigma=(sigma+idx)%lenalpha
# Skip one PRN pseudo-randomly if sigma=feedbackval (this has a 
probability of
# 1/lenalpha in case the characters in textstring are uniformly 
distributed).
       if sigma==feedbackval:
         skipped=random.randint(0,lenalpham1)
# This does a global substitution (here from plaintext alphabet to 
ciphertext
# alphabet, a mono-alphabetical substitution).
     transtab=newstring.maketrans(alphabetstr,cipheralphabetstr)
     newstring=newstring.translate(transtab)
   else:
# Begin of decryption processing for this round (reversal of encryption
# processing):
     tmpstring=textstring[:]
     transtab=tmpstring.maketrans(cipheralphabetstr,alphabetstr)
     tmpstring=tmpstring.translate(transtab)
     newlist=["" for i in range(lentext)]
     for i in range(lentext):
       tt=tmpstring[i]
       gg=alphabet.index(tt)
       rr=random.randint(0,lenalpham1)
       idx=(gg-sigma-rr)%lenalpha
       newlist[ciphersequence[i]]=alphabet[idx]
       sigma=(sigma+idx)%lenalpha
       if sigma==feedbackval:
         skipped=random.randint(0,lenalpham1)
     newstring="".join(newlist)
# Return the result of processing of this round.
   return(newstring)


# sessionkey may be a decimal or hexadecimal integer or a character 
string of
# sufficient entropy. sessionkey is used as a seed for Python's built-in 
PRNG to
# generate pseudo-random roundkeys that each has roundkeybits number of 
bits for
# use as seeds for Python's built-in PRNG in the numround rounds of
# transposition and substitution done on inputstring by the function 
process().
# It also used to generate feedbackvals, an array of PRNs used for feedback
# operations done in the function process(). sessionkey is preferably to be
# chosen different for different sessions (it may consist e.g. of a 
fixed secret
# part of sufficient entropy and a variable session-dependent part (not
# necessarily to be guarded secret) that is determined from e.g. date, time,
# message number etc.). roundkeybits is to be appropriately chosen in 
relation
# to entropy of sessionkey, i.e. too large a value for roundkeybits 
relative to
# entropy of sessionkey doesn't make much sense in practice. 
authenblocklen is
# the length of authenblock, which is a block of pseudo-random characters
# automatically generated by NEOCLASSIC to be processed together with
# inputstring to serve the purpose of authentication (integrity check), 
see also
# comment to the function process() above. neoclassic() is the function 
to be
# directly invoked by the user for encryption/decryption.
# Encryption: set kn=0.
# Decryption: set kn=1.

def 
neoclassic(sessionkey,numround,roundkeybits,authenblocklen,inputstring,kn):
   global alphabet,lenalpha
   lenalpham1=lenalpha-1
   for i in range(len(inputstring)):
     if inputstring[i] not in alphabet:
       print("Error: inputstring contains character",\
             inputstring[i],"which is not in the defined alphabet")
       exit(1)
   random.seed(sessionkey)
   roundkeys=[]
   feedbackvals=[]
   for i in range(numround):
     roundkeys+=[random.getrandbits(roundkeybits)]
     feedbackvals+=[random.randint(0,lenalpham1)]
# Generate authentication block.
   authenblock=""
   for i in range(authenblocklen):
     authenblock+=alphabet[random.randint(0,lenalpham1)]
   if kn==0:
# Append authentication block.
     textstring=inputstring+authenblock
# Encryption processing.
     for i in range(numround):
       textstring=process(roundkeys[i],textstring,feedbackvals[i],kn)
   else:
# Decryption processing:
     textstring=inputstring
     for i in range(numround-1,-1,-1):
       textstring=process(roundkeys[i],textstring,feedbackvals[i],kn)
# Separate out the (recovered) authentication block from the (recovered)
# plaintext.
     lastblock=textstring[-authenblocklen:]
     textstring=textstring[:-authenblocklen]
# The recovered authenblock (lastblock) should be identical to the 
authenblock
# that is obtained from computing with sessionkey above.
     if lastblock==authenblock:
       print("Authentication (integrity check) o.k.")
     else:
       print("Authentication (integrity check) failed ***************")
       exit(2)
# Return the processing result.
   return(textstring)



# The following is an (abitrarily chosen, toy) example illustrating how 
to use
# NEOCLASSIC to do encryption/decryption.

# The alphabet (same for sender and recipient) has been defined further 
above.

# Sender defines the session-key and the other parameters and encrypts the
# plaintext pt to ciphertext ct for transmission to the recipient. (pt 
chosen
# here uses only a subset of the alphabet defined further above. This 
limitation
# is arbitrarily done by the sender in this particular example case and 
is not
# a necessary one.) Concerning choice of system parameters, see prologue 
at the
# beginning of the document.

sessionkey="sodifreruvsfuvherudf0607052"
numround=3
roundkeybits=128
authenblocklen=15

print("Sender side:")
pt="nowisthetimeforallmentocometotheaidoftheircountry"
print("pt:",pt)
ct=neoclassic(sessionkey,numround,roundkeybits,authenblocklen,pt,0)
print("ct:",ct)
print()

# Recipient defines the same (agreed-upon with sender) session-key and the
# other parameters and decrypts the received ciphertext ct to plaintext pt1.
# NEOCLASSIC automatically verifies the correctness of the 
authentication block
# recovered from ct and tells whether the authentication is o.k., see
# the function neoclassic().

sessionkey="sodifreruvsfuvherudf0607052"
numround=3
roundkeybits=128
authenblocklen=15

print("Recipient side:")
print("ct:",ct)
pt1=neoclassic(sessionkey,numround,roundkeybits,authenblocklen,ct,1)
print("pt1:",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()

Back to comp.programming | Previous | Next — Next in thread | Find similar | Unroll thread


Thread

NEOCLASSIC, An encryption scheme based largely on use of well-known classical crypto techniques Mok-Kong Shen <mok-kong.shen@t-online.de> - 2013-07-11 11:41 +0200
  Re: NEOCLASSIC, An encryption scheme based largely on use of well-known classical crypto techniques Mok-Kong Shen <mok-kong.shen@t-online.de> - 2013-07-23 14:22 +0200

csiph-web