Esempio n. 1
0
    def test_46(self):
        plain = cu.base64_to_bytes(
            'VGhhdCdzIHdoeSBJIGZvdW5kIHlvdSBkb24ndCBwbGF5IGFyb3VuZCB3aXRoIHRoZSBGdW5reSBDb2xkIE1lZGluYQ=='
        )
        plain_int = int.from_bytes(plain, 'big')

        public, is_even = get_parity_oracle()
        e, n = public
        cipher = ck.cipher_RSA(plain_int, public)

        # constant which will allow us to double the plaintext
        double_plain = pow(2, e, n)
        max_iter = ceil(log(n, 2))
        """casting the bounds as Decimal type, and setting the precision
        to have as many bits as the modulus, is *super* important. If we
        don't do this rounding errors will screw us, and trying to do this
        with integer division without messing up the last byte is annoying"""
        lower_bound, upper_bound = Decimal(0), Decimal(n)
        getcontext().prec = max_iter
        for _ in range(max_iter):
            cipher = double_plain * cipher % n
            if is_even(cipher):
                upper_bound = (lower_bound + upper_bound) / 2
            else:
                lower_bound = (lower_bound + upper_bound) / 2
            if int(upper_bound) == int(lower_bound):
                break

        decrypted = cu.int_to_bytes(int(upper_bound))
        self.assertEqual(plain, decrypted)
Esempio n. 2
0
def PKCS1v1p5(plain, N):
    num_bytes = N // 8
    plain_bytes = cu.int_to_bytes(plain)
    num_pad = num_bytes - 3 - len(plain_bytes)
    padding = cu.random_bytes(num_pad)
    padded = bytes([0, 2]) + padding + bytes([0]) + plain_bytes
    return int.from_bytes(padded, 'big')
Esempio n. 3
0
    def login(self, server, DH_keys=None):
        if DH_keys is None:
            public, private = ck.gen_DH_keys(p=self.N, g=self.g)
        else:
            public, private = DH_keys

        simple = server.simple
        response = server.login(self.email, public)
        self.server = server
        if simple:
            self.salt, server_public, scramble = response
        else:
            self.salt, server_public = response
            scramble = srp_scrambler(public, server_public)

        m = sha256()
        m.update(self.salt + bytes(self.password, 'utf-8'))
        xH = m.digest()
        x = int.from_bytes(xH, byteorder='big')
        if simple:
            S = pow(server_public, private + scramble * x, self.N)
        else:
            S = pow(self.g, x, self.N)
            S = pow(server_public - self.k * S, private + scramble * x, self.N)
        m = sha256()
        m.update(cu.int_to_bytes(S))
        self.session_key = m.digest()
Esempio n. 4
0
    def test_PKCS(self):
        N = 1024
        public, oracle = get_PKCS_oracle(N=N)
        plain = randbelow(2**64)
        padded = PKCS1v1p5(plain, N)
        self.assertEqual(len(cu.int_to_bytes(padded)), ceil(N / 8) - 1)

        cipher = ck.cipher_RSA(padded, public)
        self.assertTrue(oracle(cipher))
Esempio n. 5
0
 def test_37(self):
     """Since SRP, server-side, multiplies by the client's public key prior
     to modexp and hashing, passing any multiple of N (including 0!) will
     result in key == SHA256(0). Note that we don't need to know g, N, k,
     the password. NOTHING. Just pass (email, 0) and SHA256(0) is your key!!!"""
     self.client.login(self.server, DH_keys=(0, 0))
     m = sha256()
     m.update(cu.int_to_bytes(0))
     self.client.session_key = m.digest()
     self.assertTrue(self.client.validate())
Esempio n. 6
0
    def _srp_key_simple(self, email, client_public):
        salt, verifier = self.login_info[email]
        public, private = ck.gen_DH_keys(p=self.N, g=self.g)

        # compute and store session key
        scramble = randbelow(2**128)
        S = pow(verifier, scramble, self.N)
        S = pow(client_public * S, private, self.N)
        m = sha256()
        m.update(cu.int_to_bytes(S))
        self.session_keys[email] = m.digest()

        return salt, public, scramble
