core/src/main/java/org/bouncycastle/pqc/crypto/qtesla/QTESLA.java
/*****************************************************************************************************************************************************
     * Description:	Generates A Signature for A Given Message According to the Ring-TESLA Signature Scheme for Provably-Secure qTESLA Security Category-1
     *				and Category-3
     *
     * @param        message                                Message to be Signed
     * @param        messageOffset                        Starting Point of the Message to be Signed
     * @param        messageLength                        Length of the Message to be Signed
     * @param        signature                            Output Package Containing Signature
     * @param        privateKey                            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        b                                    Determines the Interval the Randomness is Chosen in During Signing
     * @param        bBit                                b = (2 ^ bBit) - 1
     * @param        d                                    Number of Rounded Bits
     * @param        u                                    Bound in Checking Secret Polynomial
     * @param        rejection                            Bound in Checking Error Polynomial
     * @param        generatorA
     * @param        inverseNumberTheoreticTransform
     * @param        privateKeySize                        Size of the Private Key
     * @param        barrettMultiplication
     * @param        barrettDivision
     *
     * @return 0                                    Successful Execution
     *****************************************************************************************************************************************************/
Generates A Signature for A Given Message According to the Ring-TESLA Signature Scheme for Provably-Secure qTESLA Security Category-1
and Category-3



@return 0                                    Successful Execution
Generates A Signature for A Given Message According to the Ring - TESLA Signature Scheme for Provably - Secure qTESLA Security Category - 1 and Category - 3 @return 0 Successful Execution
private static int signing(
        byte[] signature,
        final byte[] message, int messageOffset, int messageLength,
        final byte[] privateKey, SecureRandom secureRandom,
        int n, int k, int w, int q, long qInverse, int qLogarithm, int b, int bBit, int d, int u, int rejection,
        int generatorA, int inverseNumberTheoreticTransform, int privateKeySize,
        int barrettMultiplication, int barrettDivision
    )
    {
        byte[] C = new byte[Polynomial.HASH];
        byte[] randomness = new byte[Polynomial.SEED];
        byte[] randomnessInput = new byte[messageLength + Polynomial.RANDOM + Polynomial.SEED];
        byte[] temporaryRandomnessInput = new byte[Polynomial.RANDOM];
        int[] positionList = new int[w];
        short[] signList = new short[w];
        long[] A = new long[n * k];
        long[] V = new long[n * k];
        long[] Y = new long[n];
        long[] numberTheoreticTransformY = new long[n];
        long[] Z = new long[n];
        long[] SC = new long[n];
        long[] EC = new long[n * k];
        boolean response = false;
        /* Domain Separator for Sampling Y */
        int nonce = 0;
        secureRandom.nextBytes(temporaryRandomnessInput);
        System.arraycopy(temporaryRandomnessInput, 0, randomnessInput, Polynomial.RANDOM, Polynomial.RANDOM);
        System.arraycopy(privateKey, privateKeySize - Polynomial.SEED, randomnessInput, 0, Polynomial.SEED);
        System.arraycopy(message, messageOffset, randomnessInput, Polynomial.RANDOM + Polynomial.SEED, messageLength);
        if (q == Parameter.Q_I_P)
        {
            HashUtils.secureHashAlgorithmKECCAK128(
                randomness, 0, Polynomial.SEED, randomnessInput, 0, messageLength + Polynomial.RANDOM + Polynomial.SEED
            );
        }
        else
        {
            HashUtils.secureHashAlgorithmKECCAK256(
                randomness, 0, Polynomial.SEED, randomnessInput, 0, messageLength + Polynomial.RANDOM + Polynomial.SEED
            );
        }
        Polynomial.polynomialUniform(
            A, privateKey, privateKeySize - 2 * Polynomial.SEED, n, k, q, qInverse, qLogarithm, generatorA, inverseNumberTheoreticTransform
        );
        /* Loop Due to Possible Rejection */
        while (true)
        {
            /* Sample Y Uniformly Random from -B to B */
            Sample.sampleY(Y, randomness, 0, ++nonce, n, q, b, bBit);
            Polynomial.polynomialNumberTheoreticTransform(numberTheoreticTransformY, Y, n);
            /* V_i = A_i * Y Modulo Q for All i */
            for (short i = 0; i < k; i++)
            {
                Polynomial.polynomialMultiplication(V, n * i, A, n * i, numberTheoreticTransformY, 0, n, q, qInverse);
            }
            hashFunction(C, 0, V, message, messageOffset, messageLength, n, k, d, q);
            /* Generate C = EncodeC (C') Where C' is the Hashing of V Together with Message */
            Sample.encodeC(positionList, signList, C, 0, n, w);
            sparsePolynomialMultiplication8(SC, 0, privateKey, 0, positionList, signList, n, w);
            /* Z = Y + EC modulo Q */
            Polynomial.polynomialAddition(Z, 0, Y, 0, SC, 0, n);
            /* Rejection Sampling */
            if (testRejection(Z, n, b, u) == true)
            {
                continue;
            }
            for (short i = 0; i < k; i++)
            {
                sparsePolynomialMultiplication8(EC, n * i, privateKey, n * (i + 1), positionList, signList, n, w);
                /* V_i = V_i - EC_i Modulo Q for All k */
                Polynomial.polynomialSubtractionP(V, n * i, V, n * i, EC, n * i, n, q, barrettMultiplication, barrettDivision);
                response = testV(V, n * i, n, d, q, rejection);
                if (response == true)
                {
                    break;
                }
            }
            if (response == true)
            {
                continue;
            }
            if (q == Parameter.Q_I_P)
            {
                /* Pack Signature */
                encodeSignatureIIISpeedIP(signature, 0, C, 0, Z, n, d);
            }
            else
            {
                /* Pack Signature */
                encodeSignature(signature, 0, C, 0, Z);
            }
            return 0;
        }
    }
