20-CS-694 Advanced Programming Techniques Spring 2012
I-Wars Project

Interfaces, Exceptions, Graphics, Animation, Threads, Reflection, Networking, RMI, JDBC, JNI

I-Wars Project and Protocol Details

Monitor Source
   
 
Grading Policy
It might make sense to read the rest of this page and then return here to see the grading policy. This grading policy applies to the project only. Students should read this carefully and make suggestions for refinement until they are comfortable that they completely agree with and understand the policy and they believe there will be no surprises at grading time.

My grading objective to assign high grades to students who have mastered the Java language and have demonstrated an ability to use many of its features creatively and effectively. If all students have mastered the language then all students get high grades. A student is not competing against any other student for a grade.

More is not better. A lot of bad code is no substitute for a small amount of good code. Using all features of Java does not insure a high grade. Using a subset of features well is preferred to sloppy use of many features. If you are using a feature where another would be more appropriate, some points will be lost.

High grading does not depend at all on the amount of wealth accumulated by an individual's system. Nor is it heavily dependent on strategies employed for acquiring wealth. There are some required elements that must appear in your submission in order to get a high grade. There are also some optional elements that help secure a high grade. The required elements are as follows: your system must be able to locate the Monitor, and other systems. It must be able to send and receive messages formatted below (don't look - it's not there yet). It must be able to provide for secure transmission of messages. It must make an attempt at preventing an intruder from gaining access to sensitive information. Optionally, a system may attempt to seek and succeed in finding, at least in some cases, information related to the wealth of other systems; a system may "plant" Java code on another system and run it. Any creative tricks will be appreciated as well.

 
Rationale
This will use just about every aspect of the material learned especially networking and security.
 
Objective
Each student is to design and build a Java system which attempts to accumulate a maximum amount of wealth through communications with other student systems and a monitor system maintained by the instructor and an aid.
 
Description
Abstract

This document will describe the protocol and design used by client hosts in interacting on the Monitor server. The Monitor is a server provided to implement a game for a set of participants to play. The purpose of the game is to earn as many points as possible through the use of various interfaces and features. The participants may implement various mechanisms for attacks against other participants to prevent victims from receiving points and even for stealing points directly from other participants.

Communication Modes with the Monitor
The Monitor will provide multiple services for interfacing from the client machines. There are two connection methods: Active and Passive. The Active Connection is established when a game participant initiates a connection to the Monitor. The Passive Connection is established when the monitor initiates a connection to a listening client.
 
Active Connections
The monitor provides active connections to the game participant by listening on a pre-selected port. The selected port(s) for the project is 8180 of gauss.ececs.uc.edu. Active connections require participants to connect to the selected port and authenticate themselves to the listening monitor via a pre-selected cookie or password. A participant logs in over an active connection.
 
Passive Connections
The login protocol, described below, requires participants to start a passive server which listens for Monitor messages on a legal port of their choice. The port number is given to the Monitor during the login handshake. The passive server serves two functions. First, it is used to accumulate wealth for the participant. The Monitor connects to a participant's passive server from time to time to verify that the server is up and running. Acknowledgement of so-called alive queries is necessary for the participant to receive wealth from the Monitor. Alive queries may happen at any time, for any reason. Second, passive connections are the primary medium for any sort of out-of-band connections, such as for proxied user-to-user communications.
 
Communication Protocol
All communication between active client, passive server, and Monitor is in the form of line-buffered, text messages. Each text message may contain one or more lines of text, called a message group. Each line of a message group is called a Directive. The format of each directive in a message group is the following:
                DIRECTIVE: body-of-directive 
Possible directives are given below. The client normally responds to the message group with a single line of text with the following format:
                COMMAND ARG1 ARG2 ARG3...  
The delimiter of command and arguments is the blank character. Possible commands are given below.

A communication sequence is a series of exchanges between Monitor and client to achieve some result. It begins with the Monitor sending a message group specifying a command that the client is expected to issue next. The client issues the command with arguments. The Monitor responds with another message group and so on until some result is achieved.

 
Monitor Directives
The types of directives used by the Monitor fall into the following categories: RESULT:, REQUIRE:, ERROR:, COMMENT:, and WAITING:. This list may be ammended in future revisions of the monitor (the current version is 2.9). Directive format is given above. The body of a directive specifies associated detail which informs the client of the status at the current point of the communication sequence. Message groups always end with the WAITING: directive. A common communication sequence looks something like this:
     ... 
     CLIENT> ALIVE S54DFSESX4234DX
     MONITOR> RESULT: ALIVE Identity verified.
     MONITOR> REQUIRE: HOST_PORT
     MONITOR> WAITING:
     CLIENT> HOST_PORT LOCALHOST 31337
     ...
