0

I am working on a Stream Cipher program in Java which should take three arguments from the shell: a file with a key, a file for input, and a file for output. The key should then serve as the seed which should generate a pseudo-random number which should be "XOR:ed" with the plaintext in the input file.

I have managed to write the code for reading a file but I do not know how I am supposed to write the code for taking the key as the seed and thus generate a pseudo-random number as explained above. Could someone help me?

public static void main(String[] args) throws IOException {
   File key = null;
   File input = null;
   File output = null;
   if (0 < args.length) {
      key = new File(args[0])
      input = new File(args[1]);
      output = new File(args[2]);
}
//more stuff

//a function that takes the seed from the key file and should generate a pseudo-random number

int prng (long seed) {
    Random random = new Random ();
    int bound = 256;
    int number = random.nextInt(bound);

    return number;

    }


      
Pete97
  • 81
  • 1
  • 2
  • 6
  • 1
    I don't see a stream cipher there. You can use AES in CTR mode or use ChaCha20 – kelalaka Mar 26 '21 at 20:59
  • If this is a learning exercise, then you could try coding [RC4](https://en.wikipedia.org/wiki/RC4) which is a stream cipher, but a lot easier to write for yourself than AES. For an exercise RC4 is fine, but it is now obsolete and no longer secure. It does give a good insight into how a stream cipher works. – rossum Mar 27 '21 at 11:20
  • @rossum Thank you for your answer, however I am not allowed to use neither RC4 or AES in this exercise, I have to use the library java.util.Random. How do I generate a random number stream from taking a seed from a user input? – Pete97 Mar 28 '21 at 14:49

2 Answers2

0

Pseudo-random as described by the assignment doesn't mean that you need to use a random number generator. The key stream created by the stream cipher is pseudo random (to an adversary) because it is generated from a key that they don't know. So you should not be using either Random or SecureRandom or similar. Instead, you should be using Cipher.

Basically there are two ways that you can implement CTR mode. First, you can create a stream of 16-byte unique values and encrypt them using AES in ECB mode (or use the block cipher directly, but that's not available in Java). Then you get 16 bytes of key stream in return, which you can buffer and use to XOR with the plaintext.

You can also cheat and use AES/CTR/NoPadding. Then to get to the key stream you update with bytes all set to zero. Because XOR with zero is the identity function, you'll get the key stream back. This you can in turn XOR with the actual plaintext to get the ciphertext. As this is for practice, you probably learn more if you implement the earlier method though.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • Thank you for your answer, unfortunately I am only allowed to use the library java.util.random in this exercise in order to generate a stream of bytes. – Pete97 Mar 28 '21 at 14:54
0

You need a stream of (pseudo-)random bytes using java.util.Random. Start by reading the seed/key from the user and use that to initialise your instance of the Random class.

long seedKey = getUserInput();
Random myRandom = new Random(seedKey);

Do that once only at the start of your code.

Next, you need to process your input. If you are happy with using streams, then you could use Random.ints() or Random.longs() to generate the random keystream. Alternatively, break up the input file into chunks and use Random.bytes(myAry) to get enough bytes to XOR with whatever size chunk you are using.

Unless you are using one byte chunks you will need to deal with any part-chunk left at the end of the input.

Output from the XOR will be raw bytes, not text. If you need text output then convert to Base64 using java.util.Base64 so you get something printable, which raw encrypted bytes are not.

rossum
  • 15,344
  • 1
  • 24
  • 38