####
#### File : README
#### Package : ex-Crypt
####

Welcome to ex-Crypt ! This file will enable you to understand
the utility of this package and will tell you about the procedure
involved in setting it up and then using it.

About ex-Crypt
--------------

ex-Crypt is a cryptographic library containing an implementation of 
a candidate One-Way Function (OWF) and a related Pseudorandom Function
(PRF). We presume that you are familiar with the utility of one-way 
functions and psedorandomness in cryptographic schemes and in case 
you are not, it is highly recommended that you first read relevant 
documentation on this topic before attempting to make use of this 
package. Some information provided in the directory "doc" may also 
serve to be useful. 

The suggestion for this OWF has been made by Oded Goldreich of the 
Weizmann Institute of Science, Israel (refer to the paper titled
"A Candidate One-Way Function based on Expander Graphs" on his 
homepage) though many researchers have contributed to elements in its 
construction. 

For more information on the utility and properties of this OWF and 
of the package in general, refer to the documentation provided.

Purpose of ex-Crypt
-------------------

The purpose of ex-Crypt is to provide a good and effective 
implementation of the OWF and the related PRF given in the paper
cited above so that the general public, including yourself, can
experiment with the OWF (resp. PRF) and use it at free will without 
expending much effort. We don't claim that ex-Crypt is the most
efficient implementation of the OWF (resp. PRF) possible and indeed,
it isn't. The chief consideration was not to optimize on the 
implementation but to make the program usable by many people.

You are welcome to give suggestions regarding imrovement of
efficiency of the source code, if you come up with any ideas. We
will try and incorporate them in future versions.

Availability
------------

ex-Crypt is a freely downloadable software available from the homepage
of Oded Goldreich (www.wisdom.weizmann.ac.il/~oded). You are free to 
distribute and use this software as and how you desire. 

* Kindly report bugs, if any, that you discover during the usage of
  the code.

* You are welcome to e-mail us in case you need to be informed about 
  any updates/improvements with regard to the package. (Refer to email
  addresses provided at the end).

Compatibility
-------------

The source code for the package is in C++ and, thus most importantly, 
it requires the availaibility of a C++ compiler on your system, 
alongwith the basic libraries that C++ uses. We tested the code
withe GNU version of C++ (g++) but we believe that any version
of C++ compatible with ANSI should work.

Also, the package has been tried and tested only on UNIX platforms 
including Linux (ver 6.1 or higher) and Sun OS (ver 5.7 or higher)
and IRIX. We do not gaurantee proper functionality on other systems.
Since the trial was performed on only a limited class of Unix versions,
we don't claim that bug-free performance on all of them. Please 
report any incmpatibilities to us so that we can keep upgrading
the software.

Installation
------------

Installing ex-Crypt is easy. Presuming that you've successfully opened 
the package, you should carry out the following 2 steps to create and 
install the executables :

* run './config' on the command prompt (while in the current 
  directory)

* If the above terminates successfully (without flagging any errors),
  run 'make' on the command prompt. This will place the executables 
  in the directory "bin". 

Usage of the basic OWF
----------------------

The OWF requires two sets of parameters for it's functionality - the
description of a set system and that of a predicate (ref. 
documentation). Both these need to be hard-wired into the OWF before
using it. The parameters are stored in the subdirectory "data" and the 
OWF looks for the files "setsystem.dat" and "predicate.dat" in this
subdirectory by default. You may, however, specify files containing the
parameters by a variation discussed below.

First and formost you must ensure that some parametric information is
created and stored in the directory "data". To this end, you should
execute the command './bin/genOWF' from the current directory only
Running 'genOWF' with the proper options for setting up new setsystem
and a new predicate (these are the parameters that the 
OWF function needs for execution) is necessary before making any
use of the OWF. The setsystem goes into the file "data/setsystem.dat"
and the predicate into the file "data/predicate.dat".

