You are on page 1of 10

CSL7480: CRYPTOGRAPHY

Assignment 5
Prepared by Manveer Singh Rathore

Question 1
A. Compute the SHA256 hash of your email-id. Let it be h1.

email = rathore.3@iitj.ac.in

h1 = ffd3030ae4c0cc5b13599a7f6f439a522c19ae54f875f40430daf4b10b172a49

B. Another IIT Jodhpur email-id which has the hash value h2, such that h1 and h2
match in the first 16 bits ( first 4 hexa numbers ).

another email having same first 16 bit ( 4 hexa numbers )

email_2 = syfiluhkk@iitj.ac.in

h2 = ffd34eaf46c9f817429b1e5f8d317edd918ad6c0d9109aaf870cf2d2c970b811

C. Repeating above 10 times.

Below are the number of calls made in every trial to find such id.

76139 47813 24021 67118 36643

30119 80159 8569 63257 4599

Average number of calls ( t ) = 438437 ÷ 10 = 43843


t = 43843
log2(t) = 15.42

D. Analysis

There are 216 possible values for the first 16 bits of any Hash generated using
SHA256.

So given the hash of an email id, if we choose another email id randomly then the
probability that the first 16 bits of both their hash match is 1/216.

So it is highly probable that after 216 calls we will get another email id.
That's why our log2(t) was coming out to be approximately equal to 16.

1
E. Two IITJ email having same 16 bit of hash

x@iitj.ac.in = gtbctwsgv@iitj.ac.in

Hash = 916f73dea52ef6979bf7332f155a0a8b6e24556abb26278e7e4d37895dccca4c

y@iitj.ac.in = pryuhyjcz@iitj.ac.in

Hash = 916f833f59c1d178802063b522a645f7234753e3b0f21d0207753667c23365a7

F. Repeat above 10 times

231 336 578 420 310

171 659 249 439 591

Average number of calls ( t ) = 3984 / 4 = 398

log2(t) = 8.63

G. Analysis

Here we are getting t approximately equal to 28.

After 28 calls we will have 28 * (28 - 1 ) pairs = 216.

So using the birthday paradox we can see that it is very highly probable that one
of the pairs will have the same first 16 bits of Hash.

And hence only 28 calls are required to find a suitable pair.

Code For part A, B, C, D

import hashlib

import random

str = "rathore.3@iitj.ac.in"

result = hashlib.sha256(str.encode())

print("SHA256 Encyption of my email id : "+result.hexdigest())

print()

ori = result.hexdigest()

for i in range (0,10000000,1):

2
s = ""

for x in range(0,9,1):

a = random.randint(0,25)

s= s + chr (ord ('a') + a)

s = s + "@iitj.ac.in"

result = hashlib.sha256(s.encode())

ost = result.hexdigest()

if(ost[0:4]==ori[0:4]):

print("Another IITJ email having same first 16 bit : "+s)

print()

