Ejemplo n.º 1
0
def forge(data, pk, r, s, k):
    p, q, g, y = pk['p'], pk['q'], pk['g'], pk['y']
    h1 = int(hashlib.sha1(data.encode()).hexdigest(), 16)
    h2 = int(hashlib.sha256(data.encode()).hexdigest(), 16)
    kinv = _modinv(k, q)

    x = ((s * k - h1) * _modinv(r, q)) % q
    assert y == pow(g, x, p), 'Error extracting private key'

    forge_s = kinv * (h2 + r * x) % q
    signature = encode_dss_signature(r, forge_s).hex()
    return signature, data
Ejemplo n.º 2
0
def calculate_ds_parameters(privkey, priv_key_pass, hmac_key, idf_target):
    private_key = load_privatekey(privkey, priv_key_pass)
    if not isinstance(private_key, rsa.RSAPrivateKey):
        print('ERROR: Only RSA private keys are supported')
        sys.exit(-1)
    if hmac_key is None:
        print('ERROR: hmac_key cannot be None')
        sys.exit(-2)

    priv_numbers = private_key.private_numbers()
    pub_numbers = private_key.public_key().public_numbers()
    Y = priv_numbers.d
    M = pub_numbers.n
    key_size = private_key.key_size
    if key_size not in supported_key_size[idf_target]:
        print('ERROR: Private key size {0} not supported for the target {1},\nthe supported key sizes are {2}'
              .format(key_size, idf_target, str(supported_key_size[idf_target])))
        sys.exit(-1)

    iv = os.urandom(16)

    rr = 1 << (key_size * 2)
    rinv = rr % pub_numbers.n
    mprime = - rsa._modinv(M, 1 << 32)
    mprime &= 0xFFFFFFFF
    length = key_size // 32 - 1

    # get max supported key size for the respective target
    max_len = max(supported_key_size[idf_target])
    aes_key = hmac.HMAC(hmac_key, b'\xFF' * 32, hashlib.sha256).digest()

    md_in = number_as_bytes(Y, max_len) + \
        number_as_bytes(M, max_len) + \
        number_as_bytes(rinv, max_len) + \
        struct.pack('<II', mprime, length) + \
        iv

    # expected_len = max_len_Y + max_len_M + max_len_rinv + (mprime + length packed (8 bytes))+ iv (16 bytes)
    expected_len = (max_len / 8) * 3 + 8 + 16
    assert len(md_in) == expected_len
    md = hashlib.sha256(md_in).digest()
    # In case of ESP32-S2
    # Y4096 || M4096 || Rb4096 || M_prime32 || LENGTH32 || MD256 || 0x08*8
    # In case of ESP32-C3
    # Y3072 || M3072 || Rb3072 || M_prime32 || LENGTH32 || MD256 || 0x08*8
    p = number_as_bytes(Y, max_len) + \
        number_as_bytes(M, max_len) + \
        number_as_bytes(rinv, max_len) + \
        md + \
        struct.pack('<II', mprime, length) + \
        b'\x08' * 8

    # expected_len = max_len_Y + max_len_M + max_len_rinv + md (32 bytes) + (mprime + length packed (8bytes)) + padding (8 bytes)
    expected_len = (max_len / 8) * 3 + 32 + 8 + 8
    assert len(p) == expected_len

    cipher = Cipher(algorithms.AES(aes_key), modes.CBC(iv), backend=default_backend())
    encryptor = cipher.encryptor()
    c = encryptor.update(p) + encryptor.finalize()
    return c, iv, key_size
Ejemplo n.º 3
0
def signMessageBlockAndCommitment(sk, pk, U, ms):
    R = RepresentToPublicKey(pk, ms)
    vTilde = secure_randint(pk.Params.Lv)
    twoLv = 1 << (pk.Params.Lv - 1)
    v = twoLv + vTilde

    numerator = FP2Value(pk.N, pk.S).intpow(v).a
    numerator = (numerator * R * U) % pk.N

    invNumerator = _modinv(numerator, pk.N)
    Q = (pk.Z * invNumerator) % pk.N

    e = randomPrimeInRange(pk.Params.Le - 1, pk.Params.LePrime - 1)

    order = sk.PPrime * sk.QPrime
    d = _modinv(e, order)
    A = FP2Value(pk.N, Q).intpow(d).a

    return CLSignature(A, e, v, None)