One might think of the WAITING: directive as a flow-control message from the Monitor. Upon receiving the WAITING: directive, the client knows that the monitor is expecting it to act on the provided information and issue a command when ready. The following table explains the function of each directive.

Name Description
REQUIRE: ARG1 Indicates that the sender is demanding that the next Command from receiver be ARG1. If the receiver sends some Command besides ARG1, the most likely result will be a COMMAND_ERROR: Directive, and another REQUIRE: ARG1 Directive in the next Message Group.
RESULT: ARG1 STRING This Directive is used to return results from the last Command issued by the receiver. ARG1 will be the Command for which these are results. STRING, in this case, will not be free-form. Rather, it will be in the format as described by the result format for the Command, ARG1. In many cases, particularly with those commands that generate no results, STRING will be the empty string. Note that the RESULT: Directive does not appear when there is an error executing a given command. See the COMMAND_ERROR Directive.
COMMENT: STRING This Directive is used to give verbose output on the operation of various Commands, and to give general feedback about a variety of things. STRING is completely free-form, and more than likely will only be useful to human eyes for debugging. Not every Message Group is guaranteed to have a COMMENT directive.
PLAYER_PASSWORD_CHECKSUM: ARG1 This Directive is sent by the Monitor to authenticate to the player. ARG1 is a SHA-1 digest of the player's password, represented in hexadecimal. This directive is most useful when the player receives a connection on its server port. The Monitor will always have this Directive in the first Message Group that it sends during an active client connection. However, it is up to the player to verify that ARG1 does, in fact, authenticate the Monitor properly. Note that some players will most surely be attempting to impersonate the Monitor!
WAITING: Indicates that the current Message Group is complete, and the sender awaits a Command from the receiver.
COMMAND_ERROR: STRING Indicates that an error occurred during the processing of the last Command. This could be because of invalid arguments, incorrect number of arguments, an unexpected Command (e.g., if a different Command is currently REQUIREd), or because a Command is not yet implemented. The STRING will be a diagnostic error message. COMMAND_ERROR only appears in a Message Group if there was an error with the last command.
TRADE: Player_1   to_trade   to_amount   for   Player_2   for_trade   for_amount This Directive is sent by the Monitor to Player_2, on behalf of Player_1, because Player_1 wishes to offer a trade to Player_2. The resource offered for trade is given by to_trade and the amount by to_amount. Note that Player_2 will always be the receiver of the Directive, otherwise the Directive is basically meaningless. The resource desired in exchange for that offered is given by for_trade and the amount by for_amount.
WAR_DECLARATION: Player_1 This Directive is sent by the Monitor to a player, on behalf of Player_1, who is declaring war on the player. Note that Player_1 will always be the receiver of the Directive, otherwise the Directive is basically meaningless. This Directive usually occurs in a message group with a REQUIRE: WAR_DEFEND.
WAR_TRUCE_OFFERED:   Player_1   to   Player_2   resource   amount... This Directive is sent by the Monitor to a player on behalf of Player_1 who is asking for the truce. The identity of the Player who will benefit from the truce is Player_2. The tail of the Directive consists of one or more resource, amount pairs offered in negotiating terms of the truce. If the truce is accepted, the amounts of those resources will be transferred from Player_1 to the player.

RESULT: codes

When the Monitor responds to the action(s) of one of the clients, it sends a RESULT: directive to the client. This directive has the following format:

      RESULT: body-of-result-directive
The above directive is the result of some operation the client performed. The body of the directive may not necessarily be all caps or all lowercase and may consist of many blank or comma separated tokens. The blanks are not considered separators in the same way as they are in the client commands. After a RESULT: is received, a client may parse the body to determine what course of action to take next.

REQUIRE: codes

The Monitor uses the REQUIRE: directive to demand information from a client. This directive requests that the client perform a specific action. Typically, the action is invocation of a command which has been determined by the Monitor and which is included in the REQUIRE: directive. In the sample communication sequence given above, the Monitor issues a REQUIRE: HOST_PORT directive and expects the client to respond with a HOST_PORT command. After receiving the WAITING: directive, and starting a passive server on port 31337 of the localhost, the client sends the HOST_PORT LOCALHOST 31337 command to the Monitor. More information on commands is given below.

WAITING: codes

This directive has no body. Its presence merely signifies it is waiting for the client to some specified information to the Monitor.

COMMENT: codes

