예제 #1
0
 def test_to_bitarray(self):
     self.assertEqual(len(common.to_bitarray(b'\x00')), 8)
     self.assertEqual(len(common.to_bitarray(b'\x00\x00\x00')), 3 * 8)
     self.assertEqual(len(common.to_bitarray(b'test_test')), 9 * 8)
     self.assertEqual(common.hw(common.to_bitarray(b'\x00\x00')), 0)
     self.assertEqual(common.hw(common.to_bitarray(b'\x01\x01')), 2)
     self.assertEqual(common.hw(common.to_bitarray(b'\xff\xff')), 16)
예제 #2
0
    def test_eval1(self):
        data = b'\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0'  # 12 x \xf0
        data_bin = common.to_bitarray(data)

        te = common.TermEval(16, 2)
        te.load(data_bin)
        r1 = te.eval_terms(1)
        self.assertEqual(r1[0], 6)
        self.assertEqual(r1[1], 6)
        self.assertEqual(r1[5], 0)

        r2 = te.eval_terms(2)
        self.assertEqual(r2[0], 6)  # x0x1
        self.assertEqual(r2[4], 0)  # x0x5

        r3 = te.eval_terms(3)
        self.assertEqual(r3[0], 6)
        self.assertEqual(r3[2], 0)  # x0x1x4

        r2x = te.eval_all_terms(3)
        self.assertEqual(r1, r2x[1])
        self.assertEqual(r2, r2x[2])
        self.assertEqual(r3, r2x[3])
