CSE 132 (Spring 2009)
Review studio procedures, if
necessary, before starting.
Studio 6: Streams, Sockets, and Caesar's Cipher
Some guidelines for this week's studio:
- Before you start, grab a Studio Observation form for your
have to fill it out as you go.
- Download and import this zip.
All groups do the following
I wrote this class with you during lecture. Take a look at
its getInputStream(int numWords) method. It shows
how an InputStream is formed and the role of the
Why does the method return -1 when there are no more characters
- Be prepared to explain how this class works to the TA.
- Take a look at the Crypto class.
- As given to you, the
encrypt(char) method doesn't encrypt anything but just returns
what it is given.
- The decrypt(char) method is fine, but it uses the
encrypt(char) class which is not yet working.
- Run the CryptoTest as a JUnit test and watch it fail.
- Modify encrypt(char) at the TODO so that
it returns a lower case letter shifted by the class's shift
- You can treat characters ('a') as numeric values,
in the sense that you can add to them, etc.
- The lower case characters are contiguous in their representation and
are numbered 'a' through 'z'.
- You will have to use mod (%) to return the proper value.
- Arithmetic with the shift value will take place in
int world because shift is an int.
You will have to cast the result expression to
a char before returning anything. Do not change
the return type of the methods.
- The code as given to you attempts to encrypt only lower case characters.
All other characters are transmitted as supplied.
This is the desired behavior.
- Test your Crypto class using the supplied JUnit
Sender or Receiver?
Find another group near you and decide which group will
be a Sender so that the other group is a Receiver.
You can decide by consensus, by a flip of a coin, or by playing
Rock, Paper, Scissors. Don't spend too much time figuring
out who is who.
The TAs can dictate which group you will be. You can avoid such action
by finding another group early and sorting this out.
- It is useful (and probably obvious) that the two groups be within
earshot of each other. Try the group across the table from you. If there
is no such group, maybe you should find another table.
You don't want the other group to discover your secret key.
- It is important (and probably obvious) that the two groups are not on the same machine.
- It is essential (and not so obvious) that the two groups are not running eclipse from
within the same workspace.
The best way to ensure no problems is for the groups to log in using
different accounts on different machines across the table from each other.
Based on your group's
role (Sender or Receiver), follow the steps below.
- When you are ready to interact with the other group,
if they are not ready, then find another group doing the other part
and connect with them.
- As a group, decide on an encryption shift value n for your
The number you choose must be
such that 1≤n≤25.
Keep your number a secret within your group.
- Write a class Adapter
- Whose constructor takes an InputStream and an
- Whose run() method continually reads from the
InputStream and writes to the OutputStream, until
the InputStream is exhausted.
- Be sure to flush() the OutputStream when done
(and don't leave your seat up).
- You can .close() both streams when you are done.
You do not send a -1 to indicate end-of-stream. You do that
by closing the stream.
Your work from here on should go into the run() method
of the Sender class.
- Test your Adapter on 20 words or so by:
Adapter io = new Adapter(new Preamble().getInputStream(20), System.out);
You should see the preamble words printing out in your console.
- Show your Adapter to other groups or to a TA.
- Write a similar class ForkStream
- Whose constructor takes in a single InputStream and two
- Whose run() method continually reads from the InputStream
and writes each byte to both of the OutputStrams.
OK now let's try sending the Preamble to your Receiver group.
- Create a
connection to your Receiver's
machine, using the host name and port number that they
- Use your Adapter to connect from the
Preamble input stream to the Socket's output stream.
- The Receiver group must be running their application or
your code will fail to connect to the server socket. They should run
their application first and then you should launch yours.
- Recall how to
get the Socket's output stream.
- When you execute your .run() of your Adapter,
they should receive the information you are sending in clear text
- Verify that they are seeing this.
- Now use your ForkStream class to connect the Preamble
to both the Socket OuptutStream and to System.out.
Now you can see what's beeing sent as well.
Now we encrypt!
- Modify your ForkStream so that each byte of
the input stream
is run through a
encrypt(char). method before sending the byte to the
The Crypto object should be suitably instantiated with your
secret shift value.
You will have to cast the int to a byte for
encrypt to accept it.
Try sending to the Receiver again. You should both be seeing
the encrypted version.
- Change ForkStream so you see the clear text version but
the Receiver continues to see the encrypted version.
Did the Receiver team correctly guess your encryption key?
- Once they are good at that, and can decrypt messages, change your key
and try this again.
- Now try sending messages you type in yourself, by prompting
yourself for a String using
- You probably don't want to close the connection after each message, but
you probably should flush() so your message gets sent right
Arrange for your Sender to keep sending until a particular string
- Find out your machine's host name using the technique
shown in class.
- Decide on a port address at which you will offer your
I checked out the machines in the attic, and at least port 3000 is
available. If you have trouble offering service on that port at some
point, you can try another.
- Be prepared to tell other groups your host name and the port address
at which you will offer service.
First we try to receive clear text
Your work from here on should go into the run() method
of the Receiver class.
- Instantiate a ServerSocket at the port address.
- Write code to accept() on the ServerSocket.
- Get the resulting Socket's InputStream.
- Write an Adapter class, using the specification given
above for the Sender.
- Use the Adapter to connect the Socket's
InputStream to System.out. This will let you see
the messages that are sent.
- Verify that you are receiving the text sent by your Sender
If your other group is not ready, try to find a group
that is and interact with them to test this out so you can move forward.
Now we prepare for the encrypted messages.
- The Sender will send messages
using a Caesar cipher.
Your job is to analyze the messages coming across the Socket and
determine the value of the key for the cipher.
The key value will be in the range
- Figure out as a group how to determine the value of the shift.
Some ideas were given in class.
- Write a class that analyzes properties of interest
concerning the text you are receiving.
It is not acceptable to try all 25 keys at once. You must show the TAs that
you have cleverly determined the key.
Now try to decrypt the messages.
- Keep asking your Sender group to send you messages of
a length you specify. It is unfair to ask them to send a particular
- Once you believe you know the cipher key, interpose an
instance of a Crypto object with the key and use its
decrypt message in your Adapter class to process
each byte so you can (try to) see the clear text.
- What encryption methods are more resistant to attack than Caesar's cipher?
- How is encryption currently implemented in widely used systems?
- Facebook chat (one article)
- Wireless networks
- SSL to support https
- ssh and sftp
- ATM (cash machines)
Last modified 20:11:02 CST 11 January 2010
by Ron K. Cytron