The Monitor may place comments anywhere in a message group before the WAITING: directive. Comments are generally informational messages that may be of use to the client. They do not have a specific format, except that a comment message may follow the COMMENT: token. For example, a common message announcing the Monitor looks like this: COMMENT: Monitor Server Version 2.9.

COMMAND_ERROR: codes

COMMAND_ERROR: directives are sent by the Monitor in response to a failed command or connection. An error will result if a command does not succeed as expected. The connection remains alive and the client is expected to take some action to recover from the error. Most errors are designated with a COMMAND_ERROR: code to specify that they are a result of a failed command.

 
Client Commands
A client sends a command upon receiving the WAITING: directive from the server. A command consists of the command type followed by any arguments that might be necessary for the Monitor to execute the command successfully. Any command that a client sends without proper arguments will result in an error message directive giving a description of what arguments the command was supposed to be run with. Since the commands available to the participant are numerous, only a few key commands will be listed here. The rest will be listed in the command reference towards the end of this document. The commands that will be covered by this section are outlined here:

Command Description
IDENT participant_name [key-for-encryption] This command is used to send the sender's identity to the receiver. A player's identity is not a secret---like a username, it is the method by which others (including the Monitor) identify the player. The participant_name field is the identity of the username. The key-for-encryption field is optional. If it is sent, it should be the Player's portion that is needed to do shared-secret discovery. If successful, the message group returned by the monitor includes

RESULT: IDENT number

where number is the Monitor's half for shared secret discovery and only appears if the originating IDENT command used key-for-encryption.

In addition the returned message group contains

REQUIRE: ALIVE

if the IDENT originated from the passive server (the response is sent back to the passive server) or if the active client originated the IDENT and the passive server has been communicating with the Monitor before the IDENT command was given. Otherwise the following is included in the message group

REQUIRE: PASSWORD

Thus initial log ins always result in REQUIRE: PASSWORD.
PASSWORD password This command is used to transmit the player's password to the monitor. password is the player's password. The Monitor sometimes sends REQUIRE: PASSWORD after a successful IDENT command. The result is

RESULT: PASSWORD STRING

which is sent in the Message Group following the Command invocation. STRING is an alphanumeric string with no whitespace that is the player-specific monitor password (sometimes called a "cookie"). This password ("cookie") is different from the player's own password. This password ("cookie") should be used with the ALIVE command to identify the player to the Monitor.
ALIVE alive_cookie This Command is sent to indicate to the Monitor that the Player is alive. The alive-cookie should be the player-specific monitor password ("cookie") that was given to the Player by the Monitor as a RESULT: of the PASSWORD Command. If the alive-cookie is not the right password ("cookie"), a COMMAND_ERROR: will be returned and the player will not be counted as alive. Otherwise, the result is

RESULT: ALIVE Identity has been verified

HOST_PORT hostname tcp_port This Command is always sent by an active client process of a player to the Monitor. It is used by the sender to inform receiver (usually the Monitor) what hostname and port the sender currently lives on. The hostname should be the fully qualified DNS name of the host where the server process of the sender is running. The tcp_port should be the integer port number (between 2048 and 65000, inclusive) where the server Socket for the sender is running on. Note: This Command will only be successful if there is currently a server process for the sender running on the given hostname and port. The result is

RESULT: HOST_PORT hostname tcp_port

where hostname is the fully qualified DNS hostname that the Monitor was able to identify you as, and tcp_port is the port where you live.
MAKE_CERTIFICATE exp modulus Give the Monitor your public key for encryption so that it may register your key in its certicate authority. The arguments are the two components of your RSA public key. The result is

RESULT: CERTIFICATE number

where number is the Monitor-signed hash of exp concatenated with modulus.
QUIT Ends the current session. The Monitor's response includes the directive

RESULT: QUIT

Note that the response does not include the WAITING: directive.
PLAYER_STATUS This Command is used to check on the status of the sender's wealth. The result is

RESULT: PLAYER_STATUS STRING

which is sent in the Message Group following the Command invocation. The STRING is in the format:

RESOURCE_0 AMOUNT_0 RESOURCE_1 AMOUNT_1 ... RESOURCE_9 AMOUNT_9

where RESOURCE_I is the alphanumeric string of one of the 10 resources, and AMOUNT_I is the amount of that resource the sender currently has.
SIGN_OFF This command is used to tell the Monitor to "forget about the Player". The Monitor "forgets about the Player" in two ways. First, it forgets what host and port the Player's server is on. This means that the HOST_PORT will be REQUIRE: the next time the Player connects to the Monitor with an active client connection. In addition, the Monitor will "forget about the Player" by invalidating the current Player-specific Monitor password for the Player. This means that the Player will get a PASSWORD command REQUIRE: the next time that the Player connects to the Monitor with an active client connection. Note that if you execute this command, the Monitor will consider that you are not alive, until you again send the HOST_PORT command. The result is

