1

This is a homework question that I can't get my head around at all

Its a very simple encryption algorithm. You start with a string of characters as your alphabet:

ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!, .

Then ask the user to enter there own string that will act as a map such as:

0987654321! .,POIUYTREWQASDFGHJKLMNBVCXZ

Then the program uses this to make a map and allows you to enter text that gets encrypted.

For example MY NAME IS JOSEPH would be encrypted as .AX,0.6X2YX1PY6O3

This is all very easy, however he said that its a one to one mapping and thus implied that if I enter .AX,0.6X2YX1PY6O3 back into the program I will get out MY NAME IS JOSEPH

This doesn't happen, because .AX,0.6X2YX1PY6O3 becomes Z0QCDZQGAQFOALDH

The mapping only works to decrypt when you go backwards but the question implies that the program just loops and runs the one algorithm every time.

Even if some could say that it is possible I would be happy, I have pages and pages of paper filled up with possible workings, but I came up with nothing, the only solution to run the algorithm backwards back I don't think we are allowed to do that.

Any ideas?

Edit:

Unfortunately I can't get this to work (Using the orbit computation idea) What am I doing wrong?

//import scanner class
import java.util.Scanner;

public class Encryption {

    static Scanner inputString = new Scanner(System.in);
    //define alphabet
    private static String alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!, .";
    private static String map;
    private static int[] encryptionMap = new int[40];//mapping int array
    private static boolean exit = false;
    private static boolean valid = true;

    public static void main(String[] args) {

        String encrypt, userInput;
        userInput = new String();

        System.out.println("This program takes a large reordered string");
        System.out.println("and uses it to encrypt your data");
        System.out.println("Please enter a mapping string of 40 length and the same characters as below but in different order:");
        System.out.println(alpha);

        //getMap();//don't get user input for map, for testing!
        map=".ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!, ";//forced input for testing only!
        do{
            if (valid == true){
                System.out.println("Enter Q to quit, otherwise enter a string:");
                userInput = getInput();
                if (userInput.charAt(0) != 'Q' ){//&& userInput.length()<2){

                    encrypt = encrypt(userInput);
                    for (int x=0; x<39; x++){//here I am trying to get the orbit computation going
                        encrypt = encrypt(encrypt);
                    }
                    System.out.println("You entered: "+userInput);
                    System.out.println("Encrypted Version: "+encrypt);
                }else if (userInput.charAt(0) == 'Q'){//&& userInput.length()<2){
                    exit = true;
                }

            }
            else if (valid == false){
                System.out.println("Error, your string for mapping is incorrect");
                valid = true;//reset condition to repeat
            }
        }while(exit == false);
        System.out.println("Good bye");
    }

    static String encrypt(String userInput){
        //use mapping array to encypt data
        String encrypt;
        StringBuffer tmp = new StringBuffer();
        char current;
        int alphaPosition;
        int temp;


        //run through the user string
        for (int x=0; x<userInput.length(); x++){
            //get character
            current = userInput.charAt(x);


            //get location of current character in alphabet
            alphaPosition = alpha.indexOf(current);
            //encryptionMap.charAt(alphaPosition)

            tmp.append(map.charAt(alphaPosition));

        }
        encrypt = tmp.toString();
        return(encrypt);
    }

    static void getMap(){
        //get a mapping string and validate from the user
        map = getInput();
        //validate code
        if (map.length() != 40){
            valid = false;
        }
        else{
            for (int x=0; x<40; x++){
                if (map.indexOf(alpha.charAt(x)) == -1){
                    valid = false;
                }
            }
        }
        if (valid == true){
            for (int x=0; x<40; x++){
                int a = (int)(alpha.charAt(x));
                int y = (int)( map.charAt(x));
                //create encryption map
                encryptionMap[x]=(a-y);
            }
        }
    }

    static String getInput(){
        //get input(this repeats)
        String input = inputString.nextLine();
        input = input.toUpperCase();
        if ("QUIT".equals(input) || "END".equals(input) || "NO".equals(input) || "N".equals(input)){
            StringBuffer tmp = new StringBuffer();
            tmp.append('Q');
            input = tmp.toString();
        }
        return(input);
    }




}
0

2 Answers 2

2

You will (probably) not get your original string back if you apply that substitution again. I say probably because you can construct such inputs (they all do things like if A->B then B->A). But most inputs won't do that. You would have to construct the reverse map to decrypt.

However, there is a trick you can do if you're only allowed to go forward. Keep applying the mapping and you'll eventually return to your original input. The number of times you'll have to do that depends on your input. To figure out how many times, compute the orbit of each character, and take the least common multiple of all the orbit sizes. For your input the orbits are size 1 (T->T, W->W), 2 (B->9->B H->3->H U->R->U P->O->P), 4 (C->8->N->,->C), 9 (A->...->Y->A), and 17 (E->...->V->E). The LCM of all those is 612, so 611 forward mappings applied to the ciphertext will return you to the plaintext.

Sign up to request clarification or add additional context in comments.

9 Comments

I tried to implement this,(see above), but can get it to work, do I do the 611 forward mappings on the whole string? Is it always 611 forward runs of the algorithm?
@Josepth: It is 611 forward mappings from the encrypted string, which is 612 forward mappings from the original userInput. You're one shy of the correct number.
Hey Keith, I changed the 610 in the for loop to 611 (to make 612 forward mappings) and unfortunately it does not decrypt the text back, I have also tried making it 609,612 to no effect.
Well if 40 iterations gives you the same thing you typed in, use 20 to encrypt and 20 to decrypt so encrypting and decrypting are the same operation. (Note that the encryption will probably be pretty bad if you do this.)
Yes, using half means that for many of your orbits (those that do not contribute the maximum factors of 2 to the final size) the encryption will be the identity function. In your original example, that's all the orbits except for the length 4 one. So only the characters C8N, will be modified by encryption/decryption.
|
0

Well, you can get your string back this way only if you do reverse mapping. One to one mapping means that a single letter of your default alphabet maps to only one letter of your new alphabet and vice versa. I.e. you can't map ABCD to ABBA. It doesn't imply that you can get your initial string by doing a second round of encryption.

The thing you have described can be achieved if you use a finite alphabet and a displacement to encode your string. You can choose the displacement in such a way that after a number of rounds of encryption totalDisplacement mod alphabetSize == 0 Than you will get your string back going only forward.

1 Comment

Sorry svx, I'm not entirely sure what you mean. I think I would end up with 40 different displacements because of the two alphabets

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.