mardi 22 mars 2016

Java: Using RSA to Convert a String

this is my first post on here so I'm hoping it'll be the start of a fun community!

I am attempting to make an RSA encrypter and decrypter. It works perfectly for numbers, but when I try to implement text it gets a bit screwy. I have posted all of my code, but the main part I'm having issues with is where there are comments. (After the else in the main statement).

Code:

    public class RSA{

    public static void main(String[] args) {
        System.out.println("Welcome the small-scale RSA Testing Tool!");
        System.out.println("========================================= \n");
            System.out.println("Please type two relatively small prime numbers");
            Scanner ob=new Scanner(System.in);
            System.out.print("p: ");
            int p = ob.nextInt();

            System.out.print("\nq: ");
            int q = ob.nextInt();

            System.out.println("\nn = p * q = " + p * q);

            int t = (p-1) * (q-1);
            System.out.println("t = (p-1) * (q-1) = " + t);

            System.out.println("Please type an e that is relatively prime with t=" + t +" : ");

            int e = ob.nextInt();

            int keys[] = rsaKeyGen(p, q, e);

            System.out.println("Public Keys: n = " + keys[0] + " and e = " + keys[1] + "(published)");
            System.out.println("Private Key: d = " + keys[2] + " (You should keep this secret!)");

            System.out.println("Testing the encryption/decryption using the above generated keys: ");
            System.out.println("Would you like to decript a number or a text?");
            System.out.println("Type 1 for number or 2 for text");
            Scanner aScanner=new Scanner(System.in);
            int anAnswer = aScanner.nextInt();
            if (anAnswer == 1) {
                System.out.print("Please type a number to encrypt (0 to exit): ");
                int x = ob.nextInt();
                BigDecimal y = null;
                BigDecimal z = null;

                while(x!=0){
                    if(x>=p*q) System.out.println("The number should be within (1 - " + (p*q-1) + ").");
                    else{
                        y = rsaEncrypt(new BigDecimal(x), new BigDecimal(keys[1]), new BigDecimal(keys[0]));
                        System.out.println("Result: "+ x +" encrypted to " + y);
                        System.out.println("");
                        z = rsaDecrypt(y, new BigDecimal(keys[2]), new BigDecimal(keys[0]));
                        System.out.println("Result: "+y+" decrypted to " + z);

                        if(x==z.intValue())    System.out.println("It works!");
                        else        System.out.println("It did not work, please check your implementation!");
                    }
                    System.out.print("Please type a number to encrypt (0 to exit): ");
                    x = ob.nextInt();
                }
                System.out.println("Done!");
            }
            else
                System.out.print("Please type a text to encrypt (0 to exit): ");
                String theString = ob.next(); //gets the string typed in
                char[] ciphertext= new char[theString.length()]; //creates an array of chars length of theString
                BigDecimal y = null;
                BigDecimal z = null;
                for (int j=0; j<theString.length();j++) { //for each char in theString
                    char c = theString.charAt(j);
                    int x = c; //get the ascii value of the char
                    y = rsaEncrypt(new BigDecimal(x), new BigDecimal(keys[1]), new BigDecimal(keys[0])); //encrypt
                    int finalValue = y.intValue(); //puts the intValue of the BigDecimal y into finalValue
                    ciphertext[j]= (char) finalValue; //gets the ascii figure from ascii value and puts in ciphertext
                }
                System.out.println("Result: "+ theString +" encrypted to " + new String(ciphertext)); // prints out encryption
                System.out.println("");






        }

    public static int[] egcd(int k, int j){
        List<Integer> quotients      = new ArrayList<Integer>();
        List<Integer> remainders    = new ArrayList<Integer>();
        List<Integer> xs = new ArrayList<Integer>();
        List<Integer> ys = new ArrayList<Integer>();

        int oldK = k;

        int quotient     = k / j;
        int remainder   = k % j;
        int gcd = remainder==0?j:1;
        while (remainder != 0){
            quotients.add(new Integer(quotient));
            remainders.add(new Integer(remainder));
            k = j;
            j = remainder;
            quotient     = k / j;
            remainder    = k % j;
            gcd = j;
        }

        int result[] = new int[2];
        result[0] = gcd;

        if(gcd != 1) {
            System.out.println("These two numbers "+ j + " and " + k+ " are not relatively prime.");
            System.exit(0);

        }
        xs.add(1);
        ys.add(0);

        int y = 1;
        int x = 0 - ((int)quotients.remove(quotients.size()-1)) * 1;
        int oldY = y;
        int oldX = x;

        while(quotients.size() > 0){
            y = x;
            x = oldY - ((int)quotients.remove(quotients.size()-1)) * oldX;
            oldY = y;
            oldX = x;
        }


        result[1] = mod(new BigDecimal(x), new BigDecimal(oldK)).intValue();

        return result;
    }

    public static int[] rsaKeyGen(int p, int q, int e){
        int n, d, t;
        int keys[] = new int[3];
        keys[0] = n = p * q;
        keys[1] = e;
        t = (p-1)*(q-1);
        int gcdx[] = egcd(t, e);
        keys[2] = gcdx[1];

        return keys;
    }

    public static BigDecimal rsaEncrypt(BigDecimal x, BigDecimal e, BigDecimal n){
        System.out.println("Encrypting " + x + " with e = " + e + " and n = " + n);
        return mod(x.pow(e.intValue()), n);
    }

    public static BigDecimal rsaDecrypt(BigDecimal y, BigDecimal d, BigDecimal n){
        System.out.println("Decrypting " + y + " with d = " + d + " and n = " + n);
        return  mod(y.pow(d.intValue()), n);
    }



    public static BigDecimal mod(BigDecimal a, BigDecimal n){
        if(a.compareTo(new BigDecimal(0)) == -1)
            return n.subtract(a.negate().remainder(n));
        else
            return a.remainder(n);
    }
}

It runs, but the encryption it prints out is... three very little boxes with question marks in them? I've never seen anything like it before. Like I said, it works perfectly fine for numbers, and I should be able to easily impliment it using the ASCII codes of each char in the text, but I'm not sure where I'm going wrong.

Any and all help is much appreciated!!

Aucun commentaire:

Enregistrer un commentaire