All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.crypto.generators.GOST3410ParametersGenerator Maven / Gradle / Ivy

Go to download

The Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. This jar contains JCE provider and lightweight API for the Bouncy Castle Cryptography APIs for Java 1.8 and later with debug enabled.

The newest version!
package org.bouncycastle.crypto.generators;

import java.math.BigInteger;
import java.security.SecureRandom;

import org.bouncycastle.crypto.params.GOST3410Parameters;
import org.bouncycastle.crypto.params.GOST3410ValidationParameters;
import org.bouncycastle.util.BigIntegers;

/**
 * generate suitable parameters for GOST3410.
 */
public class GOST3410ParametersGenerator
{
    private int             size;
    private int             typeproc;
    private SecureRandom    init_random;

    private static final BigInteger ONE = BigInteger.valueOf(1);
    private static final BigInteger TWO = BigInteger.valueOf(2);

    /**
     * initialise the key generator.
     *
     * @param size size of the key
     * @param typeproc type procedure A,B = 1;  A',B' - else
     * @param random random byte source.
     */
    public void init(
        int             size,
        int             typeproc,
        SecureRandom    random)
    {
        this.size = size;
        this.typeproc = typeproc;
        this.init_random = random;
    }

    //Procedure A
    private int procedure_A(int x0, int c,  BigInteger[] pq, int size)
    {
        //Verify and perform condition: 065536)
        {
            x0 = init_random.nextInt()/32768;
        }

        while((c<0 || c>65536) || (c/2==0))
        {
            c = init_random.nextInt()/32768 + 1;
        }

        BigInteger C = new BigInteger(Integer.toString(c));
        BigInteger constA16 = new BigInteger("19381");

        //step1
        BigInteger[] y = new BigInteger[1]; // begin length = 1
        y[0] = new BigInteger(Integer.toString(x0));

        //step 2
        int[] t = new int[1]; // t - orders; begin length = 1
        t[0] = size;
        int s = 0;
        for (int i=0; t[i]>=17; i++)
        {
            // extension array t
            int tmp_t[] = new int[t.length + 1];             ///////////////
            System.arraycopy(t,0,tmp_t,0,t.length);          //  extension
            t = new int[tmp_t.length];                       //  array t
            System.arraycopy(tmp_t, 0, t, 0, tmp_t.length);  ///////////////

            t[i+1] = t[i]/2;
            s = i+1;
        }

        //step3
        BigInteger p[] = new BigInteger[s+1];
        p[s] = new BigInteger("8003",16); //set min prime number length 16 bit

        int m = s-1;  //step4

        for (int i=0; i=0) 
                {
                    break; //step 14
                }
                else
                {
                    pq[0] = p[0];
                    pq[1] = p[1];
                    return y[0].intValue(); //return for procedure B step 2
                }
            }
        }
        return y[0].intValue();
    }

    //Procedure A'
    private long procedure_Aa(long x0, long c, BigInteger[] pq, int size)
    {
        //Verify and perform condition: 04294967296L)
        {
            x0 = init_random.nextInt()*2;
        }

        while((c<0 || c>4294967296L) || (c/2==0))
        {
            c = init_random.nextInt()*2+1;
        }

        BigInteger C = new BigInteger(Long.toString(c));
        BigInteger constA32 = new BigInteger("97781173");

        //step1
        BigInteger[] y = new BigInteger[1]; // begin length = 1
        y[0] = new BigInteger(Long.toString(x0));

        //step 2
        int[] t = new int[1]; // t - orders; begin length = 1
        t[0] = size;
        int s = 0;
        for (int i=0; t[i]>=33; i++)
        {
            // extension array t
            int tmp_t[] = new int[t.length + 1];             ///////////////
            System.arraycopy(t,0,tmp_t,0,t.length);          //  extension
            t = new int[tmp_t.length];                       //  array t
            System.arraycopy(tmp_t, 0, t, 0, tmp_t.length);  ///////////////

            t[i+1] = t[i]/2;
            s = i+1;
        }

        //step3
        BigInteger p[] = new BigInteger[s+1];
        p[s] = new BigInteger("8000000B",16); //set min prime number length 32 bit

        int m = s-1;  //step4

        for (int i=0; i=0)
                {
                    break; //step 14
                }
                else
                {
                    pq[0] = p[0];
                    pq[1] = p[1];
                    return y[0].longValue(); //return for procedure B' step 2
                }
            }
        }
        return y[0].longValue();
    }

    //Procedure B
    private void procedure_B(int x0, int c, BigInteger[] pq)
    {
        //Verify and perform condition: 065536)
        {
            x0 = init_random.nextInt()/32768;
        }

        while((c<0 || c>65536) || (c/2==0))
        {
            c = init_random.nextInt()/32768 + 1;
        }

        BigInteger [] qp = new BigInteger[2];
        BigInteger q = null, Q = null, p = null;
        BigInteger C = new BigInteger(Integer.toString(c));
        BigInteger constA16 = new BigInteger("19381");

        //step1
        x0 = procedure_A(x0, c, qp, 256);
        q = qp[0];

        //step2
        x0 = procedure_A(x0, c, qp, 512);
        Q = qp[0];

        BigInteger[] y = new BigInteger[65];
        y[0] = new BigInteger(Integer.toString(x0));

        int tp = 1024;

 step3: for(;;)
        {
            //step 3
            for (int j=0; j<64; j++)
            {
                y[j+1] = (y[j].multiply(constA16).add(C)).mod(TWO.pow(16));
            }

            //step 4
            BigInteger Y = new BigInteger("0");
 
            for (int j=0; j<64; j++)
            {
                Y = Y.add(y[j].multiply(TWO.pow(16*j)));
            }

            y[0] = y[64]; //step 5

            //step 6
            BigInteger N = TWO.pow(tp-1).divide(q.multiply(Q)).
                               add((TWO.pow(tp-1).multiply(Y)).
                                   divide(q.multiply(Q).multiply(TWO.pow(1024))));

            if (N.mod(TWO).compareTo(ONE)==0)
            {
                N = N.add(ONE);
            }

            int k = 0; //step 7

     step8: for(;;)
            {
                //step 11
                p = q.multiply(Q).multiply(N.add(BigInteger.valueOf(k))).add(ONE);

                if (p.compareTo(TWO.pow(tp))==1)
                {
                    continue step3; //step 9
                }

                //step10
                if ((TWO.modPow(q.multiply(Q).multiply(N.add(BigInteger.valueOf(k))),p).compareTo(ONE)==0) &&
                    (TWO.modPow(q.multiply(N.add(BigInteger.valueOf(k))),p).compareTo(ONE)!=0))
                {
                    pq[0] = p;
                    pq[1] = q;
                    return;
                }
                else
                {
                    k += 2;
                    continue step8;
                }
            }
        }
    }

    //Procedure B'
    private void procedure_Bb(long x0, long c, BigInteger[] pq)
    {
        //Verify and perform condition: 04294967296L)
        {
            x0 = init_random.nextInt()*2;
        }

        while((c<0 || c>4294967296L) || (c/2==0))
        {
            c = init_random.nextInt()*2+1;
        }

        BigInteger [] qp = new BigInteger[2];
        BigInteger q = null, Q = null, p = null;
        BigInteger C = new BigInteger(Long.toString(c));
        BigInteger constA32 = new BigInteger("97781173");

        //step1
        x0 = procedure_Aa(x0, c, qp, 256);
        q = qp[0];

        //step2
        x0 = procedure_Aa(x0, c, qp, 512);
        Q = qp[0];

        BigInteger[] y = new BigInteger[33];
        y[0] = new BigInteger(Long.toString(x0));

        int tp = 1024;

 step3: for(;;)
        {
            //step 3
            for (int j=0; j<32; j++)
            {
                y[j+1] = (y[j].multiply(constA32).add(C)).mod(TWO.pow(32));
            }

            //step 4
            BigInteger Y = new BigInteger("0");
            for (int j=0; j<32; j++)
            {
                Y = Y.add(y[j].multiply(TWO.pow(32*j)));
            }

            y[0] = y[32]; //step 5

            //step 6
            BigInteger N = TWO.pow(tp-1).divide(q.multiply(Q)).
                               add((TWO.pow(tp-1).multiply(Y)).
                                   divide(q.multiply(Q).multiply(TWO.pow(1024))));

            if (N.mod(TWO).compareTo(ONE)==0)
            {
                N = N.add(ONE);
            }

            int k = 0; //step 7

     step8: for(;;)
            {
                //step 11
                p = q.multiply(Q).multiply(N.add(BigInteger.valueOf(k))).add(ONE);

                if (p.compareTo(TWO.pow(tp))==1)
                {
                    continue step3; //step 9
                }

                //step10
                if ((TWO.modPow(q.multiply(Q).multiply(N.add(BigInteger.valueOf(k))),p).compareTo(ONE)==0) &&
                    (TWO.modPow(q.multiply(N.add(BigInteger.valueOf(k))),p).compareTo(ONE)!=0))
                {
                    pq[0] = p;
                    pq[1] = q;
                    return;
                }
                else
                {
                    k += 2;
                    continue step8;
                }
            }
        }
    }


    /*
     * Procedure C
     * procedure generates the a value from the given p,q,
     * returning the a value.
     */
    private BigInteger procedure_C(BigInteger p, BigInteger q)
    {
        BigInteger pSub1 = p.subtract(ONE);
        BigInteger pSub1DivQ = pSub1.divide(q);
        int length = p.bitLength();

        for(;;)
        {
            BigInteger d = BigIntegers.createRandomBigInteger(length, init_random);

            // 1 < d < p-1
            if (d.compareTo(ONE) > 0 && d.compareTo(pSub1) < 0)
            {
                BigInteger a = d.modPow(pSub1DivQ, p);

                if (a.compareTo(ONE) != 0)
                {
                    return a;
                }
            }
        }
    }

    /**
     * which generates the p , q and a values from the given parameters,
     * returning the GOST3410Parameters object.
     *
     * @return a generated GOST3410 parameters object.
     */
    public GOST3410Parameters generateParameters()
    {
        BigInteger [] pq = new BigInteger[2];
        BigInteger    q = null, p = null, a = null;

        int  x0, c;
        long  x0L, cL;

        if (typeproc==1)
        {
            x0 = init_random.nextInt();
            c  = init_random.nextInt();

            switch(size)
            {
            case 512:  
                procedure_A(x0, c, pq, 512); 
                break;
            case 1024: 
                procedure_B(x0, c, pq); 
                break;
            default: 
                throw new IllegalArgumentException("Ooops! key size 512 or 1024 bit.");
            }
            p = pq[0];  q = pq[1];
            a = procedure_C(p, q);
            //System.out.println("p:"+p.toString(16)+"\n"+"q:"+q.toString(16)+"\n"+"a:"+a.toString(16));
            //System.out.println("p:"+p+"\n"+"q:"+q+"\n"+"a:"+a);
            return new GOST3410Parameters(p, q, a, new GOST3410ValidationParameters(x0, c));
        }
        else
        {
            x0L = init_random.nextLong();
            cL  = init_random.nextLong();

            switch(size)
            {
            case 512:  
                procedure_Aa(x0L, cL, pq, 512); 
                break;
            case 1024: 
                procedure_Bb(x0L, cL, pq); 
                break;
            default: 
                throw new IllegalStateException("Ooops! key size 512 or 1024 bit.");
            }
            p = pq[0];  q = pq[1];
            a = procedure_C(p, q);
            //System.out.println("p:"+p.toString(16)+"\n"+"q:"+q.toString(16)+"\n"+"a:"+a.toString(16));
            //System.out.println("p:"+p+"\n"+"q:"+q+"\n"+"a:"+a);
            return new GOST3410Parameters(p, q, a, new GOST3410ValidationParameters(x0L, cL));
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy