//---------------------------------------------------------------------------//
//                                                                           //
//  Source file: RSA.java                                                    //
//                                                                           //
//  Description: Implements RSA assymetric cipher algorithm base class       //
//                                                                           //
//  Author: Pavel Hrdina, [email protected]                                 //
//                                                                           //
//---------------------------------------------------------------------------//import java.io.Serializable;
import java.math.BigInteger;
import java.util.Random;//
//  Class implementing RSA assymetric cipher algorithm
//public class RSA implements Serializable
{
    //
    //  Multiply of the lost two primes p and q
    //    protected BigInteger N;    //
    //  Decrypting and encrypting coefficient
    //    protected BigInteger D;
    protected BigInteger E;    //
    //  Random number generator
    //    private static Random RndGenerator = new Random();    //
    //  Constant BigInteger with the value of 1 (one)
    //    protected static final BigInteger BigOne = BigInteger.valueOf(1);    //
    //  Constructor which generates new instance based on bit sizes
    //    public RSA(int BitSizePQ, int BitSizeDE)
    {
        //
        //  Coeficients which we can forget
        //        BigInteger P, Q, F;        //
        //  Generating new p and q, primes with probability (1 - 1/2^64)
        //        P = new BigInteger(BitSizePQ, 64, RndGenerator);
        Q = new BigInteger(BitSizePQ, 64, RndGenerator);        //
        //  Compute f = (p-1)*(q-1) and n = p*q
        //        F = P.subtract(BigOne).multiply(Q.subtract(BigOne));
        N = P.multiply(Q);        //
        //  Generate d which is relatively prime with f
        //  Count e which is d^-1 mod f
        //        do
        {
            D = new BigInteger(BitSizeDE, RndGenerator);
        }
        while (D.gcd(F).compareTo(BigOne) != 0);        E = D.modInverse(F);
    }    //
    //  Constructor which creates new instance based on Other
    //    public RSA(RSA Other)
    {
        N = Other.N;        D = Other.D;
        E = Other.E;
    }    //
    //  Encrypts message
    //    public void Encrypt(byte[] Input, byte[] Output)
    {
        int BlockSize = (N.bitLength() + 7)/8;
        int i, j;        //
        //  For every block do the encryption separatedly
        //        for (i=0; i<Input.length; i+= BlockSize)
        {
            byte[] enc;
            byte[] dec = new byte[BlockSize];
            BigInteger x;            //
            //  Get proper block from input stream and encrypt it
            //            for (j=0; j<BlockSize; j++)
            {
                dec[j] = Input[i+j];
            }            x = new BigInteger(dec);
            enc = x.modPow(E,N).toByteArray();            //
            //  Write the block to output stream
            //            for (j=0; j<BlockSize; j++)
            {
                Output[i+j] = enc[j];
            }
        }
    }    //
    //
    //    public void Decrypt(byte[] Input, byte[] Output)
    {
        int BlockSize = (N.bitLength() + 7)/8;
        int i, j;        //
        //  For every block do the decryption separatedly
        //        for (i=0; i<Input.length; i+= BlockSize)
        {
            byte[] dec;
            byte[] enc = new byte[BlockSize];
            BigInteger y;            //
            //  Get proper block from input stream and decrypt it
            //            for (j=0; j<BlockSize; j++)
            {
                enc[j] = Input[i+j];
            }            y = new BigInteger(enc);
            dec = y.modPow(D,N).toByteArray();            //
            //  Write the block to output stream
            //            for (j=0; j<BlockSize; j++)
            {
                Output[i+j] = dec[j];
            }
        }
    }
}