After this, you can try and see the performance of the OWF on bit strings
with length as specified by you while generation by running the command
'./bin/runOWF' on the command prompt. The command 'runOWF' requires the name 
of a file containing "only" the bit-string you want to run the function on. (The
file should be specified with the path or, if the path is not specified, 
then the file should be in the current directory). The bit-string 
should be written in the file starting at the first column and row,
should not contain anything other than 0s and 1s in a single row
and should be at least as long as the length parameter fed to the 
function.

Usage of the OWF as a module in other programs
----------------------------------------------

The above use doesn't generate much interest, does it ? Well, this
OWF has been designed more for the sake of being used as a cryptographic
library and we do provide the utility for the same (though an
encryption scheme discussed below). 

To use the function as a module in other programs, one only needs to include the 
header file (with the proper path) "Execute.hpp" in the source
code directory. Do not move this header file outside and then try
to include it. It has dependencies on other files in the package.
For evaluating the OWF on a particular string, you need to
use the function "eval" whose signature is as -

		void eval(char *input, char *output);	

where 'input' and 'output' are the input and output bit-strings (both 
specified as strings of 0s and 1s of the requisite length). This 
version of the function "eval" makes use of the default parameters (the
set system and the predicate) which you should have generated before
trying to use the function. Some versions of the function are already
available in the data directory and you could utilize them also. But
when we refer to the default version we refer to the files "data/setsystem.dat"
and "predicate.dat".

For the iterative version of the function use -

		void evalIterative(char *input, char *output, int iter);

where iter is the number of iterations desired. Again, this version
uses the default parameters and to choose your own version of the
function you should do one of the following -

a) Either generate the function for your choice of parameters into 
the default files that "eval" looks for. 

b) Or better still, specify the file itself in which you've stored
your choice of parameters. For this use the following versions of 
the function -

        void evalGivenFiles(char *input, char *gfile, char *pfile, 
				char *output, int iter);

where input, output and iter are as before, gfile and pfile are the names (WITH
CORRECT PATH RELATIVE TO THE CURRENT DIRECTORY) of the files containing
the setsystem and predicate respectively. 

In case you desire repeated usage of the function for a large
number of inputs, you may want to use a faster version which provides
the parameters from memory rather than from files. For this purpose, 
use -

		void computeGiven(int n, int d, char *input, int collection[][klimit], 
				char predicate[], char *output, int iter,  
				char (*apply)(char *, int [], char [], int)
				);

where n and d are the basic parameters of the function as in the documentation, 
input and output are as before, collection is an (n)x(klimit) array containing 
the collection of sets the function has been hardwired with (klimit is the
upper limit on d, set as 20 in the source code) and predicate is an array
of length $2^d$, containing 1s and 0s only and is a specification of the 
predicate as stored in the file "predicate.dat". iter is the number of 
iterations desired and apply is either "applypredicate", "applypolynomial"
or "applyshamir" depending upon the kind of predicate you have hardwired.
Its best if you have a look at the way 'compute' itself uses 'computeGiven' 
so that you get an idea of how you should go about it.

Modifying parameters and playing around with the function
---------------------------------------------------------

There are various options available for parameterising the
function as and how you please. You should refer to the documentation
for more details on what the various parameters mean. Some parameters
work better than the others. You can try and test the function on
various parameters freely by running 'genOWF' as many times as you
desire. Just don't fool around with the generation process by
providing inputs which are not acceptable. 

Also, you can reserve some parameters for later usage if you so desire
by simply storing the files "setsystem.dat" and "predicate.dat" in the
directory "data" in some other place or by some other names in the same
directory as has been done with the examples provided. Just keep in mind
that running 'genOWF' overwrites these two files with the new parameters. 

