0

For a project in university I got the following set up:

  • Public key (p, g, h)
  • Two ciphertext-files: (c1, c2) & (c3, c4)
  • Signature files of the above mentioned files: (r1, s1) & (r2, s2)

The goal is to recover the plaintexts.

I recognized from the signature files, that the given r-values are the same (r1 = r2 = r). This leads to the possibility of re-calculating the used private key see.

Basically I need the two algorithms:

k ≡ (m1 − m2)(s1 − s2)^−1 mod (p−1)

k ≡ (m1 / (s1 - s2) - m2 / (s1 - s2)) mod (p-1)

and then

x ≡ (m1 − k*s1)r^−1 mod (p−1)

x ≡ (m1 / r - k * s1 / r) mod (p-1)

So I thought that writing a python program implementing the algorithms mentioned in the link should not be that hard. But I got stucked. For some reasons I don't get the right values from my calculations. Maybe someone can give me some nudge in here?

import random
import base64
from gmpy2 import *
from Crypto.Util.number import inverse
from binascii import hexlify, unhexlify

g = 262470350957996892686231567...
p = 394020061963944792122790401...
h = 114121123070543781308127611...

def getSign(file):
    enc_file = open(file, "rb")
    enc_byte = enc_file.read()
    r, s = (enc_byte.decode("utf-8")).split()
    return r, s

def getMess(file):
    enc_file = open(file, "rb")
    enc_base64 = enc_file.read()
    enc_byte = base64.decodebytes(enc_base64)
    c1, c2 = (enc_byte.decode("utf-8")).split()
    c1, c2 = int(c1), int(c2)
    return c1, c2

def decrypt(c1, c2, a):
        df = pow(c1, a, p)
        m = (c2 * inverse(df, p)) % p
        return m

r1, s1 = getSign("secret1.enc.sig")
c11, c12 = getMess("secret1.enc")
r2, s2 = getSign("secret2.enc.sig")
c21, c22 = getMess("secret2.enc")

if(r1 == r2):
    r = int(hexlify(str.encode(r1)), 16)
    
    s1_hex = hexlify(str.encode(s1))
    s1_int = int(s1_hex, 16)
    
    s2_hex = hexlify(str.encode(s2))
    s2_int = int(s2_hex, 16)

    m1 = c12
    m2 = c22
    
    ds = s1_int - s2_int
    ps = p - 1
    k1 = (m1 * inverse(ds, ps)) % ps
    k2 = (m2 *  inverse(ds, ps)) % ps
    k = k1 - k2
    print("k  = {}".format(k))

    x1 = (m1 * inverse(r, ps)) % ps
    x21 = k * s1_int
    x2 = (x21 * inverse(r, ps)) % ps
    x = x1 - x2
    
    dm = decrypt(c21, c22, x)
    x = format(dm, 'x')
    message = unhexlify(x)
    
    print("g  = {}".format(g))
    print("p  = {}".format(p))
    print("h  = {}".format(h))
    print("r  = {}".format(r))
    print("k  = {}".format(k))
    print("x  = {}".format(x))
    print("Decrypted Hex (x)     : {}".format(x))
    print("Decrypted Message     : {}".format(message))
Mofro
  • 1
  • 2
  • `//` is the integer division operator in python3, `/` performs floating point divides. – President James K. Polk Jun 20 '20 at 16:24
  • Thanks for your remark! I changed it, but either there is still some calculation issue or I misunderstood something completely when re-calculating.. – Mofro Jun 21 '20 at 07:26
  • I didn't look in detail at your code, but when doing division mod p you should actually be calling the `inverse()` function. So instead of `a // b` you should compute `(a * inverse(b, p)) % p`. – President James K. Polk Jun 21 '20 at 13:46
  • Changed it - Thanks! Didn't changed the result: I still get rubbish as decrypted output.. – Mofro Jun 21 '20 at 19:12

0 Answers0