RESULT: SIGN_OFF

in the Message Group following the Command invocation.
CHANGE_PASSWORD old_password new_password This command is used to request a change in the player password and the player-specific monitor password. The old_password is the player's old password (the one currently in use). The new_password is the new password that the player would like to use from this time forward. Note that the password is only changed if the command successfully returns a RESULT: Directive in the next Message Group. The result is

RESULT: CHANGE_PASSWORD STRING

which is sent in the Message Group following the Command invocation. The STRING is an alphanumeric string with no whitespace that is the player-specific monitor password (sometimes called a "cookie"). This new player-specific monitor password will be different from before. The CHANGE_PASSWORD command not only allows the player to change the player password, but also automatically changes the player-specific monitor password ("cookie"). Note that Players should be careful with this command. It is recommended that it be sent first in any set of transactions. Some Players have abused the fact that the Monitor gives 180 seconds for a connection, however, connections should never last that long. If the CHANGE_PASSWORD command is sent at the end of one of these "marathon" connections, Players may be cut off before they can receive the new Monitor password, and may be locked out of the game.
GET_CERTIFICATE player_identity Get the certificate containing the hash of the exponent and modulus of the public RSA key of the player with the named identity. If MONITOR is used for player_identity then the Monitor's hash is returned. The result is

RESULT: CERTIFICATE player_identity hash

where hash is the certificate.
SYNTHESIZE resource This command is used to synthesize a complex resource. The complex resources are WEAPONS, COMPUTERS, and VEHICLES. The name of the resource is given by resource. Be sure that the name of the resource matches the name given by the PLAYER_STATUS command. See the table in the "Synthesize" section for more information about what raw resources are needed to synthesize the complex resources. The result is

RESULT: SYNTHESIZE STRING

which is sent in the Message Group following the Command invocation. STRING is the amount of resource held increased by one. A COMMAND_ERROR is sent if the resource could not be synthesized for any reason.
TRADE_REQUEST   Player_1   to_resource   to_amount
  for   Player_2   from_resource   from_amount
This command is used by the initiator of a trade to ask the Monitor to confirm the trade, by making a request to the other player. The arguments are exactly the same as those to the TRADE: directive. Note that Player_2 may be MONITOR. In this case, the Player is requesting a trade with the Monitor itself. If the Monitor has the requested materials available, the Monitor approves trades that at current market values, plus a percentage mark-up. The result is

RESULT: TRADE_REQUEST ARG1

where ARG1 is either ACCEPTED, REJECTED, or NOT_ALIVE, all of which refer to the status of the Player with whom this trade was requested. If ARG1 is ACCEPTED, then the Player can expect its wealth to be changed to reflect the trade.
TRADE_RESPONSE ARG1 This command is used to either accept or reject a trade request. This command is most probably used in response to a Message Group that contained the TRADE: Directive (and probably a REQUIRE: TRADE_RESPONSE Directive as well). ARG1 is either ACCEPT or DECLINE. The result is

RESULT: TRADE_RESPONSE

Depending on whether the Player accepted or declined the trade (and, if a Monitor approval was given), the Player's wealth will be changed.
WAR_DECLARE   Player_1   hostname   port
   weapons   vehicles
This command is used by a player to declare war on Player_1. The host name and port where Player_1 is listening are given by hostname and port. The number of weapons and vehicles that Player_1 would like to commit to this war are given by weapons and vehicles. If the host and/or port for Player_1 are wrong, the player will automatically loose some percentage of the weapons and vehicles committed, and the war will not be started (in other words, the player must know where Player_1 "lives" before declaring war). Finally, note that the given weapons and vehicles will be tied up in that war until end of the war. A COMMAND_ERROR will be in the resulting Message Group if Player_1 cannot be found, or if the player has less weapons and/or vehicles than were specified. The result is

RESULT: WAR_DECLARE War begun with ARG1

WAR_DEFEND    weapons    vehicles This command is used to declare defending parameters for a war that was declared via a WAR_DECLARATION: directive. The number of weapons and vehicles the Player wishes to use in this war is given by weapons and vehicles. This command is most probably used in response to a Message Group that contained the WAR_DECLARATION: Directive (and probably a REQUIRE: WAR_DECLARATION Directive as well). The result is

RESULT: WAR_DEFEND

WAR_TRUCE_OFFER   Player_1   to   Player_2
   resource   amount   ...