예제 #3
0
    def work(self):
        """
        Main entry point - data processing.

        RandVerif is used to benchmark particular data sources, with different seeds.
        It takes e.g., AES-CTR(SHA256(random)), runs it 1000 times and stores the results. This particular
        computation was used to determine reference z-scores of the test.

        Another usual scenario is to take Java util.Random, seed it 1000 times with a different random seed
        and analyze the results.

        RandVerif supports supplying custom distinguishers so the whole space is not searched. This
        setup is used to assess found distinguishers on more data / independent data streams with different seeds.

        RandVerif produces results on STDOUT, it contains multiple sections, separated by -----BEGIN SECTION-----
        Sections contain stats (avg. z-score), all z-scores, the best distinguishers for further analysis...
        :return:
        """
        self.blocklen = int(self.defset(self.args.blocklen, 128))
        deg = int(self.defset(self.args.degree, 3))
        tvsize_orig = int(
            self.defset(self.process_size(self.args.tvsize), 1024 * 256))
        zscore_thresh = float(self.args.conf)
        rounds = int(
            self.args.rounds) if self.args.rounds is not None else None
        top_k = int(self.args.topk) if self.args.topk is not None else None
        top_comb = int(self.defset(self.args.combdeg, 2))
        reffile = self.defset(self.args.reffile)
        all_deg = self.args.alldeg
        tvsize = tvsize_orig

        top_distinguishers = []

        # Load input polynomials
        self.load_input_poly()
        script_path = common.get_script_path()

        logger.info(
            'Basic settings, deg: %s, blocklen: %s, TV size: %s, rounds: %s' %
            (deg, self.blocklen, tvsize_orig, rounds))

        total_terms = int(common.comb(self.blocklen, deg, True))
        hwanalysis = HWAnalysis()
        hwanalysis.deg = deg
        hwanalysis.blocklen = self.blocklen
        hwanalysis.top_comb = top_comb
        hwanalysis.comb_random = self.args.comb_random
        hwanalysis.top_k = top_k
        hwanalysis.combine_all_deg = all_deg
        hwanalysis.zscore_thresh = zscore_thresh
        hwanalysis.do_ref = reffile is not None
        hwanalysis.skip_print_res = True
        hwanalysis.input_poly = self.input_poly
        hwanalysis.no_comb_and = self.args.no_comb_and
        hwanalysis.no_comb_xor = self.args.no_comb_xor
        hwanalysis.prob_comb = self.args.prob_comb
        hwanalysis.all_deg_compute = len(self.input_poly) == 0
        hwanalysis.do_only_top_comb = self.args.only_top_comb
        hwanalysis.do_only_top_deg = self.args.only_top_deg
        hwanalysis.no_term_map = self.args.no_term_map
        hwanalysis.use_zscore_heap = self.args.topterm_heap
        hwanalysis.sort_best_zscores = max(
            common.replace_none([self.args.topterm_heap_k, top_k, 100]))
        hwanalysis.best_x_combinations = self.args.best_x_combinations
        logger.info('Initializing test')
        hwanalysis.init()

        dist_result_map = {}
        for idx, poly in enumerate(self.input_poly):
            dist_result_map[idx] = []

        for test_idx in range(self.args.tests):
            seed = random.randint(0, 2**32 - 1)
            iobj = None
            if self.args.test_randc:
                path = os.path.realpath(
                    os.path.join(script_path, '../assets/rndgen-c/rand'))
                cmd = '%s %s' % (path, seed)
                iobj = common.CommandStdoutInputObject(cmd=cmd,
                                                       seed=seed,
                                                       desc='randc-%s' % seed)

            elif self.args.test_randc_small:
                path = os.path.realpath(
                    os.path.join(script_path, '../assets/rndgen-c-small/rand'))
                cmd = '%s %s' % (path, seed)
                iobj = common.CommandStdoutInputObject(cmd=cmd,
                                                       seed=seed,
                                                       desc='randc-small-%s' %
                                                       seed)

            elif self.args.test_java:
                path = os.path.realpath(
                    os.path.join(script_path, '../assets/rndgen-java/'))
                cmd = 'java -cp %s Main %s' % (path, seed)
                iobj = common.CommandStdoutInputObject(cmd=cmd,
                                                       seed=seed,
                                                       desc='randjava-%s' %
                                                       seed)

            elif self.args.test_aes:
                iobj = common.AESInputObject(seed=seed)

            else:
                raise ValueError('No generator to test')

            size = iobj.size()
            logger.info(
                'Testing input object: %s, size: %d kB, iteration: %d' %
                (iobj, size / 1024.0, test_idx))

            # size smaller than TV? Adapt tv then
            if size >= 0 and size < tvsize:
                logger.info('File size is smaller than TV, updating TV to %d' %
                            size)
                tvsize = size

            if tvsize * 8 % self.blocklen != 0:
                rem = tvsize * 8 % self.blocklen
                logger.warning(
                    'Input data size not aligned to the block size. '
                    'Input bytes: %d, block bits: %d, rem: %d' %
                    (tvsize, self.blocklen, rem))
                tvsize -= rem // 8
                logger.info('Updating TV to %d' % tvsize)

            hwanalysis.reset()
            logger.info('BlockLength: %d, deg: %d, terms: %d' %
                        (self.blocklen, deg, total_terms))
            with iobj:
                data_read = 0
                cur_round = 0

                while size < 0 or data_read < size:
                    if rounds is not None and cur_round > rounds:
                        break

                    data = iobj.read(tvsize)
                    bits = common.to_bitarray(data)
                    if len(bits) == 0:
                        logger.info('File read completely')
                        break

                    logger.info(
                        'Pre-computing with TV, deg: %d, blocklen: %04d, tvsize: %08d = %8.2f kB = %8.2f MB, '
                        'round: %d, avail: %d' %
                        (deg, self.blocklen, tvsize, tvsize / 1024.0,
                         tvsize / 1024.0 / 1024.0, cur_round, len(bits)))

                    hwanalysis.process_chunk(bits, None)
                    cur_round += 1
                pass

            res = hwanalysis.input_poly_last_res
            if res is not None and len(res) > 0:
                res_top = res[0]
                top_distinguishers.append((res_top, seed))

                for cur in res:
                    dist_result_map[cur.idx].append(cur.zscore)

            elif hwanalysis.last_res is not None and len(
                    hwanalysis.last_res) > 0:
                res_top = hwanalysis.last_res[0]
                top_distinguishers.append((res_top, seed))

            else:
                raise ValueError('No data from the analysis')

            logger.info('Finished processing %s ' % iobj)
            logger.info('Data read %s ' % iobj.data_read)
            logger.info('Read data hash %s ' % iobj.sha1.hexdigest())

        all_zscores = []
        print('-----BEGIN JSON-----')
        js = []
        for dist in top_distinguishers:
            cr = collections.OrderedDict()
            cr['z'] = dist[0].zscore
            try:
                cr['d'] = dist[0].idx
            except:
                pass

            cr['seed'] = dist[1]
            js.append(cr)
            all_zscores.append(dist[0].zscore)
        print(json.dumps(js, indent=2))

        print('-----BEGIN JSON-STATS-----')
        js = []
        for idx in dist_result_map:
            cur = dist_result_map[idx]
            cr = collections.OrderedDict()
            cr['idx'] = idx
            cr['poly'] = common.poly2str(self.input_poly[idx])
            cr['avg'] = sum([abs(x) for x in cur]) / float(len(cur))
            cr['cnt'] = len(cur)
            cr['zscores'] = cur
            js.append(cr)
        print(json.dumps(js, indent=2))

        print('-----BEGIN RUN-CONFIG-----')
        js = collections.OrderedDict()
        js['block'] = self.blocklen
        js['deg'] = deg
        js['top_comb'] = top_comb
        js['top_k'] = top_k
        js['tvsize'] = tvsize
        js['tests'] = self.args.tests
        js['prob_comb'] = self.args.prob_comb
        js['all_deg'] = all_deg
        print(json.dumps(js))

        print('-----BEGIN Z-SCORES-NORM-----')
        print(all_zscores)
        print('-----BEGIN Z-SCORES-ABS-----')
        print([abs(x) for x in all_zscores])
        print('-----BEGIN Z-SCORES-AVG-----')
        print(sum([abs(x) for x in all_zscores]) / float(len(all_zscores)))
        print('-----BEGIN Z-SCORES-NAVG-----')
        print(sum([x for x in all_zscores]) / float(len(all_zscores)))

        if self.args.csv_zscore:
            print('-----BEGIN Z-SCORES-CSV-----')
            print('zscore')
            for x in [abs(x) for x in all_zscores]:
                print(x)

        logger.info('Processing finished')