private static int signing ( byte [ ] signature , final byte [ ] message , int messageOffset , int messageLength , final byte [ ] privateKey , SecureRandom secureRandom , int n , int k , int w , int q , long qInverse , int qLogarithm , int b , int bBit , int d , int u , int rejection , int generatorA , int inverseNumberTheoreticTransform , int privateKeySize , int barrettMultiplication , int barrettDivision ) { byte [ ] C = new byte [ Polynomial . HASH ] ; byte [ ] randomness = new byte [ Polynomial . SEED ] ; byte [ ] randomnessInput = new byte [ messageLength + Polynomial . RANDOM + Polynomial . SEED ] ; byte [ ] temporaryRandomnessInput = new byte [ Polynomial . RANDOM ] ; int [ ] positionList = new int [ w ] ; short [ ] signList = new short [ w ] ; long [ ] A = new long [ n * k ] ; long [ ] V = new long [ n * k ] ; long [ ] Y = new long [ n ] ; long [ ] numberTheoreticTransformY = new long [ n ] ; long [ ] Z = new long [ n ] ; long [ ] SC = new long [ n ] ; long [ ] EC = new long [ n * k ] ; boolean response = false ; /* Domain Separator for Sampling Y */ int nonce = 0 ; secureRandom . nextBytes ( temporaryRandomnessInput ) ; System . arraycopy ( temporaryRandomnessInput , 0 , randomnessInput , Polynomial . RANDOM , Polynomial . RANDOM ) ; System . arraycopy ( privateKey , privateKeySize - Polynomial . SEED , randomnessInput , 0 , Polynomial . SEED ) ; System . arraycopy ( message , messageOffset , randomnessInput , Polynomial . RANDOM + Polynomial . SEED , messageLength ) ; if ( q == Parameter . Q_I_P ) { HashUtils . secureHashAlgorithmKECCAK128 ( randomness , 0 , Polynomial . SEED , randomnessInput , 0 , messageLength + Polynomial . RANDOM + Polynomial . SEED ) ; } else { HashUtils . secureHashAlgorithmKECCAK256 ( randomness , 0 , Polynomial . SEED , randomnessInput , 0 , messageLength + Polynomial . RANDOM + Polynomial . SEED ) ; } Polynomial . polynomialUniform ( A , privateKey , privateKeySize - 2 * Polynomial . SEED , n , k , q , qInverse , qLogarithm , generatorA , inverseNumberTheoreticTransform ) ; /* Loop Due to Possible Rejection */ while ( true ) { /* Sample Y Uniformly Random from -B to B */ Sample . sampleY ( Y , randomness , 0 , ++ nonce , n , q , b , bBit ) ; Polynomial . polynomialNumberTheoreticTransform ( numberTheoreticTransformY , Y , n ) ; /* V_i = A_i * Y Modulo Q for All i */ for ( short i = 0 ; i < k ; i ++ ) { Polynomial . polynomialMultiplication ( V , n * i , A , n * i , numberTheoreticTransformY , 0 , n , q , qInverse ) ; } hashFunction ( C , 0 , V , message , messageOffset , messageLength , n , k , d , q ) ; /* Generate C = EncodeC (C') Where C' is the Hashing of V Together with Message */ Sample . encodeC ( positionList , signList , C , 0 , n , w ) ; sparsePolynomialMultiplication8 ( SC , 0 , privateKey , 0 , positionList , signList , n , w ) ; /* Z = Y + EC modulo Q */ Polynomial . polynomialAddition ( Z , 0 , Y , 0 , SC , 0 , n ) ; /* Rejection Sampling */ if ( testRejection ( Z , n , b , u ) == true ) { continue ; } for ( short i = 0 ; i < k ; i ++ ) { sparsePolynomialMultiplication8 ( EC , n * i , privateKey , n * ( i + 1 ) , positionList , signList , n , w ) ; /* V_i = V_i - EC_i Modulo Q for All k */ Polynomial . polynomialSubtractionP ( V , n * i , V , n * i , EC , n * i , n , q , barrettMultiplication , barrettDivision ) ; response = testV ( V , n * i , n , d , q , rejection ) ; if ( response == true ) { break ; } } if ( response == true ) { continue ; } if ( q == Parameter . Q_I_P ) { /* Pack Signature */ encodeSignatureIIISpeedIP ( signature , 0 , C , 0 , Z , n , d ) ; } else { /* Pack Signature */ encodeSignature ( signature , 0 , C , 0 , Z ) ; } return 0 ; } }
Description:     Generates A Signature for A Given Message According to the Ring-TESLA Signature Scheme for Provably-Secure qTESLA Security Category-1
                          and Category-3
Description : Generates A Signature for A Given Message According to the Ring - TESLA Signature Scheme for Provably - Secure qTESLA Security Category - 1 and Category - 3