Using the Pseudo-Random Function
--------------------------------
We have also provided the functionality of a PRF (pseudorandom function)
in the package. This PRF is based on the iterative version of the function
(as suggested in the paper). The parameters for the PRF are the setsystem
and the number of iterations of the OWF desired. We have made recommendations
for the value of the number of iterations and it's better if you stick
to these recommendations (if you want your PRF to be secure, that is !). 
The PRF uses a seed of size $n + 2^d$ out of which the first $n$ bits
form a mask on the input fed to the function (this mask is XORed with
the input string before the iterated OWF is applied to the input) and the 
next $2^d$ bits form the description of the random predicate which the OWF 
uses. Thus, using the PRF involves the following stages -

* Generating the parameters - for this use the binary code "bin/genPRF" and
run it from the main directory of the package only. This will ask you
for values for creating the setsystem with and also for the number
of iterations.

* Generating the seed (or the secret) - for this use the binary code 
"bin/genKEY". It will ask you for a random input based on which your
seed will be generated. 

* Using the PRF as a module in other programs - Once you've set up the
PRF by setting the setsystem, the number of iterations and the seed/secret
you can make use of it in your own program code. All you need to do
is to include the file "ExecutePRF.hpp" in the src directory WITH
ITS CORRECT RELATIVE PATH in your file and use either of the following
versions of the PRF -

a) void evalPRF(char *input, char *output) => as in the case of OWF 
this version will make use of the default file for setsystem + seed,
which are "data/setsystemPRF.dat" and "keys/key.dat" respectively. 
(the number of iterations is included in the former file). (When
you run "bin/genPRF" and "bin/genKEY", these are the files (in that
order) that the created parameters and seed go into. As in the case
of the OWF, running these 2 binaries overwrites the previously
contained parameters/seed in the respective files.)

b) void evalPRFGivenParams(char *input, char *gfile, char *output)
   void evalPRFGivenSeed(char *input, char *sfile, char *output);
   void evalPRFGivenParamsAndSeed(char *input, char *gfile, char *sfile, 
   									char *output);

These 3 versions are similar in the sense that YOU provide the files
to take the parameters or seed or both from. These files MUST be of 
identical format as the default files. Typically, you would like to 
generate a few (maybe 2 or 3) seeds, a fixed set of parameters (the
setsystem + number of iterations) and run the PRF for several strings
for these combinations. So you can generate more than one seed of your choice
(or even more than one setsystem) and feed the filenames of the files
where you keep these seeds/setsystems to the function. In the
above signatures of the "evalPRF" function, gfile is the name of
the file containing the setsystem + number of iterations and
sfile is that of the file containing the key/seed/secret.

c) In some cases you would want to feed the parameters (setsystem
+ iterations) and seed from memory itself to reduce on running
time (especially in cases you are running the PRF several times
in the same code and on the same seed+setsystem). In such a case,
use the following 

void evalPRFGiven(int n, int d, char *input, int collection[][klimit], 
					char seed[], char *output, int iter);

Here n,d are the parameters for the setsystem, collection is a 
2-d array containing the setsystem, seed is an $n+2^d$ array containg
the seed and input, output and iter are as before. 

In practice, we feel that you would use the default files for setsystem
and seed in most cases and will thus stick to the simplest version
of "evalPRF" (case (a) above). However, you are free to use any
of these versions at free will, as in the case of the OWF.

Note that for using the PRF you just have to include the file 
"ExecutePRF.hpp" in your respective program and not the "Execute.hpp"
file for the OWF.

A Private-Encryption Scheme Based on the above PRF
--------------------------------------------------

We have included the code for a private-Encryption scheme based 
on the above PRF in the package. The implementation is not very
efficient but it's illustrative of one important use of the PRF
module. 

The binaries created for encryption and decryption are "encrypt"
and "decrypt" respectively. For both encryption and decryption,
the default files for setsystem and seed are used by the PRF that
each of them uses. The seed becomes the "key" for encryption/decryption
and hence we've maintained a separate directory for it, which
you can treat specially (and with more security in mind). You could 
however change the encryption/decryption key by moving some previously
generated key into the default file ("keys/key.dat"). Basically, once
you've set up your PRF (that is, initialised values in the default 
files which are compatible with each other) you will be ready to
run the encryption scheme.