This command is used by the initiator of a trade to ask the Monitor to confirm a truce, by making a request to the other player. The arguments to WAR_TRUCE_OFFER are exactly the same as those to the WAR_TRUCE_OFFERED: directive. The result is

RESULT: WAR_TRUCE_OFFER ARG1

where ARG1 is either ACCEPTED, REJECTED, NOT_ALIVE, or WAR_OVER. If ARG1 is ACCEPTED, then the Player can expect its wealth to be changed to reflect the truce terms. A COMMAND_ERROR occurs if a war is not active between the two parties, an invalid resource name is given, or if the player who has offered the truce does not have sufficient resources. Note that weapons and vehicles already tied up in the war cannot be used in a war trade agreement.
WAR_TRUCE_RESPONSE ARG1 This command is used to either accept or reject a truce request. This command is most probably used in response to a Message Group that contained the WAR_TRUCE_OFFERED: Directive (and probably a REQUIRE: WAR_TRUCE_RESPONSE Directive as well). ARG1 is either ACCEPT or DECLINE. The result is

RESULT: WAR_TRUCE_RESPONSE

Depending on whether the Player accepted or declined the trade (and, if a Monitor approval was given), the Player's wealth will be changed.
WAR_STATUS ARG1 This command is used find the status of current or recently fought wars. ARG1 is the identity of the player against whom the requestor wishes to see the war status. A COMMAND_ERROR is sent in the resulting Message Group if the requestor has never been at war with the requested player. The result is

RESULT: WAR_STATUS aggressor ARG2 defender ARG4 winner ARG6 battles ARG8 status ARG10 weapons ARG12 vehicles ARG14

where ARG2 is the identity of the aggressor in this war. ARG4 is the identity of the defender in this war. ARG6 will be the identity of the winner, TRUCE if a truce was found, or NONE if the war still continues. ARG8 will be an integer that represents the number of battles fought thus far in this war. ARG10 will be COMPLETED if the war is over, or ACTIVE if the war is still active. ARG12 is the number of weapons that the requestor has committed to this war. ARG14 is the number of vehicles that the requestor has committed to this war. Note: the number of vehicles and weapons committed to wars are not part of your PLAYER_STATUS total.
GET_GAME_IDENTS This command is used to get a list of identities of Players in the current game. This is useful, for example, if you want to know who can be traded with. The result is
RESULT: GET_GAME_IDENTS ARG1 ... ARGN
There will be N arguments in the response. Each argument will be the identity of another Player who is currently in the game.
RANDOM_PLAYER_HOST_PORT This command is used to ask the Monitor for a host port of some random identity. This is useful when a Player wishes to go to war with another Player, as in these cases, it is necessary to know the host and port of the Player to be fought. A COMMAND_ERROR occurs if you have already asked for a random Player host and port recently. The result is
RESULT: RANDOM_PLAYER_HOST_PORT ARG1 ARG2 ARG3
ARG1 will be the identity of the Player, ARG2 will be the most recent host on which that Player has been seen, and ARG3 will be the port on which that Player lives and/or the host and port where that player was most recently seen.
PLAYER_STATUS_CRACK ARG1 ARG2 This command is used to make an attempt to get the player status information of an enemy Player. ARG1 is the identity of the Player whose status to crack. ARG2 is the number of computer resources to spend on this attempt. The computer resources will be lost, regardless of whether or not the crack attempt succeeds. The more computer resources committed, the greater the chance of success. A COMMAND_ERROR occurs if the Player issuing the command does not have at least the amount of computer resources requested. A COMMAND_ERROR also occurs if the identity is not known. The result is
RESULT: PLAYER_STATUS_CRACK ARG1 ARG2 STRING
ARG1 will be the identity of the Player whose status was to be cracked. ARG2 will be either SUCCEEDED or FAILED. If ARG2 is SUCCEEDED, then STRING will equivalent to the result string for the PLAYER_STATUS command, however, the status will of course be for Player, ARG1.
PLAYER_MONITOR_PASSWORD_CRACK ARG1 ARG2 This command is used to make an attempt to crack the Monitor password of another player. ARG1 is the identity of the Player whose Monitor password to crack. ARG2 is the number of computer resources to spend on this attempt. The computer resources will be lost, regardless of whether or not the crack attempt succeeds. The more computer resources committed, the greater the chance of success. A COMMAND_ERROR occurs if the Player issuing the command does not have at least the amount of computer resources requested. A COMMAND_ERROR also occurs if the identity is not known. The result is
RESULT: PLAYER_MONITOR_PASSWORD_CRACK ARG1 ARG2 ARG3
ARG1 will be the identity of the Player whose Monitor password was to be cracked. ARG2 will be either SUCCEEDED or FAILED. If ARG2 is SUCCEEDED, then ARG3 will the Monitor password of ARG1. Otherwise, ARG3 will be the empty string.

 
Synthesis
Players are permitted to synthesize the complex resources. To perform the synthesis, Players must have in the their holdings 2 units of each of the resources needed to build the complex resource. The required raw resources to build complex resources are listed in the table below:

