Upload
harahari-donkeshwaram
View
279
Download
2
Embed Size (px)
Citation preview
CRYPTOGRAPHY 11/16/2011 INDIAN INSTITUTE OF TECHNOLOGY DELHI Donkeshwaram Harahari, Srishti Bhaduri.
P a g e | 1
CRYPTOGRAPHY
A semester project report
for
Master of Science in Mathematics
Submitted by
DONKESHWARAM HARAHARI (2010MAS7133)
SRISHTI BHADURI (2010MAS7109)
Under the guidance of
Dr. R.K.Sharma
DEPARTMENT OF MATHEMATICS INDIAN INSTITUTE OF TECHNOLOGY DELHI
November 16 , 2011
P a g e | 2
CERTIFICATE
This is to certify that the dissertation entitled "Cryptography" which is being submitted by Donkeshwaram.Harahari(2010MAS7133) and Srishti Bhaduri(Entry no:2010MAS7109) for the award of the degree of Master of science in Mathematics, to the Indian Institute of Technology Delhi is a record of bonafide work carried out by them under my sustained guidance and supervision. This dissertation has reached the standard fulfilling the requirements of the regulations relating to the degree. The results embodied in the dissertation have not been submitted to any other university for the award of any degree or diploma.
Dr.R.K.Sharma Professor
Department of mathematics Indian Institute of Technology
Hauz Khas New Delhi-110016
P a g e | 3
Acknowledgement
We are grateful to Dr.R.K.Sharma for his constant motivation and guidance.
We are highly obliged to him for constantly encouraging us by giving his critics
on our work. His sincere efforts to make us see things from the right point of
view have certainly been fruitful, as we consider ourselves to in a position, to
have a fairly matured insight into the area of cryptography. Without his
motivation and useful suggestions, this project would not have been possible.
Date: November 16, 2011 Srishti Bhaduri(2010MAS7109)
Donkeshwaram Harahari (2010MAS7133)
P a g e | 4
Table of Contents
Abstract ................................................................................................................................................... 5
1. Meet Cryptography ............................................................................................................................ 6
1.1 Some Terminologies ...................................................................................................................... 6
1.2 Objective of Cryptography ............................................................................................................ 8
1.3 Classification…………………………………………………………………………………………………………………………...8
2. Historical Ciphers……………………………………..……………………………………………………………………………..16
2.1 History of Ciphers …………………………………………….……………………………………………………………………10
2.2 Some Historical Ciphers………………………………………………………………………………………………………….10
2.3 Inverse of a matrix over a Field……………………………………………………………………………………………….13
2.4 Chinese remainder theorem…………………..………………………………………………………………………………20
3. Prime number generation…………………………………………………………………….………………………………...23
3.1 Trial division…………………….……………………………………………………………………………..……………..………23
3.2 Fast powering algorithm…………………………………………………………………….………….………….…………..25
3.3 Fermat’s test…………………………………………………………………………..….……………..………….…….…………27
3.4 Rabin Miller’s test……………………………………………………….…………..………………………………..…………..29
4. Factorization……………………………………………………………………………………………………………………………33
4.1 RSA Cryptosystem………………………………………………………….………………..………..…………..………………33
4.2 Rabin Cryptosystem……………………………..…………………………..………………..……..……..……………………35
4.3 Trail division………………………………………….……………………………………………..……….……………………….37
4.4 Pollards p-1 Factorization algorithm…………………………………………………………..…………………..……..37
4.5 Fermats Factorization algorithm………………………………………………………………..…..……………………..39
5. Discrete logarithmic problem…………………………………………………………………………..……………….…….42
5.1 Trivial brute-algorithm………………………………………………………………………………..….……….…………….43
5.2 Shanks Baby step-Giant step algorithm………………………………………….……………………………………..43
P a g e | 5
Abstract
Cryptography allows people to carry over the confidence found in the physical
world to the electronic world, thus allowing people to do business
electronically without worries of deceit and deception. A principle goal of
Cryptography is to allow two people to exchange confidential information, even
if they have never met and can communicate only via a channel that is being
monitored by an adversary.
In this project we focussed on computer implementation of various algorithms uses in the field of Cryptography and we compared their efficiency (i.e., calculating the runtimes) for large values of data. At first we gave simple introduction to Cryptography. Next, we discussed about some of classical ciphers and algorithms for finding inverse of a matrix over any field and solving linear congruences. Then we discussed algorithms used for generating primes, prime factorisation and solving discrete logarithmic problems. We also discussed about some of the public key cryptosystems wherever it is necessary. We have done C++ coding for all algorithms discussed in this project.
P a g e | 6
CHAPTER 1
MEET CRYPTOGRAPHY
Cryptography is “A branch of mathematics and computer science,
cryptography is the study and practice of obscuring information”. Let‟s now
have a look at the field of cryptography (Fig. 1.1). The first thing that we notice
is that the most general term is cryptology and not cryptography.
Cryptology splits into two main branches:
Fig. 1.1 Overview of the field of cryptology
Cryptography is the science of secret writing with the goal of hiding the
meaning of a message.
Cryptanalysis is the science and sometimes art of breaking cryptosystems.
Cryptanalysis is of central importance for modern cryptosystems without
knowledge of this, we will never know whether we are really secure or not.
1.1 Some Terminologies:
• Plaintext: The message to be sent.
• Cipher text: The disguised message.
• Enciphering: The process of converting a plaintext to a cipher text.
• Deciphering: The process of getting the plaintext from the cipher text.
• Message Unit: A single letter, a pair of letters (Diagraph), a triple of
letters (trigraph), or a block of 50 letters, in which the text is broken
depending on the cryptosystem.
• Entity (party): Someone or something which sends, receives, or
manipulates information. An entity may be a person, a computer
terminal, etc.
P a g e | 7
• Sender: An entity in a two-party communication which is the legitimate
transmitter of information.
• Receiver: is an entity in a two-party communication which is the
intended recipient of information.
• Adversary: is an entity in a two-party communication which is neither
the sender nor receiver, and which tries to defeat the information security
service being provided between the sender and receiver. Various other
names are synonymous with adversary such as enemy, attacker,
opponent, tapper, eavesdropper, intruder, and interloper.
• Channel: A channel is a means of conveying information from one entity
to another.
• Enciphering Transformation:
A function that takes a plaintext message unit to a cipher text
message unit. It is a map f from the set P of all possible plaintext message
units to the set C of all possible cipher text message units. It is also called
as Encryption.
.
• Deciphering Transformation: The map f -1
which recovers the plain
text. It is also called as Decryption.
Note: Here we assume that f and f
-1 are 1-to-1 transformations.
Cryptosystem: The system formed by ‘ f’ and‘ f
-1’ is called as
Cryptosystem. This is also called as Cryptographic algorithm (Or
Cipher).
Key: An integer (large) which is used to encrypting or decrypting the
message.
The very first step in designing a cryptosystem is to label all possible
plaintext units and ciphertext units by means of mathematical objects from
which the functions can easily be constructed. (E.g. Integers in some range).For
instance, if our cryptosystem consists only of the alphabet A-Z, we can label the
integers from 0-26, sequentially. And such labels are called Numerical
Equivalents.
In order, to make calculations in enciphering and deciphering easier and
rapid, we take the set of the numerical equivalents (integers) as elements in { 0,
1, 2, ……, N-1} as Z/NZ, and operating the calculations under modulo N,
where is the N base.
P a g e | 8
1.2 Objectives of Cryptography:
The main Objectives of Cryptography are: (1) privacy or confidentiality;
(2) data integrity; (3) authentication; and (4) non-repudiation.
1. Confidentiality is a service used to keep the content of information from all
but those authorized to have it. Secrecy is a term synonymous with
confidentiality and privacy. There are numerous approaches to providing
confidentiality, ranging from physical protection to mathematical algorithms
which render data unintelligible.
2. Data integrity is a service which addresses the unauthorized alteration of
data. To assure data integrity, one must have the ability to detect data
manipulation by unauthorized parties. Data manipulation includes such things
as insertion, deletion, and substitution.
3. Authentication is a service related to identification. This function applies to
both entities and information itself. Two parties entering into a communication
should identify each other. Information delivered over a channel should be
authenticated as to origin, date of origin, data content, time sent, etc. For these
reasons this aspect of cryptography is usually subdivided into two major
classes: entity authentication and data origin authentication. Data origin
authentication implicitly provides data integrity (for if a message is modified,
the source has changed).
4. Non-repudiation is a service which prevents an entity from denying previous
commitments or actions. When disputes arise due to an entity denying that
certain actions were taken, a means to resolve the situation is necessary. For
example, one entity may authorize the purchase of property by another entity
and later deny such authorization was granted. A procedure involving a trusted
third party is needed to resolve the dispute.
A fundamental goal of cryptography is to adequately address these four
areas in both theory and practice. Cryptography is about the prevention and
detection of cheating and other malicious activities.
1.3 Classification:
Cryptography itself splits into three main branches:
I. Symmetric (or Private-key) Algorithms
These are what many people assume cryptography is about: two parties have an
encryption and decryption method for which they share a secret key. All
P a g e | 9
cryptography from ancient times until 1976 was exclusively based on
symmetric methods. Symmetric ciphers are still in widespread use, especially
for data encryption and integrity check of messages.
Examples: DES(Data Encryption standard),TDES(Triple Data Encryption
Algorithm),AES(Advanced Encryption Standard process) and nearly all
Classical ciphers like Caesar cipher, Vigenere cipher, Hill cipher, Affine
transformation etc.
II. Asymmetric (or Public-Key) Algorithms:
In 1976 an entirely different type of Cipher was introduced by Whitfield Diffie,
Martin Hellman and Ralph Merkle. In public-key cryptography, a user
possesses a secret key as in symmetric cryptography but also a public key.
Asymmetric algorithms can be used for applications such as digital signatures
and key establishment, and also for classical data encryption.
Examples: Diffie Hellmann Key-Exchange, Elgmal, Mussey Omura, RSA,
Robin Cryptosystems.
III. Cryptographic Protocols:
Roughly speaking, crypto protocols deal with the application of cryptographic
algorithms. Symmetric and asymmetric algorithms can be viewed as building
blocks with which applications such as secure Internet communication can be
realized.
Example: The Transport Layer Security (TLS) scheme, which is used in every
Web browser, is an example of a cryptographic protocol.
In next chapter we will discuss about some classical (historical)
Ciphers.
P a g e | 10
CHAPTER 2
HISTORICAL CIPHERS
2.1 History of Ciphers
The history of cryptography begins thousands of years ago. Until recent
decades, it has been the story of what might be called classic cryptography that
is, of methods of encryption that use pen and paper, or perhaps simple
mechanical aids. In the early 20th century, the invention of complex mechanical
and electromechanical machines, such as the Enigma rotor machine, provided
more sophisticated and efficient means of encryption; and the subsequent
introduction of electronics and computing has allowed elaborate schemes of still
greater complexity, most of which are entirely unsuited to pen and paper.
2.2 Some Historical Ciphers
2.2.1 Caesar Cipher
One of the simplest examples of a substitution cipher is the Caesar cipher,
which is said to have been used by Julius Caesar to communicate with his army.
Caesar is considered to be one of the first persons to have ever employed
encryption for the sake of securing messages. Caesar decided that shifting each
letter in the message would be his standard algorithm, and so he informed all of
his generals of his decision, and was then able to send them secured messages.
Using the Caesar Shift (3 to the right), the message,
”RETURN TO ROME”
would be encrypted as,
”UHWXUA WR URPH”
In this example, ‟R‟ is shifted to ‟U‟, ‟E‟ is shifted to ‟H‟, and so on. Now, even
if the enemy did intercept the message, it would be useless, since only Caesar‟s
generals could read it.
2.2.2 Playfair Cipher
P a g e | 11
The Playfair cipher or Playfair square is a manual symmetric encryption
technique and was the first literal digraph substitution cipher. The scheme was
invented in 1854 by Charles Wheatstone, but bears the name of Lord Playfair
who promoted the use of the cipher.The technique encrypts pairsof letters
(digraphs), instead of single letters as in the simple substitution cipher.
The Playfair cipher uses a 5 by 5 table containing a key word or phrase.
Memorization of the keyword and 4 simple rules was all that was required to
create the 5 by 5 table and use the cipher.
To generate the key table, one would first fill in the spaces in the table with the
letters of the keyword (dropping any duplicate letters), then fill the remaining
spaces with the rest of the letters of the alphabet in order (usually omitting”Q”
to reduce the alphabet to fit, other versions put both”I” and ”J” in the same
space). The key can be written in the top rows of the table, from left to right, or
in some other pattern, such as a spiral beginning in the upper-left-hand corner
and ending in the centre. The keyword together with the conventions for filling
in the 5 by 5 table constitutes the cipher key.
To encrypt a message, one would break the message into digraphs (groups of 2
letters) such that, for example, ”Hello World” becomes ”HE LL OW OR LD”,
and map them out on the key table. The two letters of the digraph are considered
as the opposite corners of a rectangle in the key table. Note the relative position
of the corners of this rectangle. Then apply the following 4 rules, in order, to
each pair of letters in the plaintext:
1. If both letters are the same (or only one letter is left), add an ”X” after the
first letter. Encrypt the new pair and continue. Some variants of Playfair use
”Q” instead of ”X”, but any uncommon monograph will do.
2. If the letters appear on the same row of your table, replace them with the
letters to their immediate right respectively (wrapping around to the left side of
the row if a letter in the original pair was on the right side of the row).
3. If the letters appear on the same column of your table, replace them with the
letters immediately below respectively (wrapping around to the top side of the
column if a letter in the original pair was on the bottom side of the column).
4. If the letters are not on the same row or column, replace them with the letters
on the same row respectively but at the other pair of corners of the rectangle
defined by the original pair. The order is important the first letter of the
encrypted pair is the one that lies on the same row as the first letter of the
plaintext pair.
P a g e | 12
To decrypt, use the INVERSE (opposite) of the last 3 rules, and the 1st as-is
(dropping any extra”X”s (or ”Q”s) that don‟t make sense in the final message
when finished).
2.2.3 Hill Cipher and Affine ciphers
Here we are going to introduce matrix version of Hill cipher. Why because 1*1
Matrix is nothing but an element which is special case. Let each diagraph
correspond to a vector, i.e. a pair of integers
with x and y considered modulo N.
For example if we have the 26 letter alphabet in our cryptosystem, then the
diagraph NO would correspond to
13
14
Numerous Ciphers are possible to be implemented when dealing with Matrix
Enciphering, like, Affine, Hill etc.
The mappings used are:
Hill: C=AP
Affine: C=AP + B
Where A and B are known as the enciphering keys and A is invertible in Z/NZ.
Example of Hill Transformation:
Enciphering the Plaintext, “NOANSWER”, taking the message unit as
digraph.
The numerical equivalent is:
13 0 18 4
14 13 22 17
P a g e | 13
We have the mapping as C=AP
Let A, the key, be taken as
2 7
3 8
Hence, our ciphered text is
C = AP = 2 7 13 0 18 4
3 8 14 13 22 17
= 16 13 24 7
21 0 16 8
i.e. the coded message is “QVNAYQHI”
Now, for decryption, we rearrange the mapping and and get
P=A-1
C in the case of Hill Transformation and
P= A-1
C-A-1
B in case of Affine Transformation.
Since, we deal with inverses of a matrix in decryption to a large extent, our
project begins with writing a code in C++ language, to determine the inverse of
a matrix in a finite field.
2.3 Inverse of a matrix over a finite field
We used gauss Jordan method for finding inverse so the algorithm for this
is:
Algorithm 2.3.1:
• Input the order of the matrix and the matrix itself from the user.
• The user chooses the option out of „finite field‟ or „real line‟.
P a g e | 14
• Formation of an Identity matrix of the same order.
• In the case of finite field, the user will the asked to enter the value for p as
in Zp.
• We check if there is any zero element in the diagonal, we change it to a
positive or negative number using elementary column operations.
• Simultaneously we check, for all zero columns and rows, in which case, it
displays the determinant zero and terminates the program
• Else, we use the Gauss Jordan Elimination method to change the given
matrix in its diagonal form using the following elementary row
operations.
Ri Ri – Rk * aik
akk
where,
the matrix is A = aij n x n
k = step index
i =1,2,3…….. k-1, k+1,…..n
• Simultaneously apply the above transformations on the identity matrix
of the same order, n.
• We multiply the diagonal of the matrix A to get the determinant.
• In case, the option of the finite field, we do all the calculations under
modulo.
• We check the condition, whether the determinant, thus evaluated, is co-
prime with
• p or not.
• If no, we display that the inverse doesn‟t exist and the program
terminates.
P a g e | 15
• If yes, we divide each row by it‟s respective diagonal elements,
simultaneously, applying the same on the identity matrix.
• The identity thus found is the required inverse.
• In case of finite field, all operations are done under modulo p
C source code :
#include<stdio.h>
#define MAX 10
void pivoting();
int checkzeros();
//-------------------------------------------------------------------------
// MAIN FUNCTION FOR FINDING INVERSE OF A MATRIX :
//-------------------------------------------------------------------------
int main()
{
int det();
float rem(int,float);
float a[MAX][MAX],value;
int i,j,N,u,p;
printf("Enter order of the matrix [A] : ");
scanf("%d",&N);
//inputting the values of matrix
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
printf("Enter (%d,%d) element of the matrix [A] :",i+1,j+1);
scanf("%f",&a[i][j]);
}
}
printf("\n If you want find inverse of the given matrix (on real line / on
finite field Z(p)) enter (0/1) respectively: ");
scanf("%d",&u);
if (u==1)
{
printf("\n Enter the value of the prime 'p': ");
scanf("%d",&p);
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
a[i][j]=rem(p,a[i][j]);
printf("%f",a[i][j]);
}}
}
printf("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
printf("\n RESULT:");
printf("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
printf("\n 1.GIVEN MATRIX [A] is :\n");
for(i=0;i<N;i++)
{
printf("\n");
P a g e | 16
for(j=0;j<N;j++)
{
printf("%f\t",a[i][j]);
}}
float I[N][N],det1;
//forming identity matrix of given order(N*N)
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
if(i==j)
I[i][j]=1;
else
I[i][j]=0;
}
}
det1=det(a,N,I);//calling the determinant function
printf("\n\n 2. Diagonal form of given matrix [A] is:\n");
for(i=0;i<N;i++)
{
printf("\n");
for(j=0;j<N;j++)
{
printf("%f\t",a[i][j]);
}}
if (u==1)
{
det1=rem(p,det1);
}
printf("\n\n 3.Determinent of the matrix [A] is :%f",det1);
if(det1==0)
{
printf("\n\n Sorry inverse of matrix [A] does not exist.\n");
return 0;
}
if(u==1)
{
if (gcd(p,det1)!=1)
{
printf("\n\n Sorry inverse of matrix [A] does not exist.Since
gcd(p,detA)==%d (i.e.,Not coprime)\n",gcd(p,det1));
return 0;
}}
printf("\n\n 4.the eigen values of matrix [A] are:");
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
if(i==j)
printf("%f\t",a[i][j]);
}}
float mult2;
for(i=0;i<N;i++)
{
mult2=a[i][i];
for(j=0;j<N;j++)
I[i][j]=I[i][j]/mult2;
}
if (u==1)
{
for(i=0;i<N;i++)
P a g e | 17
{
for(j=0;j<N;j++)
{
I[i][j]=rem(p,I[i][j]);
}}
}
printf("\n\n 5.the inverse of the matrix [A] is:\n");
for(i=0;i<N;i++)
{
printf("\n");
for(j=0;j<N;j++)
{
printf("%f\t",I[i][j]);
}}
printf("\n");
}
//-----------------------------------------------------------------------
// Function for finding det of a matrix:
//-----------------------------------------------------------------------
int det(float a[][MAX],int N,float I[][N])
{
int i,j,k;
float mult;
int deter=1;
for(i=0;i<N;i++)
{
if(checkzeros(a,N)==0)
return 0;
else
{
pivoting(a,N,I,i);
for(j=0;j<N;j++)
{
mult=a[j][i]/a[i][i];
for(k=0;k<N;k++)
{
if(i==j)
break;
a[j][k]=a[j][k]-a[i][k]*mult;//changing into cononical form
I[j][k]=I[j][k]-I[i][k]*mult;
}
}
printf("\n---------------------------------------------------\n");
for(i=0;i<N;i++)
{
printf("\n");
for(j=0;j<N;j++)
{
printf("%f\t",a[i][j]);
}
}
}
}
for(i=0;i<N;i++)
{
deter=deter*a[i][i];//since product of eigen values=determinant
}
return(deter);
}
P a g e | 18
//------------------------------------------------------------------------
// Function to check zero elements in rows of the Matrix:
//-------------------------------------------------------------------------
int checkzeros(float a[][MAX],int N)
{
int i,j,k,T,U;
for(i=0;i<N;i++)
{
T=0;
for(j=0;j<N;j++)
{
if(a[i][j]==0)
T=T+1; //T counts no of zeros in each row
}
if(T==N)
return 0;
}
for(i=0;i<N;i++)
{
U=0;
for(j=0;j<N;j++)
{
if(a[j][i]==0)
U=U+1; //T counts no of zeros in each row
}
if(U==N)
return 0;
}
return(1);
}
//------------------------------------------------------------------------
// Function for finding remainder of an integer (a->p%b) :
//------------------------------------------------------------------------
float rem(int a,float b)
{
if(b>0&&a>b)
return b;
else if(b>0&&a<b)
return rem(a,b-a);
else if(b<0)
return rem(a,b+a);
}
//-------------------------------------------------------------------------
// Function for finding the gcd of two numbers :
//-------------------------------------------------------------------------
int gcd(int a,int b)
{
if (a==0)
return b;
if(b==0)
return a;
if(a>b)
return (gcd(a%b,b));
if(b>a)
return (gcd(b%a,a));
}
//----------------------------------------------------------
// Function for poviting
//----------------------------------------------------------
void pivoting(float a[][MAX],int N,float I[][N],int k)
{
P a g e | 19
int l,m,index=0;
float max,temp;
for (l=0;l<N;l++)
{
max=a[0][k];
if(max<a[l][k])
{
max=a[l][k];
index=l;
}
}
for(m=0;m<N;m++)
{
temp=a[index][m];
a[index][m]=a[k][m];
a[k][m]=temp;
}
}
//-----------------------------------------------------------------
Runtime(operational count):
Number of divisions:
In each step for elementary transformations we have no. of divisions = n – 1
No. of steps = n
So,
No. of divisions in total n steps = n(n-1)
After getting the diagonal matrix, we have n divisions again.
Hence, total no. of divisions = n(n-1)+n = n2
No. of multiplications:
In the any of the step, we multiply n times in each row n-1 times.
Hence, total number of multiplication in each step = n(n-1)
No. of such steps = n
Hence, total no. of multiplications are = n2(n-1)
Therefore,
Operational count= n2 + n
2(n-1) = n
3
So worse time complexity is O(n3),which is polynmial time complexity.
Now we are going to give algorithm for finding inverse an element over moduli.
P a g e | 20
2.4 Chinese Remainder Theorem
The Chinese remainder theorem describes the solutions to a system of
simultaneous linear congruence‟s. The simplest situation is a system of two
congruence‟s, x ≡ a (mod m) and x ≡ b (mod n), with gcd(m, n) = 1, in which
case the Chinese remainder theorem says that there is a unique solution modulo
mn. The first recorded instance of a problem of this type appears in a Chinese
mathematical work from the late third or early fourth century. It actually deals
with the harder problem of three simultaneous congruence‟s.
Theorem 2.4.1
Let m1,m2, . . . , mk be a collection of pairwise relatively prime integers.This
means that
gcd(mi,mj) = 1 for all i ≠j.
Let a1, a2, . . . , ak be arbitrary integers. Then the system of simultaneous
congruences
x ≡ a1 (mod m1), x ≡ a2 (mod m3), . . . , x ≡ ak (mod mk)
has a solution x = c. Further, if x = c and x = c' are both solutions, then
c ≡ c'(mod m1m2. . .mk).
Proof . Suppose that for some value of ı we have already managed to find a
solution x = ci to the first ı simultaneous congruences,
x ≡ a1 (mod m1), x ≡ a2, . . . , x ≡ ai (mod mi)
For example, if i = 1, then c1 = a1 works. We are going to explain how to find a
solution to one more congruence,
x ≡ a1 (mod m1), x ≡ a2, . . . , x ≡ ai+1 (mod mi+1)
The idea is to look for a solution having the form,
xi = ci + m1m2. . .miy.
Notice that this value of x still satisfies all of the congruences, so we need
merely choose y so that it also satisfies x ≡ ai+1 (mod mi+1). In other words, we
need to find a value of y satisfying
P a g e | 21
ci + m1m2. . .miy ≡ ai+1 (mod mi+1)
Since gcd ( mi+1 , m1m2. . .mi ) = 1 , this is possible. This completes the proof of
existence.
So by using above theorem we done C++ code for solving linear equations
which can be solve by Chinese remainder theorem :
C++ source code:
//------------------------------------------------------------------
// PROGRAMME FOR SOLVING LINEAR CONGRUANCE EQUATIONS OF THE FORM :
// x=a1(mod m1),x=a2(mod m2),...........,x=ak(mod mk)
//---------------------------------------------------------- -------
#include<iostream>
#include<math.h>
using namespace std;
//------------------------------------------------------------
// function for finding gcd of two elements
//------------------------------------------------------------
int gcd(int a,int b)
{
if (a==0)
return b;
if(b==0)
return a;
if(a>b)
return (gcd(a%b,b));
if(b>a)
return (gcd(b%a,a));
}
//------------------------------------------------------------
// FUNCTION FOR FINDING MODULAR INVERSE OF AN ELEMENT
//------------------------------------------------------------
int inverse(int a,int b)// here a-->modulus,b-->element
{
int gcd,x=0,y=1,k=a;
int u=1, v=0, m, n, q, r;
gcd = b;
while (a!=0)
{
q=gcd/a; r=gcd%a;
m=x-u*q; n=y-v*q;
gcd=a; a=r; x=u; y=v; u=m; v=n;
}
while(y<0)
{
y=k+y;
}
return y;
}
//--------------------------------------------------------
// MAIN FUNCTION STARTS HERE
//--------------------------------------------------------
int main()
{
P a g e | 22
int k;
cout<<"TO SOLVE LINEAR CONGRUANCE EQUATIONS OF THE FORM :\n"<<endl;
cout<<"x=a1(mod m1),\nx=a2(mod m2),\n.\n.\n.\nx=ak(mod mk)."<<endl;
cout<<"where all mi's are primes & pair are co-prime to each
other.\n"<<endl;
cout<<"Enter no of congruence equations in The system : ";
cin>>k;
int m[k],a[k],i,n=1; //n=m1*m2*.....*mk
for(i=0;i<k;i++)
{
cout<<"Please enter a"<<i+1<<" and m"<<i+1<<" respectively : ";
cin>>a[i]>>m[i];
if(i>0)
{
if(gcd(m[i-1],m[i])!=1)
{
cout<<"\nChinese Remainder Theorem is not applicable for this
problem.\n\n";
return 1;
}
}
n=n*m[i];
}
int sol=0,B=1;
for(i=0;i<k;i++)
{
B=a[i]*(n/m[i])*inverse(m[i],n/m[i]);
sol=sol+B;
}
sol=sol%n;
cout<<"\n The Unique solution for Given system of Congruence Equations is
: "<<sol<<endl;
return 0;
}
Next we will discuss about the concept primality testing which is useful in
Public key cryptography.
P a g e | 23
CHAPTER 3
PRIME NUMBER GENERATION
In many Public key Cryptosystems, large random prime numbers are
used. They are produced by generating random numbers of the right size and by
testing whether those random numbers are prime. In this chapter, we explain
how we efficiently decide whether a given positive integer is a prime number.
The fallowing are commonly used algorithms:
3.1 Trail division:
Let n be a positive integer. We want to know whether n is a prime
number. This algorithm is based on the fallowing theorem without proof:
Theorem 3.1.1 If n is a composite positive integer, then n has a prime divisor p which is less
than or equal to √n.
The above theorem suggests the fallowing algorithm to test whether n is
prime.
Algorithm 3.1.1:
1. Input: n
2. Let m is prime ≤√n
Loop starts m=2 to √n
If m is divisor of n then return composite
Else m=next prime ≤√n
3. Loop ends
4. Return n is prime.
Running Time:
In the worst case, trial division is a laborious algorithm. If it starts from two and
works up to the square root of n, the algorithm requires
Trial divisions, where π(x) denotes the prime-counting function, the number of
primes less than x.
P a g e | 24
If n is large, then trial division becomes very inefficient. The trial division is
typically used for the numbers ≤106.
Note: It is also possible to test whether n is divisible by any odd, +ve integer
m ≤√n. It requires
trial divisions.
C++ Source code:
//--------------------------------------------------
// TRIAL DIVISION ALGORITHM FOR PRIMALITY TESTING
//--------------------------------------------------
#include<iostream>
using namespace std;
#include<math.h>
#include<stdlib.h>
int main()
{
int n,q;
cout<<”enter the Number : ”;
cin>>n;
int i=2;
do
{
if(n%i==0)
goto l1;
i++;
}while(i<=int(sqrt(n)));
cout<<n<<”is a prime number”;
exit(1);
l1:
cout<<”Not a prime number”<<”\n”;
}
//--------------------------------------------------
Output is:
Enter the number 37
P a g e | 25
37 is a prime number.
3.2 Fast powering algorithm(Modular exponentiation) :
In many Cryptosystems we reach to the point to computing large
powers of numbers over moduli the fallowing algorithm is very usefull for
this purpose:
Sequential steps of The algorithm are :
Step 1. Compute the binary expansion of A as
A = A0+A1 .2+A2.22+A3.2
3+· · ·+Ar.2
r with A0, . . . , Ar ∈ {0, 1},
where we may assume that Ar = 1.
Step 2. Compute the powers (g2)
i (mod N) for 0 ≤ i ≤ r by successive
squaring,
a0 ≡ g (mod N)
a1 ≡ a02≡ g
2 (mod N)
a2 ≡ a12≡ (g
2)
2 (mod N)
a3 ≡ a22≡ (g
2)
3 (mod N)
...
...
...
ar ≡ ar-12≡ (g
2)
r (mod N).
Each term is the square of the previous one, so this requires r
multiplications.
Step 3. Compute gA (mod N) using the formula
Note that the quantities a0, a1, . . . , ar were computed in Step 2. Thus the above
product can be computed by looking up the values of the ai’s whose exponent
Ai is 1 and then multiplying them together. This requires at most another r
multiplications.
P a g e | 26
The simple psuedocode for the above algorithm is :
Algorithm 3.2.1(Modular exponentiation)
Input: Positive integers N, g, and A.
1. Set a = g and b = 1.
2. Loop while A > 0.
3. If A ≡ 1 (mod 2), set b = b ・ a (mod N).
4. Set a = a2 (mod N) and A = [A/2].
5. If A > 0, continue with loop at Step 2.
6. Return the number b, which equals gA (mod N).
Running Time:
It takes at most 2r multiplications modulo N to compute gA. Since A ≥ 2
r, we
see that it takes at most 2 log2(A) multiplications modulo N to compute gA. Thus
even if A is very large, say A ≈ 21000
, it is easy for a computer to do the
approximately 2000 multiplications needed to calculate 2A modulo N.
C++ source code is:
// -------------------------------------------------------------
// FAST POWERING ALGORITHM (OR) SQUARE AND MULTIPLY ALGORITHM
//--------------------------------------------------------------
// Calculating (g^A)mod N
#include <iostream>
#include<math.h>
using namespace std;
int main()
{
int g,A,N,b=1;
cout<<endl<<"To find (g^A)mod N "<<"Enter the values of 'g,A and N' values
respectively : ";
cin>>g>>A>>N;
while(A>0)
{
if((A-1)%2==0)//if A=1(mod 2)
{
b=b*g;
b=b%N;//b=b*g(mod N)
}
g=g*g;
g=g%N;//g=g^2(mod N)
A=ceil(A/2);//A=[A/2]
}
cout<<endl<<"The value of (g^A)[mod N] is : "<<b<<endl;
return 0;
}
//------------------------------------------------------------
// end
//------------------------------------------------------------
P a g e | 27
3.3 Fermats test : Let n be a positive integer. We want to know whether n is a prime
number. This algorithm is based on the fallowing theorem without proof:
Theorem 3.3.1(Fermat‟s Little Theorem)
Let p be a prime number. Then ap ≡ a (mod p) for every integer a with
gcd(a,p)=1.
From above theorem we have:
Def: Let n be an odd integer and if a is an integer such that gcd (a, n) = 1 and
an-1
≠ 1 (mod n)
Then n is not prime. Such a number 'a' is called a compositeness witness for n.
It suggests the fallowing algorithm to test whether n is prime.
Algorithm 3.3.1:
1. Input: n, a value to test for primality;
2. a=2, k=n-1
3. Loop starts if a<k
if an-1
≠ 1 (mod n), then return (composite, a)
else a=a+1
4. Loop ends
5. Return probably prime
If the above algorithm outputs “(composite, a)” then we know
• n is definitely a composite number,
• a is a witness for this compositeness, in that one can verify that n is
composite by using the value of a.
If the above algorithm outputs “(Probably prime)” then
• n is a composite with probability at most 1/2k,
• n is either a prime or a so-called probable prime.
Runtime:
As we know that worse case time complexity for computing gA
(mod N) is
O (2log2A).
So worse case Time complexity for this algorithm is O (2log2(n-1)!).
P a g e | 28
C++ Source code is:
//------------------------------------------------
// PRIMALITY TESTING(FERMATS TEST)
// NOTE:Potential witness is taken as "2"
//------------------------------------------------
#include <iostream>
#include<math.h>
using namespace std;
//------------------------------------------------
// FUNCTION FOR MODULAR EXPONENTIATION
//------------------------------------------------
int mod_power(int g,int A,int N)
{
int b=1;
while(A>0)
{
if((A-1)%2==0)//if A=1(mod 2)
{
b=b*g;
b=b%N;//b=b*g(mod N)
}
g=g*g;
g=g%N;//g=g^2(mod N)
A=ceil(A/2);//A=[A/2]
}
return b;
}
//---------------------------------------
// MAIN FUNCTION STARTS HERE
//---------------------------------------
int main()
{
int N;
cout<<endl<<"Enter any +ve integer for testing its primality, N: ";
cin>>N;
if(N%2==0)
{
cout<<" '"<<N<<"' is composite Number"<<endl;
return 0;
}
int a=2;
if(mod_power(a,N-1,N)==1)
cout<<"The number '"<<N<<"' may be a prime."<<endl;
else
cout<<" '"<<N<<"' is composite Number"<<endl;
return 0;
}
Here in this algorithm there is a drawback that is, we are not able to decide
whether given number is prime or not. It is because of carmical numbers.
“Composite numbers having no witness are called Carmical numbers”
Example: 561 is a Carmical number i.e., a561
≡a(mod 561) for every integer a.
P a g e | 29
3.4 Rabin-Miller Test:
This test(for Compositeness) is better than fermats test which is also
works for Carmical numbers. The following property of prime numbers is used
to formulate the Miller–Rabin test, which has the agreeable property that every
composite number has a large number of witnesses.
Theorem 3.4.1 Let p be an odd prime and write
p − 1 = 2kq with q odd.
Let a be any number not divisible by p. Then one of the following two conditions
is true:
(i) aq is congruent to 1 modulo p.
So by using above theorem we define,
Definition(Rabin-Miller witness):
Let n be an odd number and write n − 1 = 2kq with q odd. An integer a
satisfying gcd (a, n) = 1 is called a Miller–Rabin witness for (the
compositeness of) n if both of the following conditions are true:
It suggests the fallowing algorithm to test whether n is prime.
Algorithm 3.4.1:
Input: A odd Integer n>3 to be tested, integer a as potential witness and k, a
parameter that determines the accuracy of the test
Output: composite if n is composite, otherwise probably prime
1. If n is even or 1 < gcd (a, n) < n, return Composite.
2. Write n−1 = 2kq with q odd.
3. LOOP: repeat k times:
4. Pick a random integer a in the range [2, n − 2] and Set a = aq (mod n).
5. If a ≡ 1 (mod n), then do next LOOP
6. Loop i = 0, 1, 2,. . . k−1
P a g e | 30
7. If a ≡ −1 (mod n), then do next LOOP
8. Set a = a2 mod n.
9. Increment i and loop again at Step 6.
10. Return Composite.
11.Return probably prime
By given theorem below answer the question that for which values of a we will
run The algorithm instead of running the test using a bunch of randomly
selected values of a.
Theorem 3.4.2 Let n be an odd composite number. Then at least 75% of the numbers a between
1 and n − 1 are Miller–Rabin witnesses for n.
Consider now Bob‟s (a user) quest to identify large prime numbers. He
takes his potentially prime number n and he runs the Miller–Rabin test on n for
(say)10 different values of a. If any a value is a Miller–Rabin witness for n,
then Bob knows that n is composite. But suppose that none of his a values is a
Miller–Rabin witness for n. Above Theorem says that if n were composite, then
each time Bob tries a value for a, he has at least a 75% chance of getting a
witness. Since Bob found no witnesses in 10 tries, it is reasonable to conclude
that the probability of n being composite is at most (25%)10
,which is
approximately 10−6
. And if this is not good enough, Bob can use 100 different
values of a, and if none of them proves n to be composite, then the probability
that n is actually composite is less than (25%)100
≈ 10−60
.
Runtime :
Using modular exponentiation for each iteration we need at most 2log2(n)
multiplication for each iteration. So, The running time of this algorithm
is O(k log2 n), where k is the number of different values of a we test; thus this is
an efficient, polynomial-time algorithm.
C++ source code:
//------------------------------------------------
// PRIMALITY TESTING(ROBIN MILLER TEST)
// NOTE:Potential witness is taken as "2"
//------------------------------------------------
#include <iostream>
#include<math.h>
using namespace std;
P a g e | 31
// FUNCTION FOR FINDING POWERS OF A NUMBER OVER MODULI.
int mod_power(int g,int A,int N)
{
int b=1;
while(A>0)
{
if((A-1)%2==0)//if A=1(mod 2)
{
b=b*g;
b=b%N;//b=b*g(mod N)
}
g=g*g;
g=g%N;//g=g^2(mod N)
A=ceil(A/2);//A=[A/2]
}
return b;
}
//MAIN FUNCTION STARTS HERE
int main()
{
int N;
cout<<endl<<"Enter any +ve integer for testing its primality, N: ";
cin>>N;
if(N%2==0)
{
cout<<"\n '"<<N<<"' is composite Number"<<endl;
return 0;
}
int d=N-1,k=0;
while(d%2==0)
{
d=d/2;
k=k+1;
}
int a=2;// 'a' is potential witness
l:
while(a<N-1)
{
a=mod_power(a,d,N);//a=a^d(mod N)
if((a-1)%N==1)
{
a=a+1;
goto l;
}
for(int i=0;i<k;i++)
{
if((a+1)%N==0)
{
a=a+1;
goto l;
}
a=a*a;
a=a%N;
}
cout<<" '"<<N<<"' is composite Number"<<endl;
return 1;
}
cout<<" '"<<N<<"' is Probably a prime Number"<<endl;
return 0;
}
P a g e | 32
Drawback:
The algorithm is efficient with polynomial time complexity but it it not able
to decide whether the given large random number is prime 100%.Only it gives
25% probability that the number is prime. But The algorithm also works for
Carmichael Numbers where as Fermats test does not work for them.
P a g e | 33
CHAPTER 4
FACTORING
In number theory, integer factorization or prime factorization is the
decomposition of a composite number into smaller non-trivial divisors, which
when multiplied together equals the original integer.
When the numbers are very large, no efficient integer factorization algorithm is
known. Based on the difficulty of factorisation problem we have some public
key cryptographic algorithms those are:
1. RSA cryptosystem
2. Rabin cryptosystem
4.1 RSA Cryptosystem:
The RSA crypto scheme, sometimes referred to as the Rivest–Shamir–Adleman
algorithm (Published in 1978), is currently the most widely used asymmetric
cryptographic scheme, even though elliptic curves and discrete logarithm
schemes are gaining ground.
Before going to explain about RSA we mention some theorems without proof:
Theorem 4.1.1(Euler’s Formula for pq):
Let p and q be distinct primes and let
g = gcd(p−1, q−1).
Then
a(p−1)(q−1)/g
≡ 1 (mod pq) for all a satisfying gcd(a, pq) = 1.
In particular, if p and q are odd primes, then
a(p−1)(q−1)/2
≡ 1 (mod pq) for all a satisfying gcd(a, pq) = 1
Theorem 4.1.2
Let p be a prime and let e ≥ 1 be an integer satisfying gcd(e,p−1)=1. Then e has
an inverse modulo p − 1, say
de ≡ 1 (mod p−1).
P a g e | 34
Then the congruence xe ≡ c (mod p)
has the unique solution
x ≡ cd (mod p).
The RSA public key cryptosystem relies on the difficulty of solving equations
of the form
xe ≡ c (mod N),
where now the quantities e, c, and N are known and x is the unknown.
Theorem 4.1.3
Let p and q be distinct primes and let e ≥ 1 satisfy
gcd(e, (p − 1)(q − 1)) = 1.
So, e can have an inverse modulo (p − 1) (q − 1), say
de ≡ 1 (mod (p − 1)(q − 1)).
Then the congruence
xe ≡ c (mod pq)
has the unique solution x ≡ cd (mod pq).
The RSA public key cryptosystem relies on the difficulty of solving equations
of the form
xe ≡ c (mod N)
Where now the quantities e, c, and N are known and x is the unknown. In
other words, the security of RSA relies on the assumption that it is difficult to
take eth roots modulo N. But if N is a prime then by theorem4.1.2 it is easy to
solve this problem.
It is easy to take eth
roots if the modulus is a prime p. The situation for a
composite modulus N looks similar, but there is a crucial difference. If we know
how to factor N, then it is again easy to compute eth
roots. The theorem 4.1.3
above explains how to do this if N = pq is a product of two primes.
P a g e | 35
Let Alice wants send message to Bob through insecure communication
transmitter then RSA algorithm as given below,
Bob Alice
Key Creation
Choose secrete primes p and q
Choose encryption exponent e with
gcd(e,(p-1)(q-1))=1.
Publish N=pq and e
Encryption
Choose plaintext m
Use Bobs public key (N,e) to compute
c≡me(mod N)
Send coiphertext c to Bob.
Decryption
Compute d satisfying
ed≡1(mod (p-1)(q-1))
Compute m'≡ cd (mod N)
Then m' equals the plaintext m.
The security of RSA depends on the following dichotomy:
• Setup: Let p and q be large primes, let N = pq, and let e and c be integers.
• Problem: Solve the congruence xe ≡ c (mod N) for the variable x.
• Easy: Bob, who knows the values of p and q, can easily solve for x as
described in Theorem 4.1.3.
• Hard: Eve, who does not know the values of p and q, cannot easily find x.
• Dichotomy: Solving xe ≡ c (mod N) is easy for a person who possesses certain
extra information, but it is apparently hard for all other people.
4.2 Rabin Cryptosystem
The Rabin cryptosystem also based on the difficulty of factoring
integers. For this the problem in hand is solving
c=m2(mod N)
P a g e | 36
Where N=pq, and p,q≡3(mod 4).
But if we know p,q values, it easy to solve above equation as given in next
Theorem 4.2.1 and using Chinese remainder theorem.
Theorem 4.2.1
Let p be a prime satisfying p≡3(mod 4).Let a be an integer s.t. the congruence
x2 ≡ a(mod p)
Has a solution. The solution is,
x= a(p+1)/4
(mod p).
Now we Rabin cryptosystem as given below,
Bob
Alice
Key creation
Chooses randomly two large secrete
primes p and q s.t. p,q≡3(mod 4).
Publish N=pq.
Encryption
Using public key of Bob,
Chooses plaintext m ɛ {0,1,....,N-1}.
Compute c≡m2(mod N).
Send cipher text c to Bob.
Decryption
Compute the plaintext m from c
extracting square roots of c.
Compute,
mp=c(p+1)/4
(mod p) and
mp=c(q+1)/4
(mod q)
Now uses Chinese remainder
theorem and computes,
m (mod pq) i.e.(mod N).
P a g e | 37
Advantage:
The Rabin cryptosystem has the advantage that the problem(Finding square
roots over composite moduli) on which it relies has been proved to be as hard as
integer factorization, which is not currently known to be true of the RSA
problem.
Disadvantage:
It has the disadvantage that each output of the Rabin function can be generated
by any of four possible inputs (i.e., four possible square roots of output); For
each output (i.e., ciphertext), extra complexity is required on decryption to
identify which of the four possible inputs was the true plaintext.
So, the security of above cryptosystems is depend on the problem
factoring the integers so to enhance the security we should know about
algorithms developed for factorisation.
4.3 Trail division
We discussed the trail division method for primality testing. The same
method can also be used for factorisation. But as we know, running time is very
high so it is not efficient algorithm for factorisation.
4.4 Pollards p-1 factorisation algorithm
This method is not useful for all numbers; there are certain types of numbers for
which it is quite efficient. Pollard‟s method demonstrates that there are insecure
RSA moduli that at first glance appear to be secure. This alone warrants the
study of Pollard‟s method.
Algorithm 4.4.1
Input: Integer N to be factored.
Output: a non-trivial factor of N or failure
1. Set a = 2 (or some other convenient value).
2. Loop j = 2, 3, 4, . . . up to a specified bound n.
3. Set a = aj mod N.
4. Compute d = gcd(a − 1,N).
5. If 1 < d < N then success, return d.
6. Increment j and loop again at Step 2.
P a g e | 38
7. Return failure.
NOTE: We can observe in the algorithm that in each iteration we are nothing
but calculating the value aj!
(mod N).But as shown in the algorithm it is
equivalent to calculate aj (mod N) in each iteration. So finally we are only
calculating an!
(mod N) in Total algorithm.
Runtime:
The fast exponentiation algorithm gives a method
for computing ak (mod N) in at most 2log2 k steps, where each step is a
multiplication modulo N. Stirling‟s formula
ln(n!) = n ln(n) − n + ½ ln(2πn) + O(1/n)
says that if n is large, then n! is approximately equal to (n/e)n. So we can
compute an!
(Mod N) in 2n log2(n) steps. Thus it is feasible to compute
an!
(mod N) for reasonably large values of n. So time complexity for this
algorithm is O (2n log2(n) ).
C++ source code is:
//----------------------------------------------------------
// POLLARDS P-1 FACTORISATION METHOD
//----------------------------------------------------------
#include <iostream>
#include<math.h>
using namespace std;
//-----------------------------------------
//FUNCTION FOR FINDING GCD OF TWO NUMBERS
//-----------------------------------------
int gcd(int a,int b)
{
if((a<0)||(b<0))
{
cout<<"Error";
return 0;
}
if (a==0)
return b;
if(b==0)
return a;
if(a>b)
return (gcd(a%b,b));
if(b>a)
return (gcd(b%a,a));
}
//----------------------------------------------------
// FUNCTION FOR FAST POWERING
//----------------------------------------------------
P a g e | 39
int mod_power(int g,int A,int N)
{
int b=1;
while(A>0)
{
if((A-1)%2==0)//if A=1(mod 2)
{
b=b*g;
b=b%N;//b=b*g(mod N)
}
g=g*g;
g=g%N;//g=g^2(mod N)
A=ceil(A/2);//A=[A/2]
}
return b;
}
//------------------------------------------------
// MAIN FUNCTION STARTS HERE
//-------------------------------------------------
int main()
{
int N,a=2,B,i;//B->bound
cout<<"Enter the number to be factored : ";
cin>>N;
for(i=2;i<N-1;i++)
{
a=mod_power(a,i,N);
int d=gcd(a-1,N);
if(d>1&&d<N)
{
int c=N/d;
cout<<"The two factors of '"<<N<<"' are: '"<<d<<"' and '"<<c<<"'."<<endl ;
return 0;
}}
return 0;
}
4.5 Fermat’s factorisation algorithm
Consider an odd positive integer n, and suppose that
n = ab
where a and b are integers. (Note that since n is odd, both a and b must be odd.)
Now, note that we can write n as the difference of two squares
n = s2 - t
2
if we have
s = (a + b)/2, and t = (a - b)/2.
Note that both s and t are integers, since both a and b are odd. Similarly, if we
have an odd positive integer n that is the difference of two squares, say
n = x2-y
2
then we can factor this integer into
n = cd
where
c = (x + y), and d = (x -y).
P a g e | 40
Thus, we can approach the problem of factoring an odd positive integer n by
looking for squares whose difference is n, rather than looking directly for
factors of n. That is, we look for integer solutions of the equation
n = x2-y
2.
We can do this by rewriting the previous equation in this way:
Y2 = x
2- n.
and search for perfect squares of the form x2-n. We can do this sequentially; we
start with m, the smallest integer greater than the square root of n, and look for
perfect squares in the sequence
m2-n, (m + 1)
2 -n, (m + 2)
2 -n, . . .
This search is guaranteed to end, since m will have to go no further than
m = (n + 1)/2, since:
((n + 1)/2)2-n = ((n-1)/2)
2
and all the terms are integers. To see that the previous equation is true, note that
((n + 1)/2)2-((n-1)/2)
2 = (n
2 + 2n + 1)/4 -(n
2- 2n + 1)/4 = 4n/4 = n.
(However, if we do go this far, note that we have only obtained the trivial
factorization n = n۰1).
Algorithm 4.5.1
Input: Integer N to be factored.
Output: a non-trivial factor of N 1. Set i =smallest integer >square root of N
2. Set k= (N+1)/2
3. Loop, Maximum k repetitions
4. Calculate T=i2 –N
5. If T is perfect square then Return ( i+square_root(T), i-square_root(T) )
6. Increment i (i.e. i=i+1) and loop again at STEP 3
Runtime :
Hopefully we can see how inefficient this method of factoring can be. It can be
even worse than the trial division method, for trial division never has to test
more than √n integers, but with the Fermat method it may be necessary to
search as many as (n + 1)/2-√n integers before the procedure is guaranteed to
terminate. As the integer n gets larger, the quantity (n + 1)/2-√n becomes much
larger than √n. So worse time complexity for this algorithm is
О((n + 1)/2-√n) .
The Fermat factorization method is most efficient when the two factors of n, say
n = ab = x2 - y
2 = (x + y)(x - y)
P a g e | 41
are close together (thereby making x and y close together). This keeps the search
of the sequence
m2-n, (m + 1)
2 -n, (m + 2)
2 -n, . . .
relatively short.
C++ Source Code:
//--------------------------------------------------------------------
// FERMATS FACTORISATION METHOD(Via Difference of Squares)
//--------------------------------------------------------------------
#include <iostream>
#include<math.h>
using namespace std;
int main()
{
int N,T,i=floor(sqrt(N));
cout<<"Enter the number to be factored : ";
cin>>N;
while(i<=(N+1)/2)
{
T=(i*i)-N;
int K=sqrt(T);
if(K==sqrt(T))
{
cout<<"Factors of '"<<N<<"' are : "<<i+K<<" and "<<i-K<<endl;
return 0;
}
i=i+1;
}
return 0;
}
P a g e | 42
CHAPTER 5
DISCRETE LOGARITHMIC PROBLEM
Many of the most commonly used cryptography systems are based on the
assumption that the discrete log is extremely difficult to compute; the more
difficult it is, the more security it provides a data transfer. One way to increase
the difficulty of the discrete log problem is to base the cryptosystem on a larger
group. In this chapter we discuss Algorithms solving Discrete logarithm
problems and some cryptosystems based on this problem.
Theorem 5.0 (Primitive Root Theorem)
Let p be a prime number. Then there exists an element g ɛ Fp* whose powers
give every element of Fp*, i.e.,
Fp*
= {1, g, g2, g
3, . . . , g
p−2}.
Elements with this property are called primitive roots of Fp or generators
of Fp*. They are the elements of Fp
* having order p − 1.
By above theorem, we can guarantee the solution to the below given problem:
Definition (Discrete logarithm problem)
Let g be a primitive root for Fp and let h be a nonzero element
of Fp. The Discrete Logarithm Problem (DLP) is the problem of finding an
exponent x such that
gx ≡ h (mod p).
The number x is called the discrete logarithm of h to the base g and is denoted
by logg(h).
We can define DLP over a Group as follows:
“Let G be a group whose group law we denote by the symbol *.
The Discrete Logarithm Problem for G is to determine, for any two given
elements g and h in G, an integer x satisfying
g *g* g * . . .* g( x times)= h. ”
There are faster ways to solve the DLP in Fp*, some of which are
very fast but work only for some primes, while others are less fast, but work for
all primes. We mention them here,
P a g e | 43
1. Shanks Baby step-Giant step algorithm
2. Pollards ρ (rho) algorithm
3. Pohling Hellmann algorithm
4. Index calculus algorithm
The Pohlig–Hellman algorithm shows that if p− 1 factors entirely into a
product of small primes, then the DLP is quite easy. For arbitrary primes, the
shanks baby giant step algorithm described in solves the DLP in O(√p log p)
steps, which is much faster than O(p),but still exponential. Even better is the
index calculus algorithm solves the DLP in
O (ec√(log p)(log log p)
) steps,
so it is a sub exponential algorithm. Maximum fastest algorithm for solving
DLP is only sub exponential so we consider DLP with large p as a hard
problem. This hardness gives the security to the cryptosystems based on DLP.
5.1 Trivial brute-force algorithm
Let G be a group and let g ∈ G be an element of order N and note that gN = e
and that no smaller positive power of g is equal to the identity element e.
5.1.1 Algorithm
Simply make a list of the values g
x for x = 0, 1, 2,. . . N −1. Note that each
successive value may be obtained by multiplying the previous value by g.
If a solution to gx = h exists, then h will appear in your list.
Runtime:
By using above algorithm the discrete logarithm problem
gx = h
can be solved in O (N) steps, where each step consists of multiplication by g.
5.2 Shanks Baby step-Giant step algorithm
This algorithm is due to shanks. It is an example of a collision, or meet-
in-the-middle, algorithm. Shanks‟s algorithm works in any group, not just Fp*.
It is the just improvement of above brute force algorithm.
P a g e | 44
Let G be a group and let g ɛ G be an element of order N ≥ 2. The following
algorithm solves the discrete logarithm problem gx = h .
5.2.1 Algorithm
Input: Order of the group N, g and h.
1. Let n = 1+[√N], so in particular, n >√N.
2. Let x=qn+r , 0≤r<n. Then create two lists given below.
3. Baby steps(list 1):
Ƀ:= {( hg-r
, r ): 0≤ r <n }
If any pair of Ƀ =( 1 , r ) then Return r
4. Else Giant steps(List 2):
δ = gn
and Ğ={ δ q :q=1,2,3,..........n}
5. Find a match between the two lists, say δ q= hg
-r for particular values of
q and r .
6. Then Return qn+r
Runtime:
For creating two lists takes approximately 2n multiplications. Assuming that a
match exists, we can find a match in a small multiple of log(n) steps using
sorting and searching algorithms. So step5 takes O (log n) steps. Hence total
Running time for The algorithm is O (n log (n)) =O (√N log (N)).
C++ source code :
//---------------------------------------------------------------
// DLP (DESCRETE LOGARITHMIC PROBLEM) //
// SHANKS BABY STEP-GIANT STEP ALGORITHM //
//---------------------------------------------------------------
#include<iostream>
#include<math.h>
using namespace std;
//------------------------------------------------------------
// FUNCTION FOR FINDING INVERSE
//------------------------------------------------------------
int inverse(int a,int b)
{
int gcd,x=0,y=1,k=a;
int u=1, v=0, m, n, q, r;
gcd = b;
P a g e | 45
while (a!=0)
{
q=gcd/a; r=gcd%a;
m=x-u*q; n=y-v*q;
gcd=a; a=r; x=u; y=v; u=m; v=n;
}
while(y<0)
{
y=k+y;
}
return y;
}
//---------------------------------------------------------
// FUNCTION FOR FINDING POWERS OF A NUMBER OVER MODULI.
//---------------------------------------------------------
int mod_power(int g,int A,int N)
{
int b=1;
while(A>0)
{
if((A-1)%2==0)//if A=1(mod 2)
{
b=b*g;
b=b%N;//b=b*g(mod N)
}
g=g*g;
g=g%N;//g=g^2(mod N)
A=ceil(A/2);//A=[A/2]
}
return b;
}
//--------------------------------------------------------
// MAIN FUNCTION STARTS HERE
//--------------------------------------------------------
int main()
{
int n,m,g,l,i;
//n->order of field,m->[root of(n)]+1 and DLP is:g^x=l
// INPUT:
cout<<"\n Enter the order of finite field(Fp*) : ";
cin>>n;
cout<<"\n Enter the generator of the field : ";
cin>>g;
cout<<"\n Enter the element of the field for which you want to find dlog :
";
cin>>l;
// m=[sqrt(n)]+1 and x=q*m+r,0<=r<m
m=ceil(sqrt(n))+1;
int B[m];
//----------------------------------------------
// BABY STEPS :
// B={(l*[g^-r],r)/0<=r<m}
//----------------------------------------------
cout<<"\n Baby step result is:\n-------------------------------------------
-------\n{ ("<<l<<",0) , ";
B[0]=l;
for(i=1;i<m;i++)
{
B[i]=B[i-1]*inverse(n,g);
B[i]=B[i]%n;
cout<<"("<<B[i]<<","<<i<<") ";
P a g e | 46
if(B[i]==1)
{
cout<<endl<<"DESCRETE LOG OF '"<<l<<"' IS : "<<i<<endl<<endl;
return 0;
}
}
cout<<"}"<<endl;
//-------------------------------------------------------------------------
----------------
// GIANT STEPS :
// 1) D=(g^m)
// 2)FINDING (D^q) WHERE q=1,2,3,....... AND COMPARING EACH VALUE WITH BABY
STEP RESULTS.
//-------------------------------------------------------------------------
----------------
int D=mod_power(g,m,n);
int j=1;
while(1)
{
for(i=0;i<m;i++)
{
if(mod_power(D,j,n)==B[i])
{
cout<<endl<<"DESCRETE LOG OF '"<<l<<"' IS : "<<(j*m)+i<<endl<<endl;
return 0;
}}
j=j+1;
}
return 0;
}
//---------------------------------------------------------------------
This algorithm is slower algorithm.The public key cryptosystems depend upon
DLP are:
1. Diffie Hellmann key exchange
2. ElGamal Cryptosystem
3. Mussey Omura Cryptosystem.
We will discuss above Crypto systems after discussing the more efficient
algorithms to solve DLP.
P a g e | 47
References
1. Jeffrey Hoffstein,Jill Pipher,Joseph H.Silverman;An Introduction to
mathematical Cryptography(1st edition) ; Springer, ISBN-10: 0387779930, August 12, 2008.
2. Alfred J. Menezes,Paul C. van Oorschot,Scott A. Vanstone;Hand book of Applied Cryptography; CRC Press,ISBN: 0-8493-8523-7,October 1996.
3. Christof paar,Jan pelzl;Understanding Cryptography(1 st edition);Springer, ISBN-10: 3642041000 , July 8, 2010.
4. Nigel Smart; Cryptography: An Introduction(3rd Edition) ,McGraw Hill, ISBN: 0077099877, 2002,2009 .
5. Johannes Buchmann; Introduction to Cryptography; Springer, ISBN-10: 0387950346, December 21, 2000 .