a) To encrypt a piece of plaintext contained in file "message" and put
the ciphertext in a file "cipher", run the following from the main 
directory of the package -
	
	$ encrypt message cipher

The ciphertext is stored as a series of 0s and 1s. Note that we've
given an implementation in which every bit is stored as a character
and thus uses a lot more of memory space than what's required. You 
could come up with a better implementation of your own.

b) To decrypt the ciphertext created above and to put it in a file
named "decrypted_cipher", do the following, again only when in the
main directory of the package 

 	$ decrypt cipher decrypted_cipher

"decrypted_cipher" will be a text file absolutely similar to the 
original plaintext, "message" (unless of course you fool around 
with your key or the setsystem in between).

Secrecy of the KEY
------------------
It is important for the key (for the encryption scheme) or seed (for
the PRF) to be maintained with greater care than the rest of the
information in this directory. We have provided a separate directory, "keys",
for keeping keys. The default file is "keys/key.dat" which is currently
empty and you'll need to generate a seed/key before using the PRF.

Some Setsystems + Predicates provided
-------------------------------------
We have provided 4 sets of setsystem and  predicate for the OWF with
one of them also copied onto the default file for setsystem and predicate
("data/setsystem.dat" and "data/predicate.dat"). WE have given the following
instances for the setsystems -

a) Random Expander (n=256, d=8) in "data/setsystemR.256.8.dat"
b) Random Expander (n=512, d=10) in "data/setsystemR.512.10.dat"
c) Alon's Expander (n=183, d=14) in "data/setsystemA.183.14.dat"
d) Alon's Expander (n=133, d=12) in "data/setsystemA.133.12.dat"

Five predicates are also provided -

a) Random predicate (d=8) in "data/predicateR.8.dat"
b) Random predicate (d=10) in "data/predicateR.10.dat"
c) Random predicate (d=12) in "data/predicateR.12.dat"
d) Random predicate (d=14) in "data/predicateR.14.dat"
e) Random 2-degree polynomial as the predicate (d=12) in "data/predicateRP.12.dat"

As should be clear to you the names of the files, both for predicate
and setsystem are suggestive of the parameters (n, d) they use and 
the type of predicate (Random/polynomial) OR setsystem (Random/Alon's)
it contains.

The predicate in the file "predicate.dat" is the same as "data/predicateRP.12.dat" 
and the setsystem in "setsystem.dat" is the same as "data/setsystemA.133.12.dat".
Hence the 2 are compatible in the sense that they involve the same value
of "d".

For the PRF, we have provided one setsystem (n=256, d=8) (which is currently 
in the default file = "data/setsystemPRF.dat"). Keep in mind the fact that
the file for setsystem is different from that for that for the OWF. There
is the additional parameter - the number of iterations. So don't mix them
up.

Challenges
----------
We have also included some challenges corresponding to the above included
sets of paramters in the challenges directory. Specifically, for every
instnace of the one-way function included in the data directory, we have 
included an output string whose input we want you to determine.

For the encryption scheme we have provided a message text file and 
the corresponding ciphertext under encrytion. We want you to determine
the key used. (The encrytion scheme corresponds to the data in
the setsystemPRF.dat file)

Authors
-------

1> Saurabh Kumar Panjwani <panjwani@cse.iitb.ac.in>
2> Oded Goldreich <oded@wisdom.weizmann.ac.il

For technical clarificaltions or bugs, it's better if you contact
Saurabh and on the other hand, for doubts or suggestions related
to the OWF and its construction in theory, you should refer to
Oded.

We are open to any suggestions you can provide us with. Also, we would
be highly grateful to you if, in case you are convinced about the
utility of this package, you could distribute it around to other people
who can experiment with it.

All the best in using ex-Crypt ! 