Ejemplo n.º 4
0
def calculate_ds_parameters(privkey, priv_key_pass):
    private_key = load_privatekey(privkey, priv_key_pass)
    if not isinstance(private_key, rsa.RSAPrivateKey):
        print("Only RSA private keys are supported")
        sys.exit(-1)

    priv_numbers = private_key.private_numbers()
    pub_numbers = private_key.public_key().public_numbers()
    Y = priv_numbers.d
    M = pub_numbers.n
    key_size = private_key.key_size
    supported_key_size = [1024, 2048, 3072, 4096]
    if key_size not in supported_key_size:
        print("Key size not supported, supported sizes are" +
              str(supported_key_size))
        sys.exit(-1)

    hmac_key = os.urandom(32)
    with open(hmac_key_file, 'wb') as key_file:
        key_file.write(hmac_key)

    iv = os.urandom(16)

    rr = 1 << (key_size * 2)
    rinv = rr % pub_numbers.n
    mprime = -rsa._modinv(M, 1 << 32)
    mprime &= 0xFFFFFFFF
    length = key_size // 32 - 1

    aes_key = hmac.HMAC(hmac_key, b"\xFF" * 32, hashlib.sha256).digest()

    md_in = number_as_bytes(Y, 4096) + \
        number_as_bytes(M, 4096) + \
        number_as_bytes(rinv, 4096) + \
        struct.pack("<II", mprime, length) + \
        iv
    assert len(md_in) == 12480 / 8
    md = hashlib.sha256(md_in).digest()

    # Y4096 || M4096 || Rb4096 || M_prime32 || LENGTH32 || MD256 || 0x08*8
    p = number_as_bytes(Y, 4096) + \
        number_as_bytes(M, 4096) + \
        number_as_bytes(rinv, 4096) + \
        md + \
        struct.pack("<II", mprime, length) + \
        b'\x08' * 8

    assert len(p) == 12672 / 8

    cipher = Cipher(algorithms.AES(aes_key),
                    modes.CBC(iv),
                    backend=default_backend())
    encryptor = cipher.encryptor()
    c = encryptor.update(p) + encryptor.finalize()
    return c, iv, key_size
