Java Stream Cipher (With input and output txt files) outputting random characters not complete decrypted string

2.1k views Asked by At

Don't know where I went wrong necessarily but my program is supposed to be a stream cipher that takes an input.txt file of chars and encrypts it into numbers and then decrypts it back to chars.

My issue is that I type in:

java Program4 -e 71 < inp.txt > out.txt

(to encrypt txt to output file and it works fine,) input file looks like:

guess what? Chicken butt

output file looks like:

222 204 220 202 202 153 206 209 216 205 134 153 250 209 208 218 210 220 215 153 219 204 205 205

Then when I decrypt the file..

java Program4 -d 71 < out.txt

it comes out like this:

g  E ?  ? 8 º ? Ä ì  ß ê ( ? ½ ^ ~ ? ? X  ?

I don't know what I'm doing wrong but I'm guessing it's something with my decryption method or how my encryption gives the same number on some values? I truly appreciate any help!

import java.util.Scanner;
import java.util.Random;
public class Program4
{
public static void main(String[] args)
{
    if(args.length < 2)
    {
        usage();
    }
    else if(args[0].equals("-e"))
    {
        encrypt(args);
    }
    else if(args[0].equals("-d"))
    {
        decrypt(args);
    }

}   
        //Intro (Usage Method)
    public static void usage()
    {
        System.out.println("Stream Encryption program by my name");
        System.out.println("usage: java Encrypt [-e, -d] < inputFile > outputFile" );
    }
        //Encrypt Method
        public static void encrypt(String[] args)
    {   Scanner scan = new Scanner(System.in);
        String key1 = args[1];
        long key = Long.parseLong(key1);
        Random rng = new Random(key);
        int randomNum = rng.nextInt(256);
        while (scan.hasNextLine())
        {
            String s = scan.nextLine();
            for (int i = 0; i < s.length(); i++)
            {
                char allChars = s.charAt(i);
                int cipherNums = allChars ^ randomNum;
                System.out.print(cipherNums + " ");
            }

        }
    }   

        //Decrypt Method
        public static void decrypt(String[] args)
    {   String key1 = args[1];
        long key = Long.parseLong(key1);
        Random rng = new Random(key);
        Scanner scan = new Scanner(System.in);

            while (scan.hasNextInt())
        {
            int next = scan.nextInt();
            int randomNum = rng.nextInt(256);
            int decipher = next ^ randomNum;
            System.out.print((char)decipher + " ");

        }

    }

}
1

There are 1 answers

2
Jon Skeet On BEST ANSWER

You're using your random number generator differently in the two cases. In your encryption code, you generate one random number, and use it for all characters:

Random rng = new Random(key);
int randomNum = rng.nextInt(256);
while (scan.hasNextLine())
{
    String s = scan.nextLine();
    for (int i = 0; i < s.length(); i++)
    {
        char allChars = s.charAt(i);
        int cipherNums = allChars ^ randomNum;
        System.out.print(cipherNums + " ");
    }
}

In your decryption code, you generate a new random number per character:

while (scan.hasNextInt())
{
    int next = scan.nextInt();
    int randomNum = rng.nextInt(256);
    int decipher = next ^ randomNum;
    System.out.print((char)decipher + " ");
}

The best way to fix this (to avoid each 'e' always encrypting to the same number, for example) would be to use a new random number for each character when encrypting:

Random rng = new Random(key);
while (scan.hasNextLine())
{
    String s = scan.nextLine();
    for (int i = 0; i < s.length(); i++)
    {
        char allChars = s.charAt(i);
        int randomNum = rng.nextInt(256);
        int cipherNums = allChars ^ randomNum;
        System.out.print(cipherNums + " ");
    }
}

(Of course, this code shouldn't be used for real encryption - I assume it's only for the purposes of education.)