Esempio n. 7
0
    def _srp_key_standard(self, email, client_public):
        salt, verifier = self.login_info[email]
        public, private = ck.gen_DH_keys(p=self.N, g=self.g)
        public = (public + self.k * verifier) % self.N

        # compute and store session key
        scramble = srp_scrambler(client_public, public)
        S = pow(verifier, scramble, self.N)
        S = pow(client_public * S, private, self.N)
        m = sha256()
        m.update(cu.int_to_bytes(S))
        self.session_keys[email] = m.digest()

        return salt, public
Esempio n. 8
0
def cipher_RSA(data, key):
    """Process data using the given RSA key (exponent, modulus)

    Input data can be an int or bytes-like (interpreted as big-endian).
    We'll return either an int or bytes, respectively
    """
    byte_input = False
    if isinstance(data, bytes) or isinstance(data, bytearray):
        byte_input = True
        data = int.from_bytes(data, 'big')
    cipher = pow(data, key[0], key[1])
    if byte_input:
        cipher = int_to_bytes(cipher)
    return cipher
Esempio n. 9
0
 def key_exchange(self, p, g, public):
     if self.mod_g is False:
         """Parameter-injection. Make both parties think the public-key
         is p, yielding a secret of 0 (empty bytes)"""
         self.server.key_exchange(p, g, p)
         return p
     """Malicious g-value, but same idea. Control the estimated public-key
     so that the secret is known a priori"""
     new_g = choice([1, p, p - 1])
     if new_g == p:
         fake_public, secret = 0, 0
     else:
         fake_public, secret = 1, 1
     self.key = cbc_keygen(cu.int_to_bytes(secret))
     return self.server.key_exchange(p, new_g, fake_public)
Esempio n. 10
0
 def crack(self, email):
     public, salt, scramble = self.login_info[email]
     validation = self.validations[email]
     for pw in WEAK_PASSWORDS:
         m = sha256()
         m.update(salt + bytes(pw, 'utf-8'))
         xH = m.digest()
         x = int.from_bytes(xH, byteorder='big')
         S = pow(self.g, scramble * x, self.N)
         S = public * S % self.N
         m = sha256()
         m.update(cu.int_to_bytes(S))
         key_guess = m.digest()
         expected = hmac.new(key_guess, salt, sha256).digest()
         if hmac.compare_digest(validation, expected):
             self.passwords[email] = pw
             return True
     return False
Esempio n. 11
0
    def test_42(self):
        # we only know the public key, so we have to forge the signature
        public, _ = ck.gen_RSA_keys(N=3072)

        message = b'hi mom'
        m = sha1()
        m.update(message)
        message_hash = m.digest()
        block = bytes([0]) + SHA1_ASN + message_hash
        """Bleichenbacher's 'pencil and paper' attack strategy doesn't
         work for smaller moduli (e.g., N=1024), and via brute-forcing I
        couldn't find a zero-padded forged signature that worked, so I'm
        saying screw it and doing this for 3072 bit RSA"""
        D = int.from_bytes(block, 'big')
        M = 2**288 - D
        F = 2**1019 - 2**34 * M // 3
        forged = cu.int_to_bytes(F)

        self.assertTrue(verify_RSA(message_hash, forged, public))
Esempio n. 12
0
def srp_scrambler(client_public, server_public):
    """compute the scrambling integer used in the SRP protocal, using two
    ephemeral public keys"""
    m = sha256()
    m.update(cu.int_to_bytes(client_public) + cu.int_to_bytes(server_public))
    return int.from_bytes(m.digest(), byteorder='big')
Esempio n. 13
0
def gen_DH_secret(public, private, p=DH_P):
    """Return a Diffie-Hellman secret key, as a bytes-like"""
    return int_to_bytes(pow(public, private, p))