/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.cryptolib.securerandom.cryptoapi;

import java.math.BigInteger;
import java.util.Set;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;

/**
 * Interface that provides the functionality to obtain random integers, for
 * which the class {@link BigInteger} is used.
 */
public interface CryptoAPIRandomInteger {

    /**
     * Creates a random positive {@link BigInteger} according to the specified
     * bit length.
     * 
     * @param lengthInBits
     *            the bit length of the random integer.
     * @return a random {@link BigInteger} within the range [0, 2^
     *         {@code numberBits}-1].
     * @throws GeneralCryptoLibException
     *             if {@code lengthInBits} is out of the range for this
     *             generator.
     */
    BigInteger nextRandomByBits(int lengthInBits)
            throws GeneralCryptoLibException;

    /**
     * Creates a random positive {@link BigInteger} according to the specified
     * {@code lengthInDigits}.
     * 
     * @param lengthInDigits
     *            The lengthInDigits that specifies the maximum number of digits
     *            of the {@link BigInteger} to be generated.
     * @return a random {@link BigInteger} up to {@code lengthInDigits} digits.
     * @throws GeneralCryptoLibException
     *             if {@code lengthInDigits} is out of the range for this
     *             generator.
     * @see java.security.SecureRandom#nextBytes(byte[] bytes)
     */
    BigInteger nextRandom(int lengthInDigits)
            throws GeneralCryptoLibException;

    /**
     * Creates a random positive {@link BigInteger} according to the specified
     * {@code lengthInDigits}. The output is not equal to any of the
     * {@link BigInteger} in the {@code blackList}. Note: the {@code blackList}
     * cannot contain more elements than: (10^( {@code lengthInDigits}) - 1).
     * Moreover, the {@code blackList} should only contain BigIntegers with a
     * number of digits up to the given {@code lengthInDigits}.
     * 
     * @param lengthInDigits
     *            the lengthInDigits that specifies the maximum number of digits
     *            of the {@link BigInteger} to be generated.
     * @param blackList
     *            set of {@link BigInteger} in the black list.
     * @return a random {@link BigInteger} up to {@code lengthInDigits} digits.
     * @throws GeneralCryptoLibException
     *             if {@code lengthInDigits} is out of the range for this
     *             generator.
     * @throws GeneralCryptoLibException
     *             if the {@code blackList} contains too many elements.
     * @throws GeneralCryptoLibException
     *             if the {@code blackList} contains any element with more
     *             digits that the given {@code lengthInDigits}.
     * @see java.security.SecureRandom#nextBytes(byte[] bytes)
     */
    BigInteger nextRandom(int lengthInDigits, Set<BigInteger> blackList)
            throws GeneralCryptoLibException;

    /**
     * Creates a random {@link BigInteger} that is probably a prime number, of
     * the specified bit length. Uses the method
     * {@link java.math.BigInteger#probablePrime(int, java.util.Random)}
     * 
     * @param lengthInBits
     *            the bit length of the random integer to be generated.
     * @return a random {@link BigInteger}, which is probably a prime number, of
     *         the specified bit length.
     * @throws GeneralCryptoLibException
     *             if {@code lengthInBits} is out of the range for this
     *             generator.
     */
    BigInteger getRandomProbablePrimeBigInteger(int lengthInBits)
            throws GeneralCryptoLibException;

    /**
     * Creates a random {@link BigInteger} that is probably a prime number, of
     * the specified bit length and certainty. Uses the constructor
     * {@link java.math.BigInteger#BigInteger(int, int, java.util.Random)}.
     * 
     * @param lengthInBits
     *            the bit length of the random integer to be generated.
     * @param certainty
     *            a measure of the probability that the random
     *            {@link BigInteger} is a prime number, defined such that this
     *            probability will exceed (1 - 1/(2^{@code certainty})).
     * @return a random {@link BigInteger}, which is probably a prime number, of
     *         the specified bit length and certainty.
     * @throws GeneralCryptoLibException
     *             if {@code lengthInBits} is out of the range for this
     *             generator.
     */
    BigInteger getRandomProbablePrimeBigIntegerWithSetCertainty(
            int lengthInBits, int certainty)
            throws GeneralCryptoLibException;
}