print("Number of calls required to find another IITJ email as


required : ")

print(i)

break

print ("\r")

Code for Part E, F, G

import hashlib

import random

mapp = {}

for i in range (0,10000000,1):

s = ""

for x in range(0,9,1):

a = random.randint(0,25)

3
s= s + chr (ord ('a') + a)

s = s + "@iitj.ac.in"

result = hashlib.sha256(s.encode())

ost = result.hexdigest()

if(ost[0:4] in mapp):

print("x@iitj.ac.in : " + mapp[ost[0:4]])

print("y@iitj.ac.in : " + s)

print()

print("Number of calls required : ")

print(i)

break

mapp[ost[0:4]]=s

print ("\r")

Question 2
A. Implement the Miller-Rabin primality test.

import random

def miller_rabin(n):

if (n <= 1 or n == 4):

return False

if (n <= 3):

return True

d = n - 1

while (d % 2 == 0):

4
d //= 2

for i in range(0,100,1):

d1,d2=d,d

a = random.randint(3, n - 2)

x = 1

a = a % n

while (d2 > 0):

if (d2 & 1):

x = (x * a) % n

d2 = d2>>1

a = (a * a) % n

if (x == 1 or x == n - 1):

return True

while (d1 != n - 1):

x = (x * x) % n

d1 *= 2

if (x == 1):

return False

if (x == n - 1):

x=-1

break

if(x==-1):

continue

return False

return True

aa = 0

5
while 1:

n = random.randint(0,1<<513-1)

if (miller_rabin(n)):

print(n)

aa = aa+1

if aa == 2 :

break

B. Generate random primes p and q of size 512 bits each.

Randomly generated 512 bit numbers p and q, checked with the miller_rabin test
are given below.
p:
417657490309640327586858116010341686020932847660392697068921214501091
544979058170931423372452436040001206845120686051090940744101112036729
0705250868635701

q:
222874305874695584090616150466783128329444894868415622437426307223300
369722134873487527211330130331059139530058611963573089838018043683879
3249556890325879
C. Implement Extended Euclidean Algorithm (EEA) to compute gcd and the
linear combi-nation for two (long) integers.
def EEA_gcd(p, q):
if p==0:
return 0,1,q
a, b, ans=EEA_gcd(q%p,p)
return (b-(q//p)*a),a,ans
p, q = 35,4
x,y,g = EEA_gcd(p, q)
print("Below is the Linear Combination of above two number :")
print(x,"*",p,"+",y,"*",q,"=",g)
print("Below is the GCD of above two number : ")
print(g)

6
D. Set n = p · q and compute d = e−1mod φ(n) by using the EEA
φ(n) = (p-1)*(q-1)
We know that,
1. gcd(e,φ(n)) = 1
2. d*e = k*φ(n) + 1
=> d*e - k*φ(n) = 1
e= 7 hence gcd (e,φ(n)) = 1
And hence
d=
398936242483407793916164418114699275118004842951657198414995295986616
691838888414976157868490541214430950929854734128454605868124006077109
664121917800144947466459145487897154253795728190735432439471769472151
135075549678841806012900346652512209296079303342332282045634139528175
7367585190050172676089541990543
E. generate a random message of 1024 bits, encrypt it using the textbook RSA,
decrypt the ciphertext, and show that you get the same message after
decryption.
import random
def power(x, y, p):
res = 1
x = x % p
while (y > 0):
if (y & 1):
res = (res * x) % p
y = y>>1;
x = (x * x) % p
return res
stri = {}
cipher = {}
decypt = {}
print("Random plaintext : ")
for i in range (0,128):
a=random.randint(50,110)
stri[i]=a

7
print(chr(a),end="")
print()
d=39893624248340779391616441811469927511800484295165719841499529598
6616691838888414976157868490541214430950929854734128454605868124006
0771096641219178001449474664591454878971542537957281907354324394717
6947215113507554967884180601290034665251220929607930334233228204563
41395281757367585190050172676089541990543
e=7
p, q =
4176574903096403275868581160103416860209328476603926970689212145010
9154497905817093142337245243604000120684512068605109094074410111203
67290705250868635701,
2228743058746955840906161504667831283294448948684156224374263072233
0036972213487348752721133013033105913953005861196357308983801804368
38793249556890325879
phi=(p-1)*(q-1)

for i in range (0,128):


cipher[i]=stri[i]**e
print(cipher[i],end="")
print()
for i in range (0,128):
decypt[i]=power(cipher[i],d,p*q)
a=decypt[i]
print(chr(a),end="")

Output :

Question 3
A. If a cyclic group has n elements then show that it has φ(n) generators.

8
Suppose G is a finite cyclic group with order n.

Let g be the generator of G and hence any element of G will be of the form

gx where x ≥ 0 and x ≤ n-1

We know that order of any finite cyclic group with generator gr is as follow :

o(gr) = o(g) / gcd(n,r)

=> if o(gr) = n

=> gcd(n,r) = 1

Suppose there is a set GS having all the possible generators.

=> GS = { gr | 1 < r < n and gcd ( n, r ) = 1 }

We can observe that |GS| = number of positive integers relatively prime to n.

We know that

φ(n) = number of positive integers relatively prime to n.

=> |GS| = φ(n)

=> There are φ(n) generators in a cyclic group having n elements.

B. Generate a random Sophie-Germain prime p of size 512 bits.

1281865814363518305056821462401885293296419202811638351643305266558684
1299356438331390400976138746476092937808504760478578363173241384590498
268709859817591

Is a Sophie-Germain prime. It was randomly generated using


random.randint(0,1<<513-1) and then verified using miller-rabin.

C. Find a generator of the group Z∗(p) for the prime you generated above by
randomly picking elements from the group.

We know that,

1. P is a prime number
2. Size of the set of all generators = φ(n).
3. If n is prime then φ(n) = (n-1)

3rd point means that all element of group Z*(p) is a generator if p is prime

=> for given situation where p the number generated in previous step which is a
sophie germain number so all elements of Z*(p) is a generator.

9
Hence 5 is a generator of Z*(p) {where p is a sophie-Germain prime found in last part.

D. Implement the Diffie-Hellman Key Exchange.

import random

def power(x, y):

ans = 1

while (y > 0):

if (y & 1):

ans = (ans * x)

x = (x * x)

y=y>>1

return ans

#g is public information and a and b are generated randomly by


parties A and B

g,a,b=50,random.randint(2,10),random.randint(2,10)

matb = power(g,a) #message from A to B

mbta = power(g,b) #message from B to A

k1 = power(mbta,a) #key of A

k2 = power(matb,b) #key of B

print("A have key =",k1)

print("B have key =",k2)

10

You might also like