core/src/main/java/org/bouncycastle/pqc/crypto/qtesla/QTESLA.java
/*******************************************************************************************************************************************************
     * Description:	Generates A Pair of Public Key and Private Key for qTESLA Signature Scheme for Provably-Secure qTESLA Security Category-1
     * 				and Category-3
     *
     * @param        publicKey                            Contains Public Key
     * @param        privateKey                            Contains Private Key
     * @param        secureRandom                        Source of Randomness
     * @param        n                                    Polynomial Degree
     * @param        k                                    Number of Ring-Learning-With-Errors Samples
     * @param        w                                    Number of Non-Zero Entries of Output Elements of Encryption
     * @param        q                                    Modulus
     * @param        qInverse
     * @param        qLogarithm                            q <= 2 ^ qLogarithm
     * @param        generatorA
     * @param        inverseNumberTheoreticTransform
     * @param        xi
     * @param        zeta
     * @param        errorBound                            Bound in Checking Error Polynomial
     * @param        secretBound                            Bound in Checking Secret Polynomial
     *
     * @return 0                                    Successful Execution
     *******************************************************************************************************************************************************/
Generates A Pair of Public Key and Private Key for qTESLA Signature Scheme for Provably-Secure qTESLA Security Category-1
and Category-3



@return 0                                    Successful Execution
Generates A Pair of Public Key and Private Key for qTESLA Signature Scheme for Provably - Secure qTESLA Security Category - 1 and Category - 3 @return 0 Successful Execution
private static int generateKeyPair(
        byte[] publicKey, byte[] privateKey, SecureRandom secureRandom,
        int n, int k, int w, int q, long qInverse, int qLogarithm, int generatorA, int inverseNumberTheoreticTransform, double xi,
        long[] zeta,
        int errorBound, int secretBound
    )
    {
        /* Initialize Domain Separator for Error Polynomial and Secret Polynomial */
        int nonce = 0;
        long mask;
        byte[] randomness = new byte[Polynomial.RANDOM];
        /* Extend Random Bytes to Seed Generation of Error Polynomial and Secret Polynomial */
        byte[] randomnessExtended = new byte[Polynomial.SEED * (k + 3)];
        long[] secretPolynomial = new long[n];
        long[] secretPolynomialNumberTheoreticTransform = new long[n];
        long[] errorPolynomial = new long[n * k];
        long[] A = new long[n * k];
        long[] T = new long[n * k];
        /* Get randomnessExtended <- seedErrorPolynomial, seedSecretPolynomial, seedA, seedY */
        secureRandom.nextBytes(randomness);
        if (q == Parameter.Q_I_P)
        {
            HashUtils.secureHashAlgorithmKECCAK128(
                randomnessExtended, 0, Polynomial.SEED * (k + 3), randomness, 0, Polynomial.RANDOM
            );
        }
        if (q == Parameter.Q_III_P)
        {
            HashUtils.secureHashAlgorithmKECCAK256(
                randomnessExtended, 0, Polynomial.SEED * (k + 3), randomness, 0, Polynomial.RANDOM
            );
        }
        /*
         * Sample the Error Polynomial Fulfilling the Criteria
         * Choose All Error Polynomial_i in R with Entries from D_SIGMA
         * Repeat Step at Iteration if the h Largest Entries of Error Polynomial_k Summation to L_E
         */
        for (int i = 0; i < k; i++)
        {
            do
            {
                if (q == Parameter.Q_I_P)
                {
                    Sample.polynomialGaussSamplerI(
                        errorPolynomial, n * i, randomnessExtended, Polynomial.SEED * i, ++nonce, n, xi, Sample.EXPONENTIAL_DISTRIBUTION_P
                    );
                }
                if (q == Parameter.Q_III_P)
                {
                    Sample.polynomialGaussSamplerIII(
                        errorPolynomial, n * i, randomnessExtended, Polynomial.SEED * i, ++nonce, n, xi, Sample.EXPONENTIAL_DISTRIBUTION_P
                    );
                }
            }
            while (checkPolynomial(errorPolynomial, n * i, errorBound, n, w) == true);
        }
        /*
         * Sample the Secret Polynomial Fulfilling the Criteria
         * Choose Secret Polynomial in R with Entries from D_SIGMA
         * Repeat Step if the h Largest Entries of Secret Polynomial Summation to L_S
         */
        do
        {
            if (q == Parameter.Q_I_P)
            {
                Sample.polynomialGaussSamplerI(
                    secretPolynomial, 0, randomnessExtended, Polynomial.SEED * k, ++nonce, n, xi, Sample.EXPONENTIAL_DISTRIBUTION_P
                );
            }
            if (q == Parameter.Q_III_P)
            {
                Sample.polynomialGaussSamplerIII(
                    secretPolynomial, 0, randomnessExtended, Polynomial.SEED * k, ++nonce, n, xi, Sample.EXPONENTIAL_DISTRIBUTION_P
                );
            }
        }
        while (checkPolynomial(secretPolynomial, 0, secretBound, n, w) == true);
        /* Generate Uniform Polynomial A */
        Polynomial.polynomialUniform(
            A, randomnessExtended, Polynomial.SEED * (k + 1), n, k, q, qInverse, qLogarithm, generatorA, inverseNumberTheoreticTransform
        );
        Polynomial.polynomialNumberTheoreticTransform(secretPolynomialNumberTheoreticTransform, secretPolynomial, n);
        /* Compute the Public Key T = A * secretPolynomial + errorPolynomial */
        for (int i = 0; i < k; i++)
        {
            Polynomial.polynomialMultiplication(T, n * i, A, n * i, secretPolynomialNumberTheoreticTransform, 0, n, q, qInverse);
            Polynomial.polynomialAddition(T, n * i, T, n * i, errorPolynomial, n * i, n);
            for (int j = 0; j < n; j++)
            {
                mask = (q - T[n * i + j]) >> 63;
                T[n * i + j] -= (q & mask);
            }
        }
        /* Pack Public and Private Keys */
        packPrivateKey(privateKey, secretPolynomial, errorPolynomial, randomnessExtended, Polynomial.SEED * (k + 1), n, k);
        if (q == Parameter.Q_I_P)
        {
            encodePublicKeyIP(publicKey, T, randomnessExtended, Polynomial.SEED * (k + 1));
        }
        if (q == Parameter.Q_III_P)
        {
            encodePublicKeyIIIP(publicKey, T, randomnessExtended, Polynomial.SEED * (k + 1));
        }
        return 0;
    }