예제 #4
0
    def work(self):
        """
        Main entry point - data processing
        :return:
        """
        start=time.time()
        self.blocklen = int(self.defset(self.args.blocklen, 128))
        deg = int(self.defset(self.args.degree, 3))
        tvsize_orig = int(self.defset(self.process_size(self.args.tvsize), 1024*256))
        zscore_thresh = float(self.args.conf)
        rounds = int(self.args.rounds) if self.args.rounds is not None else None
        top_k = int(self.args.topk) if self.args.topk is not None else None
        top_comb = int(self.defset(self.args.combdeg, 2))
        reffile = self.defset(self.args.reffile)
        all_deg = self.args.alldeg

        # Load input polynomials
        self.load_input_poly()
        self.load_input_objects()

        logger.info('Basic settings, deg: %s, blocklen: %s, TV size: %s, rounds: %s'
                    % (deg, self.blocklen, tvsize_orig, rounds))

        # specific polynomial testing
        logger.info('Initialising')

        # read file by file
        for iobj in self.input_objects:
            tvsize = tvsize_orig

            iobj.check()
            size = iobj.size()
            logger.info('Testing input object: %s, size: %d kB' % (iobj, size/1024.0))

            # size smaller than TV? Adapt tv then
            if size >= 0 and size < tvsize:
                logger.info('File size is smaller than TV, updating TV to %d' % size)
                tvsize = size

            if tvsize*8 % self.blocklen != 0:
                rem = tvsize*8 % self.blocklen
                logger.warning('Input data size not aligned to the block size. '
                               'Input bytes: %d, block bits: %d, rem: %d' % (tvsize, self.blocklen, rem))
                tvsize -= rem//8
                logger.info('Updating TV to %d' % tvsize)

            hwanalysis = HWAnalysis()
            hwanalysis.deg = deg
            hwanalysis.blocklen = self.blocklen
            hwanalysis.top_comb = top_comb
            hwanalysis.comb_random = self.args.comb_random
            hwanalysis.top_k = top_k
            hwanalysis.combine_all_deg = all_deg
            hwanalysis.zscore_thresh = zscore_thresh
            hwanalysis.do_ref = reffile is not None
            hwanalysis.input_poly = self.input_poly
            hwanalysis.no_comb_and = self.args.no_comb_and
            hwanalysis.no_comb_xor = self.args.no_comb_xor
            hwanalysis.prob_comb = self.args.prob_comb
            hwanalysis.do_only_top_comb = self.args.only_top_comb
            hwanalysis.do_only_top_deg = self.args.only_top_deg
            hwanalysis.no_term_map = self.args.no_term_map
            hwanalysis.use_zscore_heap = self.args.topterm_heap
            hwanalysis.sort_best_zscores = max(common.replace_none([self.args.topterm_heap_k, top_k, 100]))
            hwanalysis.best_x_combinations = self.args.best_x_combinations
            hwanalysis.compute_on_cpu = self.args.compute_on_cpu
            hwanalysis.verify = self.args.verify

            # compute classical analysis only if there are no input polynomials
            hwanalysis.all_deg_compute = len(self.input_poly) == 0
            logger.info('Initializing test')
            hwanalysis.init()

            total_terms = int(scipy.misc.comb(self.blocklen, deg, True))
            logger.info('BlockLength: %d, deg: %d, terms: %d' % (self.blocklen, deg, total_terms))

            # Reference data stream reading
            # Read the file until there is no data.
            fref = None
            if reffile is not None:
                fref = open(reffile, 'r')

            with iobj:
                data_read = 0
                cur_round = 0

                while size < 0 or data_read < size:
                    if rounds is not None and cur_round > rounds:
                        break

                    data = iobj.read(tvsize)
                    bits = common.to_bitarray(data)
                    if len(bits) == 0:
                        logger.info('File read completely')
                        break

                    ref_bits = None
                    if fref is not None:
                        ref_data = fref.read(tvsize)
                        ref_bits = common.to_bitarray(ref_data)

                    logger.info('Pre-computing with TV, deg: %d, blocklen: %04d, tvsize: %08d = %8.2f kB = %8.2f MB, '
                                'round: %d, avail: %d' %
                                (deg, self.blocklen, tvsize, tvsize/1024.0, tvsize/1024.0/1024.0, cur_round, len(bits)))

                    hwanalysis.proces_chunk(bits, ref_bits)
                    cur_round += 1
                pass

            logger.info('Finished processing %s ' % iobj)
            logger.info('Data read %s ' % iobj.data_read)
            logger.info('Read data hash %s ' % iobj.sha1.hexdigest())

            if fref is not None:
                fref.close()
        logger.info('Processing finished')
        end = time.time()
        print(end-start)