Ejemplo n.º 5
0
def get_private_key(public_key: RsaKey, prime_factor: int):
    n = public_key.n
    e = public_key.e
    p = prime_factor
    q = int(n // p)
    assert p * q == n

    # Phi
    ϕ = (p - 1) * (q - 1)
    d = _modinv(e, ϕ)
    assert (e * d) % ϕ == 1

    return RSA.construct((n, e, d, p, q))
Ejemplo n.º 6
0
def _get_sbv2_rsa_primitives(public_key):
    primitives = namedtuple('primitives', ['n', 'e', 'm', 'rinv'])
    numbers = public_key.public_numbers()
    primitives.n = numbers.n  #
    primitives.e = numbers.e  # two public key components

    # Note: this cheats and calls a private 'rsa' method to get the modular
    # inverse calculation.
    primitives.m = -rsa._modinv(primitives.n, 1 << 32)

    rr = 1 << (public_key.key_size * 2)
    primitives.rinv = rr % primitives.n
    return primitives
Ejemplo n.º 7
0
def rsa_pq(p, q, e=65537):
    n = p * q
    public_numbers = rsa.RSAPublicNumbers(e=e, n=n)
    d = rsa._modinv(e, (p - 1) * (q - 1) // 2)
    private_numbers = rsa.RSAPrivateNumbers(
        public_numbers=public_numbers,
        p=p,
        q=q,
        d=d,
        dmp1=rsa.rsa_crt_dmp1(d, p),
        dmq1=rsa.rsa_crt_dmq1(d, q),
        iqmp=rsa.rsa_crt_iqmp(p, q),
    )
    return private_numbers.private_key(backend)
Ejemplo n.º 8
0
def sign(ctf_key, data):
    data = data.encode("ascii")
    pn = ctf_key.private_numbers()
    g = pn.public_numbers.parameter_numbers.g
    q = pn.public_numbers.parameter_numbers.q
    p = pn.public_numbers.parameter_numbers.p
    x = pn.x
    k = random.randrange(2, q)
    kinv = _modinv(k, q)
    r = pow(g, k, p) % q
    h = hashlib.sha1(data).digest()
    h = int.from_bytes(h, "big")
    s = kinv * (h + r * x) % q
    return (r, s)
Ejemplo n.º 9
0
def sign(ctf_key, data):
    data = data.encode("ascii")
    pn = ctf_key.private_numbers()
    g = pn.public_numbers.parameter_numbers.g
    q = pn.public_numbers.parameter_numbers.q
    p = pn.public_numbers.parameter_numbers.p
    x = pn.x
    k = random.randrange(2, q)
    kinv = _modinv(k, q)
    r = pow(g, k, p) % q
    h = hashlib.sha1(data).digest()
    h = int.from_bytes(h, "big")
    s = kinv * (h + r * x) % q
    return (r, s)
Ejemplo n.º 10
0
    def normalize(self):
        """
        Normalize to aC = 1: this is the best human-readable form.

        Ex. '20/4' becomes '5'
            '4 + 4x/2 + 2x' becomes '2 + 2x/1 + x'
        """
        mp = _modinv(self.aC % self.mod, self.mod)
        if mp > 0:
            a = (self.a * mp) % self.mod
            b = (self.b * mp) % self.mod
            c = (self.c * mp) % self.mod
            aC = 1
            bC = (self.bC * mp) % self.mod
            cC = (self.cC * mp) % self.mod
            return FP2Value(self.mod, a, b, c, aC, bC, cC)
        return FP2Value(self.mod, self.a, self.b, self.c, self.aC, self.bC, self.cC)
Ejemplo n.º 11
0
def test_modular_inverse():
    p = int(
        "d1f9f6c09fd3d38987f7970247b85a6da84907753d42ec52bc23b745093f4fff5cff3"
        "617ce43d00121a9accc0051f519c76e08cf02fc18acfe4c9e6aea18da470a2b611d2e"
        "56a7b35caa2c0239bc041a53cc5875ca0b668ae6377d4b23e932d8c995fd1e58ecfd8"
        "c4b73259c0d8a54d691cca3f6fb85c8a5c1baf588e898d481", 16
    )
    q = int(
        "d1519255eb8f678c86cfd06802d1fbef8b664441ac46b73d33d13a8404580a33a8e74"
        "cb2ea2e2963125b3d454d7a922cef24dd13e55f989cbabf64255a736671f4629a47b5"
        "b2347cfcd669133088d1c159518531025297c2d67c9da856a12e80222cd03b4c6ec0f"
        "86c957cb7bb8de7a127b645ec9e820aa94581e4762e209f01", 16
    )
    assert rsa._modinv(q, p) == int(
        "0275e06afa722999315f8f322275483e15e2fb46d827b17800f99110b269a6732748f"
        "624a382fa2ed1ec68c99f7fc56fb60e76eea51614881f497ba7034c17dde955f92f15"
        "772f8b2b41f3e56d88b1e096cdd293eba4eae1e82db815e0fadea0c4ec971bc6fd875"
        "c20e67e48c31a611e98d32c6213ae4c4d7b53023b2f80c538", 16
    )
Ejemplo n.º 12
0
    def reconstructZ(self, pk):
        numerator = 1 << (pk.Params.Le - 1)
        numerator = FP2Value(pk.N, self.A).intpow(numerator).a

        for i, exp in self.ADisclosed.items():
            if exp.bit_length() > pk.Params.Lm:
                exp = sha256_as_int(str(exp))
            numerator *= FP2Value(pk.N, pk.R[i]).intpow(exp).a
        numerator = numerator % pk.N

        known = pk.Z * _modinv(numerator, pk.N)
        knownC = FP2Value(pk.N, known).intpow(-self.C).a
        Ae = FP2Value(pk.N, self.A).intpow(self.EResponse).a
        Sv = FP2Value(pk.N, pk.S).intpow(self.VResponse).a
        Rs = 1
        for i, response in self.AResponses.items():
            Rs *= FP2Value(pk.N, pk.R[i]).intpow(response).a
        Z = (knownC * Ae * Rs * Sv) % pk.N
        return Z
Ejemplo n.º 13
0
def encode_pubkey(private_key_path):
    """Encodes a public RSA key into Android's custom binary format.

    Parameters
    ----------
    private_key_path : str
        TODO

    Returns
    -------
    TODO
        TODO

    """
    with open(private_key_path, 'rb') as key_file:
        key = serialization.load_pem_private_key(key_file.read(), password=None, backend=default_backend()).private_numbers().public_numbers

    # Compute and store n0inv = -1 / N[0] mod 2^32.
    # BN_set_bit(r32, 32)
    r32 = 1 << 32
    # BN_mod(n0inv, key->n, r32, ctx)
    n0inv = key.n % r32
    # BN_mod_inverse(n0inv, n0inv, r32, ctx)
    n0inv = rsa._modinv(n0inv, r32)  # pylint: disable=protected-access
    # BN_sub(n0inv, r32, n0inv)
    n0inv = r32 - n0inv

    # Compute and store rr = (2^(rsa_size)) ^ 2 mod N.
    # BN_set_bit(rr, ANDROID_PUBKEY_MODULUS_SIZE * 8)
    rr = 1 << (ANDROID_PUBKEY_MODULUS_SIZE * 8)
    # BN_mod_sqr(rr, rr, key->n, ctx)
    rr = (rr ** 2) % key.n

    return struct.pack(
        ANDROID_RSAPUBLICKEY_STRUCT,
        ANDROID_PUBKEY_MODULUS_SIZE_WORDS,
        n0inv,
        _to_bytes(key.n, ANDROID_PUBKEY_MODULUS_SIZE, 'little'),
        _to_bytes(rr, ANDROID_PUBKEY_MODULUS_SIZE, 'little'),
        key.e
    )
Ejemplo n.º 14
0
def _digest_public_key(keyfile):
    keydata = keyfile.read()
    try:
        private_key = serialization.load_pem_private_key(
            keydata, password=None, backend=default_backend())
        public_key = private_key.public_key()
    except ValueError:
        public_key = serialization.load_pem_public_key(
            keydata, backend=default_backend())
    if public_key.key_size != 3072:
        raise esptool.FatalError(
            "Key file %s has length %d bits. Secure Boot V2 only supports RSA-3072."
            % (keyfile.name, public_key.key_size))

    numbers = public_key.public_numbers()
    n = numbers.n  #
    e = numbers.e  # two public key components

    # Note: this cheats and calls a private 'rsa' method to get the modular
    # inverse calculation.
    m = -rsa._modinv(n, 1 << 32)

    rr = 1 << (public_key.key_size * 2)
    rinv = rr % n

    # Encode in the same way it is represented in the signature block
    #
    # Note: the [::-1] is to byte swap all of the bignum
    # values (signatures, coefficients) to little endian
    # for use with the RSA peripheral, rather than big endian
    # which is conventionally used for RSA.
    binary_format = struct.pack("<384sI384sI",
                                int_to_bytes(n)[::-1], e,
                                int_to_bytes(rinv)[::-1], m & 0xFFFFFFFF)

    return hashlib.sha256(binary_format).digest()
Ejemplo n.º 15
0
def Benor(key_size, logging):
    # setup 1
    e = 65537
    priv = rsa.generate_private_key(public_exponent=e,
                                    key_size=key_size,
                                    backend=default_backend())
    d = priv.private_numbers().d
    pub = priv.public_key()
    N = pub.public_numbers().n

    # setup 2
    N_size = ceildiv(priv.key_size, 8)
    plaintext = 0x6c6f6c  # "lol"
    padded = padding(plaintext, N_size)
    logging.info("to find: %d" % padded)
    ciphertext = pow(padded, e, N)

    # setup 3
    t = upper(N_size - 1)  # we choose t+1 = N/256
    total_msg = 0

    # full attack
    while True:
        # setup attack
        # note: we're starting with `i` = 1, which will always work (as the first
        #   byte of a padded message is set to 0).
        #   perhaps a random value is better here? Not sure...
        i = 1
        leak = 0
        coeffs = []
        # step 1
        logging.info("step 1.")
        # finding i, j
        while True:
            c2 = (ciphertext * pow(i, e, N)) % N
            total_msg += 1
            leak = oracle_length(c2, d, N)
            if leak < N_size:
                logging.info("found one i such that i*m <= t")
                logging.info(str(i))
                coeffs.append(i)
                if len(coeffs) == 2:
                    break
            # note: I use a random value here so that the algorithm doesn't always choose
            #   the same `i` and `j`. (Although remember, `i` is always 1).
            i += random.randint(1, 100000)

        logging.info(str(total_msg) + " messages")

        # Step 2. figure out which one is larger
        logging.info("Step 2. gcd(b, c)")
        i = coeffs[0]  # b = i * m mod N
        j = coeffs[1]  # c = j * m mod N
        # checks
        assert ((i * padded) % N < t)
        assert ((j * padded) % N < t)

        # gcd algorithm
        while True:
            logging.info("trying to sort b and c")
            c2 = (ciphertext * pow(j - i, e, N)) % N  # E(j*m - i*m mod N)
            total_msg += 1
            leak = oracle_length(c2, d, N)
            if leak == N_size:  # c < b
                i, j = j, i  # now b < c
            # checks
            b = (padded * i) % N  # c mod N
            c = (padded * j) % N  # k*b mod N
            assert (b < c)  # b < c

            logging.info("find largest k s.t. kb < c")
            """ Unfortunately this doesn't work because I don't know a good range
            k_min = 1
            k_max = t # is there a better range?
            k = 1
            while True:
                if k_max == k_min + 1:
                    k = k_max # the largest of the two
                else:
                    k = (k_max + k_min) // 2 # right in the middle
                c2 = (ciphertext * pow(j - k * i, e, N)) % N # E(j*m - k*i*m mod N)
                total_msg += 1
                leak = oracle_length(c2, d, N)
                if leak < N_size: # <= t
                    k_min = k
                else:
                    k_max = k-1
                if k_min == k_max:
                    k = k_min
                    logging.info("found it:" + str(k))
                    # let's still verify that (we're cheating)
                    c = (padded * j) % N # c mod N
                    kb = (padded * i*k) % N # k*b mod N
                    b = (padded * i) % N # b mod N
                    kp1b = (padded * i*(k+1)) % N # (k+1)*b mod N
                    assert(kb < c) # kb < c
                    assert(kp1b >= c) # (k+1)b > c
                    r = c - kb
                    assert(r < b)
                    assert(c == r + kb)
                    break
     #           logging.info("range of k: [" + str(k_min) + "," + str(k_max) + "]")
            """
            k = 1
            # finding k
            # note: the paper talks about a binary search,
            #   but to do one, we need an upperbound, which I don't think we have
            #   so I take the naive approach of incrementing `k`, starting from 1.
            #   this works well in practice because `k` seems to always be < 50
            while True:
                c2 = (ciphertext *
                      pow(j - k * i, e, N)) % N  # E(j*m - k*i*m mod N)
                total_msg += 1
                leak = oracle_length(c2, d, N)
                if leak >= N_size:  # <= t
                    k -= 1
                    logging.info("found it:" + str(k))
                    # let's still verify that (we're cheating)
                    c = (padded * j) % N  # c mod N
                    b = (padded * i) % N  # b mod N
                    kb = (padded * i * k) % N  # k*b mod N
                    kp1b = (padded * i * (k + 1)) % N  # (k+1)*b mod N
                    assert (kb <= c)  # kb < c
                    assert (kp1b >= c)  # (k+1)b > c
                    r = c - kb
                    logging.info("r:" + str(r))
                    assert (r < b)
                    assert (c == r + kb)
                    break
                k += 1

            logging.info(
                "c <- b, b <- r")  # with r = r_i * m = j*m - r_i * i * m mod N
            r_i = j - k * i
            j = i
            i = r_i

            logging.info("checking if we found the solution")
            c2 = (ciphertext * pow(i, e, N)) % N  # E(d)
            if c2 == 0:
                logging.info("c2 == 0")
                #                input("press a key")
                break
            if c2 == 1:
                logging.info("computing answer")
                solution = _modinv(i, N)
                assert (solution == padded)
                logging.info("found the plaintext")
                logging.info(str(total_msg) + " messages")
                return total_msg
        sizes = [4096, 3072, 2048, 1024, 512]
        key_size = sizes[case % len(sizes)]

        private_key = rsa.generate_private_key(public_exponent=65537,
                                               key_size=key_size,
                                               backend=default_backend())

        priv_numbers = private_key.private_numbers()
        pub_numbers = private_key.public_key().public_numbers()
        Y = priv_numbers.d
        M = pub_numbers.n

        rr = 1 << (key_size * 2)
        rinv = rr % pub_numbers.n
        mprime = -rsa._modinv(M, 1 << 32)
        mprime &= 0xFFFFFFFF
        length = key_size // 32 - 1

        f.write("        .p_data = {\n")
        f.write("            .Y = %s,\n" % number_as_bignum_words(Y))
        f.write("            .M = %s,\n" % number_as_bignum_words(M))
        f.write("            .Rb = %s,\n" % number_as_bignum_words(rinv))
        f.write("            .M_prime = 0x%08x,\n" % mprime)
        f.write("            .length = %d, // %d bit\n" % (length, key_size))
        f.write("        },\n")

        # calculate MD from preceding values and IV

        # Y4096 || M4096 || Rb4096 || M_prime32 || LENGTH32 || IV128
        md_in = number_as_bytes(Y, 4096) + \
Ejemplo n.º 17
0
 def randomElementMultiplicativeGroup(self, modulus):
     r = 0
     while r <= 0 or _modinv(r, modulus) == 1:
         r = randint(1, modulus - 1)
     return r
Ejemplo n.º 18
0
public_key = RSA.import_key("""-----BEGIN PUBLIC KEY-----
        MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCG3rk7v9MWOhAkkqZoXBP2CLMx
        pVswwYSYmm1GArDf7ys4tQ0kk/iBS55Shu1h0Ld5nM5xSg8YHmthmPSjeaK/WkBy
        /Qjabol5Sfg30J4ksV0JsR0dK2mQSExs5hlQuLcgl9leIukzsUs7uXg2KvZ4ZWoh
        fnoqzEujTvkaXhhfgwIDAQAB
        -----END PUBLIC KEY-----""")
n = public_key.n
e = public_key.e

q = int(n // p)
assert p * q == n

# Phi
ϕ = (p - 1) * (q - 1)
d = _modinv(e, ϕ)
assert (e * d) % ϕ == 1

print(f'RSA modulus: {n}')
print(f'RSA public exponent: {e}')
print(f'First factor of the RSA modulus: {p}')
print(f'Second factor of the RSA modulus: {q}')
print(f'RSA private exponent: {d}')

# I suck at reading files in python, so I base64'd it
raw_cipher = b64decode(
    'U0JUONM2neF4/SksiQsBjybSLlJ/HbHrtM9iesDJWFlN/9y1N1OqouihxVqWpliUdAc8608bkxNXAz9DCdMG6myABK9H6Fd1+diVKktMWw+FbhV95MouJdvXRXR0VBOxc5RefLUL/ntTXoTZ3uR2oDthD8f+nB4Ky00y3DHOFuE='
)

private_key = RSA.construct((n, e, d, p, q))
cipher = PKCS1_OAEP.new(private_key)
Ejemplo n.º 19
0
# Testomg
r = requests.get("http://crypto.chal.csaw.io:1000/forgotpass")
boo = binascii.unhexlify(str(r.text.split('/')[-1]))
bit64_num = struct.unpack(">Q", boo)
print "From server the next number is: " + str(bit64_num[0])

our_gen = r2.getrandbits(64)
print "Our next number is: " + str(our_gen)

if our_gen == bit64_num[0]:
    print "[+] Owned!"

k = r2.randrange(2, q)
r_int = pow(g, k, p) % q
kinv = _modinv(k, q)

r1 = requests.get("http://crypto.chal.csaw.io:1000/sign/" + hardcoded_message)
s = json.loads(str(r1.text))['s']
r_server = json.loads(str(r1.text))['r']

print r_int
print r_server

# r^-1 (s.k -H(m)) % q

h_ourend = hashlib.sha1(hardcoded_message).digest()
h = int(h_ourend.encode('hex'), 16)
x = (s * k) - h
x = x * _modinv(r_int, q) % q
print x