private static int generateKeyPair ( byte [ ] publicKey , byte [ ] privateKey , SecureRandom secureRandom , int n , int k , int w , int q , long qInverse , int qLogarithm , int generatorA , int inverseNumberTheoreticTransform , double xi , long [ ] zeta , int errorBound , int secretBound ) { /* Initialize Domain Separator for Error Polynomial and Secret Polynomial */ int nonce = 0 ; long mask ; byte [ ] randomness = new byte [ Polynomial . RANDOM ] ; /* Extend Random Bytes to Seed Generation of Error Polynomial and Secret Polynomial */ byte [ ] randomnessExtended = new byte [ Polynomial . SEED * ( k + 3 ) ] ; long [ ] secretPolynomial = new long [ n ] ; long [ ] secretPolynomialNumberTheoreticTransform = new long [ n ] ; long [ ] errorPolynomial = new long [ n * k ] ; long [ ] A = new long [ n * k ] ; long [ ] T = new long [ n * k ] ; /* Get randomnessExtended <- seedErrorPolynomial, seedSecretPolynomial, seedA, seedY */ secureRandom . nextBytes ( randomness ) ; if ( q == Parameter . Q_I_P ) { HashUtils . secureHashAlgorithmKECCAK128 ( randomnessExtended , 0 , Polynomial . SEED * ( k + 3 ) , randomness , 0 , Polynomial . RANDOM ) ; } if ( q == Parameter . Q_III_P ) { HashUtils . secureHashAlgorithmKECCAK256 ( randomnessExtended , 0 , Polynomial . SEED * ( k + 3 ) , randomness , 0 , Polynomial . RANDOM ) ; } /*
         * Sample the Error Polynomial Fulfilling the Criteria
         * Choose All Error Polynomial_i in R with Entries from D_SIGMA
         * Repeat Step at Iteration if the h Largest Entries of Error Polynomial_k Summation to L_E
         */ for ( int i = 0 ; i < k ; i ++ ) { do { if ( q == Parameter . Q_I_P ) { Sample . polynomialGaussSamplerI ( errorPolynomial , n * i , randomnessExtended , Polynomial . SEED * i , ++ nonce , n , xi , Sample . EXPONENTIAL_DISTRIBUTION_P ) ; } if ( q == Parameter . Q_III_P ) { Sample . polynomialGaussSamplerIII ( errorPolynomial , n * i , randomnessExtended , Polynomial . SEED * i , ++ nonce , n , xi , Sample . EXPONENTIAL_DISTRIBUTION_P ) ; } } while ( checkPolynomial ( errorPolynomial , n * i , errorBound , n , w ) == true ) ; } /*
         * Sample the Secret Polynomial Fulfilling the Criteria
         * Choose Secret Polynomial in R with Entries from D_SIGMA
         * Repeat Step if the h Largest Entries of Secret Polynomial Summation to L_S
         */ do { if ( q == Parameter . Q_I_P ) { Sample . polynomialGaussSamplerI ( secretPolynomial , 0 , randomnessExtended , Polynomial . SEED * k , ++ nonce , n , xi , Sample . EXPONENTIAL_DISTRIBUTION_P ) ; } if ( q == Parameter . Q_III_P ) { Sample . polynomialGaussSamplerIII ( secretPolynomial , 0 , randomnessExtended , Polynomial . SEED * k , ++ nonce , n , xi , Sample . EXPONENTIAL_DISTRIBUTION_P ) ; } } while ( checkPolynomial ( secretPolynomial , 0 , secretBound , n , w ) == true ) ; /* Generate Uniform Polynomial A */ Polynomial . polynomialUniform ( A , randomnessExtended , Polynomial . SEED * ( k + 1 ) , n , k , q , qInverse , qLogarithm , generatorA , inverseNumberTheoreticTransform ) ; Polynomial . polynomialNumberTheoreticTransform ( secretPolynomialNumberTheoreticTransform , secretPolynomial , n ) ; /* Compute the Public Key T = A * secretPolynomial + errorPolynomial */ for ( int i = 0 ; i < k ; i ++ ) { Polynomial . polynomialMultiplication ( T , n * i , A , n * i , secretPolynomialNumberTheoreticTransform , 0 , n , q , qInverse ) ; Polynomial . polynomialAddition ( T , n * i , T , n * i , errorPolynomial , n * i , n ) ; for ( int j = 0 ; j < n ; j ++ ) { mask = ( q - T [ n * i + j ] ) >> 63 ; T [ n * i + j ] -= ( q & mask ) ; } } /* Pack Public and Private Keys */ packPrivateKey ( privateKey , secretPolynomial , errorPolynomial , randomnessExtended , Polynomial . SEED * ( k + 1 ) , n , k ) ; if ( q == Parameter . Q_I_P ) { encodePublicKeyIP ( publicKey , T , randomnessExtended , Polynomial . SEED * ( k + 1 ) ) ; } if ( q == Parameter . Q_III_P ) { encodePublicKeyIIIP ( publicKey , T , randomnessExtended , Polynomial . SEED * ( k + 1 ) ) ; } return 0 ; }
Description:     Generates A Pair of Public Key and Private Key for qTESLA Signature Scheme for Provably-Secure qTESLA Security Category-1
                          and Category-3
Description : Generates A Pair of Public Key and Private Key for qTESLA Signature Scheme for Provably - Secure qTESLA Security Category - 1 and Category - 3
// this.rng.randomByte (randomness, (short) 0, Polynomial.RANDOM);