예제 #5
0
    def work(self):
        """
        Main entry point - data processing
        :return:
        """
        config = None
        with open(self.args.config_file) as fh:
            config = json.load(fh)

        hw_cfg = config['hwanalysis']
        test_run = config['config']
        data_file = test_run['spec']['data_file']
        skip_finished = common.defvalkey(config, 'skip_finished', False)
        res_file = common.defvalkey(config, 'res_file')

        if skip_finished and res_file and self.check_res_file(res_file):
            logger.info('Already computed in %s' % res_file)
            return

        hwanalysis = HWAnalysis()
        hwanalysis.from_json(hw_cfg)

        rounds = None
        size_mb = test_run['spec']['data_size'] / 1024 / 1024
        tvsize = test_run['spec']['data_size']

        # Load input polynomials
        # self.load_input_poly()

        logger.info('Basic settings, deg: %s, blocklen: %s, TV size: %s' %
                    (hwanalysis.deg, hwanalysis.blocklen, tvsize))
        total_terms = int(
            scipy.misc.comb(hwanalysis.blocklen, hwanalysis.deg, True))

        logger.info('Initializing test')
        time_test_start = time.time()
        hwanalysis.init()

        # Process input object
        iobj = common.FileInputObject(
            data_file) if data_file else common.StdinInputObject('stdin')
        size = iobj.size()
        logger.info('Testing input object: %s, size: %d kB' %
                    (iobj, size / 1024.0))

        # size smaller than TV? Adapt tv then
        if size >= 0 and size < tvsize:
            logger.info('File size is smaller than TV, updating TV to %d' %
                        size)
            tvsize = size

        if tvsize * 8 % hwanalysis.blocklen != 0:
            rem = tvsize * 8 % hwanalysis.blocklen
            logger.warning('Input data size not aligned to the block size. '
                           'Input bytes: %d, block bits: %d, rem: %d' %
                           (tvsize, hwanalysis.blocklen, rem))
            tvsize -= rem // 8
            logger.info('Updating TV to %d' % tvsize)

        hwanalysis.reset()
        logger.info('BlockLength: %d, deg: %d, terms: %d' %
                    (hwanalysis.blocklen, hwanalysis.deg, total_terms))
        with iobj:
            data_read = 0
            cur_round = 0

            while size < 0 or data_read < size:
                if rounds is not None and cur_round > rounds:
                    break

                data = iobj.read(tvsize)
                if (len(data) * 8 % hwanalysis.blocklen) != 0:
                    logger.warning(
                        'Not aligned block read, terminating. Data: %s bits remainder: %s'
                        % (len(data) * 8, hwanalysis.blocklen))
                    break

                bits = common.to_bitarray(data)
                if len(bits) == 0:
                    logger.info('File read completely')
                    break

                logger.info(
                    'Pre-computing with TV, deg: %d, blocklen: %04d, tvsize: %08d = %8.2f kB = %8.2f MB, '
                    'round: %d, avail: %d' %
                    (hwanalysis.deg, hwanalysis.blocklen, tvsize, tvsize /
                     1024.0, tvsize / 1024.0 / 1024.0, cur_round, len(bits)))

                hwanalysis.proces_chunk(bits, None)
                cur_round += 1
            pass

        # RESULT process...
        total_results = len(hwanalysis.last_res) if hwanalysis.last_res else 0
        best_dists = hwanalysis.last_res[
            0:min(128, total_results)] if hwanalysis.last_res else None
        data_hash = iobj.sha1.hexdigest()

        jsres = collections.OrderedDict()
        if best_dists:
            jsres['best_zscore'] = best_dists[0].zscore
            jsres['best_poly'] = best_dists[0].poly

        jsres['blocklen'] = hwanalysis.blocklen
        jsres['degree'] = hwanalysis.deg
        jsres['comb_degree'] = hwanalysis.top_comb
        jsres['top_k'] = self.top_k
        jsres['all_deg'] = self.all_deg
        jsres['time_elapsed'] = time.time() - time_test_start

        jsres['data_hash'] = data_hash
        jsres['data_read'] = iobj.data_read
        jsres['generator'] = self.config_js
        jsres['best_dists'] = best_dists
        jsres['config'] = config

        res_file_path = config['res_file']
        with open(res_file_path, 'w+') as fh:
            fh.write(common.json_dumps(jsres, indent=2))

        logger.info('Finished processing %s ' % iobj)
        logger.info('Data read %s ' % iobj.data_read)
        logger.info('Read data hash %s ' % data_hash)
        return jsres