Complex Resource Raw Resources Needed
WEAPONS STEEL, PLASTIC, OIL
COMPUTERS COPPER, PLASTIC, GLASS
VEHICLES STEEL, RUBBER, GLASS, OIL

 
Logging In to the Monitor for the First Time
When you log into the Monitor for the first time your connection is not encrypted. You may already have a pre-selected participant_name and password (set by the Monitor Administrator), or you may be creating a new participant account if the Monitor provides such a facility (available in the practice contest). Either way, you should register yourself with the Monitor to maintain some good level of security for subsequent connections.

The IDENT command
    The IDENT command initiates login and is almost always the first command you will send to the monitor. No other commands are possible without first identifying yourself to the Monitor. When you first connect to the monitor you will receive a message group similar to the following.
      COMMENT: Monitor Server Version 2.9
      REQUIRE: IDENT
      WAITING:
Upon receiving this, your client should identify itself to the Monitor. The easiest way to accomplish this is to send the monitor your participant_name. For example:
      IDENT PLAYER

The PASSWORD command

    After receiving the IDENT command, the Monitor requests a password from your active client as follows:
      RESULT: IDENT PLAYER
      REQUIRE: PASSWORD
      WAITING:
If you are creating a new player, then this will set the stored password from this time forward. If you already have a registered password, then you will need to give that, or else the Monitor will give you the error message:
      COMMAND_ERROR: Invalid player password
Assuming the IDENT command was successful, the client responds to the WAITING: directive with a command such as the following:
      PASSWORD MYLITTLESECRET
The Monitor takes this password and then generates a special cookie, which gets returned to the client. The client must save this cookie (to disk maybe), as it will be needed later to authenticate to the Monitor again. This is known as the session-key. You will need to hold onto this key and keep it secret from others. The monitor will request this key from you in future communications.
 
The HOST_PORT command
The server will respond to the PASSWORD command with:
      RESULT: PASSWORD VKJHJ6FSK3JGM
      REQUIRE: HOST_PORT
      WAITING:
In this example, the cookie chosen by the Monitor is VKJHJ6FSK3JGM. It must be remembered! At this stage the participant's passive server must be started and listening on a port which it chooses randomly. Suppose the port chosen is 31337 and the server is started on rhodes.ececs.uc.edu. Then the client sends the following command to the Monitor:
      HOST_PORT RHODES.ECECS.UC.EDU 31337
The monitor may connect to this port from different source ports, and even (possibly) from different IP addresses. Upon connecting to the passive server, the Monitor exchanges two pieces of secret information. This allows a client to authenticate the Monitor, and the Monitor to authenticate the client. The Monitor takes the SHA-1 hash of the chosen password (not the session-key), first converted to upper case, and gives that as a base-16 number (converted to a String) to the passive server. The Monitor also requests from the passive server the session-key given previously by the result of the PASSWORD command. The checksum given by the Monitor is generated by taking the magnitude of the result of MessageDigest.digest() as the positive magnitude of an integer. The following shows the communication between the Monitor and the passive server:
      PLAYER_PASSWORD_CHECKSUM: 224726e0160bf4a844f445424f2c81e03cf739cb
      COMMENT: Monitor Server Version 2.9
      REQUIRE: IDENT
      WAITING:
      IDENT PLAYER
      RESULT: IDENT
      REQUIRE: ALIVE
      WAITING:
 
The ALIVE command
The passive server uses the checksum to authenticate the Monitor, then sends the session-key to the Monitor in an ALIVE command as follows:
      ALIVE VKJHJ6FSK3JGM
      RESULT: ALIVE Identity verified
      REQUIRE: QUIT
      WAITING
 
The QUIT command
The passive server responds with the QUIT command. This ends the passive session.
      QUIT
This is the end of verification. The Monitor then sends a message group to the active client telling it whether it succeeded in authenticating a passive server. This looks as follows:
      RESULT: HOST_PORT Command succeeded
      REQUIRE: COMMAND
      WAITING:

 
Getting a Certificate (using RMI)
Certificates are obtained using RMI. The Monitor starts a new RMI registry listening on port 1099, and provides the CertRegistry service. The CertRemote interface looks like this:

    public interface CertRemote extends Remote {
       PlayerCertificate getCert(String ident);
    }

The above is available from CertRemote.java. It should be compiled and the resulting class file should be accessible to a client's code. Also, you must be the stub file and put it in your classpath. The stub file is CertRemoteImpl_Stub.class.

The getCert(String) method should be called to grab the certificate of a player. For instance:

    CertRemote r =
       (CertRemote)(Naming.lookup("rmi://gauss.ececs.uc.edu/CertRegistry"));
    PlayerCertificate c = r.getCert("FRANCO");

The above stores FRANCO's certificate into object c.

If the invocation of getCert() returns null, it is because the certificate of the player given in the argument does not exist.

Observe that using the string MONITOR as an argument to getCert() returns the Monitor's certificate.

 
RSA Key Exchange Using IDENT
The client's first IDENT command, which intends to set up encryption, operates differently from all the others. The objective is to use the first IDENT and RESULT: exchange to build a secret which is used to encrypt subsequent messages. The following shows what happens on the initial IDENT and RESULT: exchange. It is assumed that the Monitor's certificate has been obtained according to the previous section and resides in PlayerCertificate montCert.

After the participant starts the active client to make the first connection, the following message group is received:

      COMMENT: Monitor Server Version 2.9
      REQUIRE: IDENT
      WAITING:

The client uses the following code to read the Monitor's certificate, make an RSA public-private key pair, and encrypt the modulus of the RSA public key with the public key of the Monitor:


      RSA myKey = new RSA(256);
      BigInteger m = myKey.publicKey().getModulus();
      String myHalf = monCert.getPublicKey().encrypt(m).toString(32);

The PlayerCertificate class is provided here. The RSA class is provided here. The result (myHalf) is sent to the Monitor as the last argument of an IDENT command as exemplified by the following:

      IDENT FRANCO 87jkg543gffd8673gdh
The Monitor responds with a message group such as the following:
      RESULT: IDENT g5jh673gfu2468673gdh
      WAITING:
which contains a 256 bit number that was generated by the Monitor and RSA encrypted using the modulus of the public key that was sent over in the previous command and the exponent of 65537 (official project exponent). Call the String representing the number that is parsed from the RESULT: directive, srv. The client decrypts srv and creates the shared secret using the following:
      String number = srv.split("\\s+")[2];
      BigInteger srvHalf = myKey.decryptNum(new BigInteger(number, 32));
      byte myHalf[] = myKey.publicKey().getModulus().toByteArray();
      byte monHalf[] = srvHalf.toByteArray();

Assembling the secret key for Karn encryption

The following code is used to construct the shared secret:

      int keySize = 512;
      ByteArrayOutputStream bos = new ByteArrayOutputStream(keySize/8);
		
      for (int i=0; i < keySize/16; i++) {
         bos.write(monHalf[i]);
         bos.write(myHalf[i]);
      }
      BigInteger sharedSecret = new BigInteger(1, bos.toByteArray());
The monHalf and myHalf arrays must be used in the order shown or else the resulting secret will not match that of the Monitor. Once the shared secret is established, encrypted communication can proceed using the following:
      KarnBufferedReader karnIn = new KarnBufferedReader(in, sharedSecret);
      KarnPrintWriter karnOut = new KarnPrintWriter(out, true, sharedSecret);
where in and out represent the streams used in the connection to the Monitor. The KarnBufferedReader class can be obtained here and the KarnPrintWriter class can be obtained here. Now one can do karnIn.readLine() to decrypt incoming messages, line-by-line, and karnOut.println(..) to encrypt.
 
Registering a Certificate
The MAKE_CERTIFICATE command is used to register a public encryption key for use in RSA encryption facilities with the Monitor. The MAKE_CERTIFICATE command takes two arguments: the public encryption key exponenet (commonly called e) followed by the public key modulus (commonly called n). The monitor does not perform any sort of checks to verify that the numbers are cryptographically strong. Such is the responsibility of the key generation method used. Each number is expected to be in base-32 numeric format (BigInteger.toString(32)), and should be a positive number. The Monitor responds with a new number which is the monitor-signed hash of the supplied key. This number is used to authenticate the Monitor. Here is an example.

The client uses the following code to build an RSA private key:

      RSA myPrivateKey = new RSA(); /* Default is 512-bit key size */

      ObjectOutputStream oos = 
         new ObjectOutputStream(new FileOutputStream("ParticipantKey"));
      oos.writeObject(myPrivateKey);
      oos.close();