예제 #6
0
    def testcase(self, function, cur_round, size_mb, blocklen, degree,
                 comb_deg, data_file, tmpdir):
        """
        Test case executor
        :param function:
        :param cur_round:
        :param size_mb:
        :param blocklen:
        :param degree:
        :param comb_deg:
        :param data_file:
        :return:
        """
        rounds = 0
        tvsize = 1024 * 1024 * size_mb

        # Load input polynomials
        self.load_input_poly()
        script_path = common.get_script_path()

        logger.info('Basic settings, deg: %s, blocklen: %s, TV size: %s' %
                    (degree, blocklen, tvsize))

        total_terms = int(common.comb(blocklen, degree, True))
        hwanalysis = HWAnalysis()
        hwanalysis.deg = degree
        hwanalysis.blocklen = blocklen
        hwanalysis.top_comb = comb_deg

        hwanalysis.comb_random = self.args.comb_random
        hwanalysis.top_k = self.top_k
        hwanalysis.combine_all_deg = self.all_deg
        hwanalysis.zscore_thresh = self.zscore_thresh
        hwanalysis.do_ref = None
        hwanalysis.skip_print_res = True
        hwanalysis.input_poly = self.input_poly
        hwanalysis.no_comb_and = self.args.no_comb_and
        hwanalysis.no_comb_xor = self.args.no_comb_xor
        hwanalysis.prob_comb = self.args.prob_comb
        hwanalysis.all_deg_compute = len(self.input_poly) == 0
        hwanalysis.do_only_top_comb = self.args.only_top_comb
        hwanalysis.do_only_top_deg = self.args.only_top_deg
        hwanalysis.no_term_map = self.args.no_term_map
        hwanalysis.use_zscore_heap = self.args.topterm_heap
        hwanalysis.sort_best_zscores = max(
            common.replace_none([self.args.topterm_heap_k, self.top_k, 100]))
        hwanalysis.best_x_combinations = self.args.best_x_combinations

        logger.info('Initializing test')
        time_test_start = time.time()
        hwanalysis.init()

        # Process input object
        iobj = common.FileInputObject(data_file)
        size = iobj.size()
        logger.info('Testing input object: %s, size: %d kB' %
                    (iobj, size / 1024.0))

        # size smaller than TV? Adapt tv then
        if size >= 0 and size < tvsize:
            logger.info('File size is smaller than TV, updating TV to %d' %
                        size)
            tvsize = size

        if tvsize * 8 % blocklen != 0:
            rem = tvsize * 8 % blocklen
            logger.warning('Input data size not aligned to the block size. '
                           'Input bytes: %d, block bits: %d, rem: %d' %
                           (tvsize, blocklen, rem))
            tvsize -= rem // 8
            logger.info('Updating TV to %d' % tvsize)

        hwanalysis.reset()
        logger.info('BlockLength: %d, deg: %d, terms: %d' %
                    (blocklen, degree, total_terms))
        with iobj:
            data_read = 0
            cur_round = 0

            while size < 0 or data_read < size:
                if rounds is not None and cur_round > rounds:
                    break

                data = iobj.read(tvsize)
                bits = common.to_bitarray(data)
                if len(bits) == 0:
                    logger.info('File read completely')
                    break

                logger.info(
                    'Pre-computing with TV, deg: %d, blocklen: %04d, tvsize: %08d = %8.2f kB = %8.2f MB, '
                    'round: %d, avail: %d' %
                    (degree, blocklen, tvsize, tvsize / 1024.0,
                     tvsize / 1024.0 / 1024.0, cur_round, len(bits)))

                hwanalysis.process_chunk(bits, None)
                cur_round += 1
            pass

        # RESULT process...
        total_results = len(hwanalysis.last_res)
        best_dists = hwanalysis.last_res[0:min(128, total_results)]
        data_hash = iobj.sha1.hexdigest()

        jsres = collections.OrderedDict()
        jsres['best_zscore'] = best_dists[0].zscore
        jsres['best_poly'] = best_dists[0].poly

        jsres['blocklen'] = blocklen
        jsres['degree'] = degree
        jsres['comb_degree'] = comb_deg
        jsres['top_k'] = self.top_k
        jsres['all_deg'] = self.all_deg
        jsres['time_elapsed'] = time.time() - time_test_start

        jsres['data_hash'] = data_hash
        jsres['data_read'] = iobj.data_read
        jsres['generator'] = self.config_js
        jsres['best_dists'] = best_dists

        logger.info('Finished processing %s ' % iobj)
        logger.info('Data read %s ' % iobj.data_read)
        logger.info('Read data hash %s ' % data_hash)
        return jsres