Now the MAKE_CERTIFICATE command is invoked (note: replace karnOut below with out or something appropriate if you have not started to encrypt yet):
      karnOut.println("MAKE_CERTIFICATE " +
                      myPrivateKey.publicKey().getExponent().toString(32) +
                      " " + myPrivateKey.publicKey().getModulus().toString(32));
The response of the Monitor should be something like this:
      RESULT: CERTIFICATE 02m21jhbb23jjm23jj23bbh32h
      WAITING:
This is only an example - the values above are not actually generated values.

The Monitor handles the MAKE_CERTIFICATE command using the following code:

      MessageDigest mdsha = MessageDigest.getInstance("SHA-1");
      mdsha.update(myPublicKey.getExponent().toByteArray());
      mdsha.update(myPublicKey.getModulus().toByteArray());

      BigInteger m = new BigInteger(1, mdsha.digest());
      String certNumber = monitorPrivateKey.signNum(m).toString(32);
where monitorPrivateKey is of type RSA and myPublicKey, of type PubRSA, is what was sent over previously from the client. This has the effect of creating a value which facilitates verification that the Monitor has registered the certificate, provided one has the Monitor's public key. A second client can use the encrypt function of the Monitor's public key to compare the hash with what has been received from a first client. As long as the second client can trust the Monitor's public key, the identity is considered authenticated.

Assuming encryption is enabled, the client checks the hash with the following:

      String s[] = karnIn.readLine().split("\\s+");
      MessageDigest mdsha = MessageDigest.getInstance("SHA-1");
      mdsha.update(myPublicKey.getExponent().toByteArray());
      mdsha.update(myPublicKey.getModulus().toByteArray());

      BigInteger m = new BigInteger(1, mdsha.digest());
      BigInteger p = new BigInteger(s[2], 32);
      BigInteger certNumber = monitorPublicKey.encrypt(p);
      if (m.compareTo(certNumber) == 0) { "got it!" } else { "don't got it" }
 
Authenticated Connection Encryption
In order to authenticate the client end of a connection, the Monitor must have some information to prove that the client is who it says it is. This is provided by the challenge which operates as follows:
  1. Assume the Monitor has a client's RSA encryption key which was obtained by the MAKE_CERTIFICATE command described above.
  2. No eavesdropper will be able to properly decrypt text encrypted with this key unless the client had its private RSA decryption key compromised.
  3. The Monitor encrypts its key half using the client's encryption key and sends it to the client.
  4. Only the client will be able to properly decrypt this value and assemble the shared key for the Karn block cipher.
  5. If the client builds the key, and manages to maintain (now encrypted) communication with the monitor, it is considered authenticated.
  6. All eavedroppers attempting this will not be able to hijack this connection.

The specific sequence of actions is as follows. From the Monitor comes:

      COMMENT: Monitor Server Version 2.9
      REQUIRE: IDENT
      WAITING:
The client generates a random 256-bit value to be encrypted by the Monitor's public RSA key using the following code:
      SecureRandom sr = new SecureRandom();
      BigInteger participantHalf = new BigInteger(256, sr);

      out.println("IDENT " + playerName + " " +
         monCert.getPublicKey().encrypt(participantHalf).toString(32));
where monCert and karnOut are as above. The Monitor responds with the same directive but different meaning.
      RESULT: IDENT dsafsdf7daf6d7fsda5dsa5fds4fsd5f4sd
Assuming encryption is enabled, the client breaks this up:
      String s[] = karnIn.readLine().split("\\s+");
where karnIn is as above. Next, the client creates the Monitor key half using the previously generated (and stored) private RSA key which the client created.
      BigInteger monitorHalf = new BigInteger(myPrivateKey.decrypt(s[2]), 32);
      byte myHalf[] = participantHalf.toByteArray();
      byte monHalf[] = monitorHalf.toByteArray();
From this point on, the halves get reassembled and communication proceeds exactly as it does in the Unauthenticated connection.

It is important to know that after a participant registers a new key with the Monitor, via MAKE_CERTIFICATE, there are no longer any Unauthenticated Encrypted connections allowed. The presence of a player certificate tells the monitor to use that certificate's public key to encrypt the value sent back to the client. This corresponds to challenge steps #3 and #4 above.

By this point you should have a completely operational client that is up and running and receiving encrypted connections from the monitor. This typically puts the connection into command mode.

 
The Command Mode
Once authentication and login have completed, the active client is in Command Mode. At this stage, the participant is at the root of the command interface and has the freedom to commit any sort of actions that the Monitor accepts. There are numerous commands available to the participant, and they are covered later on. This section will focus on a few commands that are useful to the neophyte.

The HELP command
    Very important to the novice participant is the HELP command. This command provides a list of all of the commands that can be accepted by the Monitor.