A DISTRIBUTED, FAULT TOLERANT, AND SECURE POINT OF …



A DISTRIBUTED, SECURE, AND FAULT TOLERANT POINT OF SALE SYSTEM

Jimmie Yann-Sheng Wang

B.A., University of California, Davis, 1997

PROJECT

Submitted in partial satisfaction of

the requirements for the degree of

MASTER OF SCIENCE

in

COMPUTER SCIENCE

at

CALIFORNIA STATE UNIVERSITY, SACRAMENTO

FALL

2004

A DISTRIBUTED, SECURE, AND FAULT TOLERANT POINT OF SALE SYSTEM

A Project

By

Jimmie Yann-Sheng Wang

Approved by:

______________________________, Committee Chair

Dr. Isaac Ghansah

Date: __________________________

______________________________, Second Reader

Prof. Dick Smith

Date: __________________________

Student: Jimmie Yann-Sheng Wang

I certify that this student has met the requirements for format contained in the University format manual, and that this Project is suitable for shelving in the Library and credit is to be award for the Project.

________________________________________________ __________________

Dr. Cui Zhang, Graduate Coordinator Date

Department of Computer Science

Abstract

of

A DISTRIBUTED, SECURE, AND FAULT TOLERANT POINT OF SALE SYSTEM

By

Jimmie Yann-Sheng Wang

The small business Point of Sale software packages available on the market today are mainly stand alone or simple client-server based systems. While these packages are feature rich in sales transaction functions, stand alone or simple client-server based systems are, by nature, prone to single point of system failure. Additionally, most systems are not easily scalable, and they generally do not offer data security features. In other words, these systems are susceptible to failure, can’t cannot grow easily with the business they are charged with, and do not protect sensitive financial data.

A more robust system is required for the small business. The small business Point of Sale software package, in addition to its core functionalities, should better protect its data by offering fault tolerance with resource redundancy, scalability through a distributed architecture and a capacity to add system resources, and data security by way of cryptography.

This project implements a functional and robust Point of Sale system. The software developed in this project will be the basis for a full implementation of a complete Point of Sale system package.

____________________________________, Committee Chair

Dr. Isaac Ghansah

____________________________________

Date

ACKNOWLEDGEMENTS

My most sincere appreciation to Dr. Issac Ghansah, my project advisor, for all the knowledge and guidance he has lend to me through his classes and this project.

Thanks to Professor Dick Smith for giving his time as second reader.

I also thank the friends, faculty, and staff I have worked with in the many Computer Science classes I have taken here at Sac State. I have been fortunate enough to interact with and learn from many talented and knowledgeable individuals.

TABLE OF CONTENTS

ACKNOWLEDGEMENTS v

LIST OF TABLES viii

LIST OF FIGURES ix

1. Scope 1

1.1 Background 1

1.2 Identification 3

1.3 System Overview 3

1.4 Document Overview 4

2. Preliminary Design 5

2.1 Requirements 5

2.2 System Description 6

2.3 Data Flow/Control Diagram 8

2.4 Internal Messages 9

2.5 Internal Data 9

2.7 Design Constraints 9

3. Detailed Design 10

3.1 Message Processing 10

3.1.1 Encryption Thread 10

3.2.2 Communications Thread 12

3.2 Design Description 14

3.2.1 Name Server 15

3.2.2 Database Server 16

3.2.3 Front End Server 17

3.2.4 Client 17

3.3 Functional Capability 18

3.3.1 Distributed System 18

3.3.2 Security 19

3.3.3 Graphical User Interface (GUI) 20

3.3.4 Database 21

4. Testing 22

4.1 Test Plan 22

4.2 Test Case 24

5. Operations 27

6. Conclusions 29

6.1 Summary 29

6.2 Future Implementation and Upgrades 29

Appendix 31

Appendix A: Source Code 32

BIBLIOGRAPHY 106

LIST OF TABLES

Table 1: Requirements 6

Table 2: Internal Messages 9

Table 3: Internal Data 9

Table 4: Test Cases 23

Table 5: Requirements/Test Cases Map 24

Table 6: Test Case Test Procedures 26

LIST OF FIGURES

Figure 1: Data Flow/Control Diagram 8

Figure 2: Public Key/Secret Key Encryption Thread Diagram 11

Figure 3: Communication Thread Diagram 13

1. Scope

1 Background

There is no shortage of Point of Sale (POS) software packages for the small retail business. Competitors in the market range from Microsoft to Intuit to many fledgling enterprises. Not surprisingly, with so many competitors in the field, most small business POS software packages from reputable companies are very good products. Many small retail businesses use and depend on these POS systems with good success.

As a former small retail business owner, I understand the value of a good POS system. The retail sales side of my business was completely leveraged and dependant on my POS software for sales transactions and inventory control. The accounting side of the business depended on the data that the POS software provided. Suffice it to say, the day to day operation of my company was integrally dependant on the POS system, much like any other retail business.

The problem with small business POS systems does not relate to the execution of the product. Most packages from well known vendors perform their core functions very well, that is performing sales transactions and controling inventory. Many small businesses have deployed POS systems with good success. My biggest concerns, like other small companies that does not employ a technology staff, were the reliability of the system, and how well my POS system would grow with my company.

Most small business POS software packages, such as Intuit’s very popular Quickbook POS, are stand alone or simple client-server based packages that are geared towards the smallest retailers. These systems, while efficient, tend to be vulnerable to single point of failures. The potential for a system side shutdown is very real, and it is something most small businesses can’t afford. Moreover, stand alone and simple client-server packages tend not to scale very well (evident by the move towards distributed architectures), so a growing business is usually faced with the daunting task of moving to a new system for larger businesses. Lastly, most POS systems lack data security measures. It is my contention that small businesses need a better POS software product. POS systems is the entry point for financial transactions and the keeper of financial data for retailers. These systems need to be fault tolerant, scalable, and secure in transactions. For this project, I present a product that I believe is the basis for a better small business POS software, titled, A Distributed, Secure, and Fault Tolerant Point of Sale System (ADSFPOSS).

ADSFPOSS seeks to address reliability, scalability, and security issues that small business POS software generally does not. ADSFPOSS offer system reliability and fault tolerance by utilizing redundant servers that are allowed to fail without impacting the system. The system is also scalable due to its distributed architecture, allowing for processing anywhere on a network. Lastly, data security is provided through two layers of cryptography.

In this paper, I will discuss the preliminary and detailed design of the system, present the code written for each component module, create a test plan for insuring the system meets its requirements, and offer an operations guide.

2 Identification

This document captures the Preliminary Design, Detailed Design, Testing, and Operations phases of the ADSFPOSS software development process. The complete code listing is presented in the Appendix. ADSFPOSS is composed of four separate, though integrally dependent, components:

A. Client

B. Name Server

C. Front End Server

D. Database Server

3 System Overview

ADSFPOSS is a software package that, on the most basic level, implements rudimentary functions of a Point of Sale system. However, it is also designed as an enterprise level sales system that is easy to use, robust, secure, and scalable. The package supports such features as:

• An intuitive GUI based client program

• A Name Server that provides resource management services to all servers and load balancing services to the Database Servers

• Two Front End Servers that provide transparent data transport services to the client

• Multiple Database Servers that provide robust and redundant data storage services

• Two layers of encryption (Diffie-Hellman [1] and Blowfish [2]) for secure data communications

• Network enabled servers that are capable of running on any combinations of one or more computers for scalability and reliability

4 Document Overview

This document describes the development process of the ADSFPOSS. Section 1 is the Scope, which contains a high level description of the features and the architecture of the system. Section 2 is the Preliminary Design, which contains the requirements of the system and a description of the individual components of the system. Section 3 is the Detailed Design, which contains rules of interaction within the system. Section 4 is the Testing, which contains the Test Plan and Test Cases developed to ensure all system requirements and capabilities have been met and achieved. Section 5 is the Operations, which outlines the deployment process for the system. Section 6 concludes the documentation of the the project with a summary and discussion of the future of software.

Preliminary Design

2.1 Requirements

The ADSFPOSS system requirements are identified and listed in Table 1. These requirements, along with the Test Plan and Test Cases described in Section 4, ensure that all the capability requirements of the system will be met.

|Identification |Requirement Title and Description |

|EXEC.10010 |Software Execution |

| |The Name Server, Front End Servers, Database Server(s), and Client(s) are standalone Java program that |

| |shall be capable of being executed from the command line on any platform containing Java 2 Runtime |

| |Environment. |

|EXEC.10020 |Startup Sequence |

| |The startup sequence shall be performed exactly as follows: Name Server, Front End Servers, Database |

| |Server(s), and Client(s). |

|EXEC.10030 |Name Service |

| |All software servers, other than the Name Server, shall register with the Name Server upon startup. |

|EXEC.10040 |Software Termination |

| |The Name Server, Front End Servers, Database Server(s), and Client(s) programs shall terminate given a |

| |sequence of stop execution command (i.e. CTRL-C from the command line on a Microsoft Windows 2000 Operating|

| |System running on a x86 processor). |

|ENCR.20010 |Diffie-Hellman Public Key Encryption |

| |Client and Database Servers shall obtain a secret key from the Name Server upon startup, secured by |

| |Diffie-Hellman encryption. |

|ENCR.20020 |Blowfish Secret Key Encryption |

| |All data exchanged amongst software components shall be secured by Blowfish encryption. |

|DATA.30010 |Database Servers |

| |The system shall be capable of utilizing multiple/redundant Database Servers for reliability. |

|DATA.30020 |Database |

| |The database servers shall read from and write update to a central database. |

|DATA.30030 |Database Servers Fault Tolerance |

| |The Database Servers shall be capable of startup and termination at any point during the execution of the |

| |system. |

|FRNT.40010 |Front End Servers |

| |The system shall utilize two Front End Servers. |

|FRNT.40020 |Front End Servers Fault Tolerance |

| |The Front End Servers shall be capable of startup and termination at any point during the execution of the |

| |system. |

|CLNT.50010 |Client |

| |The system shall be capable of handling multiple Client connections. |

|CLNT.50020 |Graphical User Interface |

| |The Client software shall be presented to the user as a graphical user interface (GUI). |

|NAME.60010 |Name Server |

| |The system shall utilize a Name Server. |

|COMM.70010 |Data Communication |

| |All data communications between software components shall utilize Java Remote Method Invocation (RMI). |

|DIST.80010 |Distributed System |

| |With a given configuration, each software component shall be capable of executing on different platforms on|

| |a TCP/IP network. |

Table 1: Requirements

2.2 System Description

The ADSFPOSS system consists of four software modules. Together, they form a distributed, fault tolerant, and secure system.

A. Name Server: The Name Server provides resource allocation and name resolution for the system. As each software server begins execution, they must register their location with the Name Server. The Name Server will in turn, assigns resources when a software module makes such a request. For example, when the Front End Server queries the Name Server for an available Database Server, the Name Server will return the location of the next available Database Server in a load balancing, round robin fashion. The Name Server also maintains the secret key used by the software modules for encryption and decryption. Each software module may securely communicate with the Name Server via a public key (Diffie-Hellman) exchange to obtain the secret key.

B. Database Server: As the name suggests, the Database Server maintains the system database. When new invoice data arrives, the Database Server updates the database with the newly available data. Likewise, the server will also return database data when requested. The system requires at least one active Database Server to be functional. Multiple Database Servers form the basis for a redundant and fault tolerant database system.

C. Front End Server: The Front End Server is an intermediary between the Client and the Database Servers. Two Front End Servers act to provide location transparency and data transfer service. When a Client needs to access the Database Server, it simply makes a request or makes a data transfer to one of the Front End Servers. The Front End Server locates an available Database Server via the Name Server and makes appropriate data transactions.

D. Client: The Client provides an intuitive GUI to the user for basic Point of Sale services. The GUI provides an invoice form for the user to enter and submit invoice sales data. There is also a report form where the user can access the latest summary sales reports. Multiple copies of the Client software may be run anywhere there is network connection to the rest of the system.

2.3 Data Flow/Control Diagram

Figure 1 is a high level architecture diagram that illustrates the data flow of the ADSFPOSS.

[pic]

Figure 1: Data Flow/Control Diagram

2.4 Internal Messages

Table 2 summarizes the ADSFPOSS internal messages.

|Message |Description |

|Invoice Submission |This message contains the data found in the Client invoice form to be submitted to the Database |

| |Servers. |

|Report Request |This message contains a summary of the data contained in the system database. The summary data |

| |is gathered by the Database Server and returned to the Client software. |

|Name Registration |This message contains the name and location of the server as it registers with the Name Server as|

| |part of its required startup routine. |

|Name Resolution |This message contains the name and location of a server that is requested by a software module. |

Table 2: Internal Messages

2.5 Internal Data

Table 3 summarizes the ADSFPOSS internal data.

|Data |Description |

|Database |This file contains all the invoice data submitted by the Clients and maintained by the Database |

| |Servers. |

Table 3: Internal Data

2.7 Design Constraints

The ADSFPOSS system will be developed on the Java [3] platform and use Java RMI [4] as its communication mechanism.

Detailed Design

3.1 Message Processing

The message processing threads that the ADSFPOSS software employs are described below.

3.1.1 Encryption Thread

At startup, the Client and Database Servers are required to obtain an Encryption Key from the Name Server for subsequent, secure data communications. The process of obtaining the Encryption Key is secure. The Client and Database Servers receive the Encryption Key from Name Server using a Public Key Algorithm called Diffie-Hellman. Diffie-Hellman allows two parties, who may never have been in contact before, to communicate securely over an unsecured network. Figure 2 illustrates the ADSFPOSS Diffie-Hellman implementation.

[pic]

Figure 2: Public Key/Secret Key Encryption Thread Diagram

The Client generates a Public Key and sends it to the Name Server. In return, the Name Server returns its Public Key to the Client. Once the Public Keys have been exchanged, both the Client and Server can separately generate a mutual Secret Key that can be used to encrypt and decrypt data. The Client requests the Encryption Key from the Name Server. The Name Server encrypts the Encryption Key using the mutual Secret Key and returns the Encryption Key to the Client. The Database Servers obtains the Encryption Key from the Name Server using the same process.

The Client uses the Encryption Key with the Blowfish algorithm to encrypt all data communications with the servers. Blowfish is a Secret Key Encryption algorithm used to transmit secure data between two parties that share a Secret Key. On the receiving end, the Database Servers uses Blowfish and the Encryption Key to decrypt data communications.

3.2.2 Communications Thread

ADSFPOSS presents basic Point of Sale functions to the user as part of its Client GUI. The Client Invoice form allows the user to enter invoice sales data and to submit the data to the Database Servers. The Client Report form allows the user to obtain a summarized sales data report from the Database Servers. Figure 3 illustrates the ADSFPOSS implementations for the sales functions.

[pic]

Figure 3: Communication Thread Diagram

The Submit Invoice thread extracts invoice data from the Client Invoice form and sends the data to the Front End Server. The Front End Server receives the data and requests for the next available Database Server from the Name Server. The data is send from the Client through the Front End Server to the Database Server in an encrypted format. The Database server decrypts and saves the data.

The Get Report thread displays a summarized sales report in the Client GUI. The Client makes a request for the summarized report through the Front End Server to the Database Server in the same fashion as the Submit Invoice thread. The Database Server reads its entire database and summarized all the sales data and returns it to the Client. Once received, the Client displays the summary sales data in the Report form. The data is sent from the Database Server through the Front End Server to the Client in an encrypted format. The Client displays the decrypted data.

3.2 Design Description

The ADSFPOSS software has a startup sequence that is essential to the functionality of the system. The Name Server must be the first software module to startup, followed by either the Database Servers or the Front End Servers. The Client software module may execute when there is one instance of the Name Server, one or two instances of the Front End Server, and at least one instance of the Database Server running. Multiple copies of the Database Server may execute concurrently.

Upon startup, the Database Server must contact the Name Server to register its location and obtain an Encryption Key. The Client also obtains the Encryption Key when it begins execution. Each software module receives the Encryption Key securely through a Diffie-Hellman Public Key exchange. The Client and Database Servers utilize the Encryption Key and the Blowfish cipher to secure message data exchange.

The ADSFPOSS system performs the majority of its message data processing in response to the user’s actions through the Client GUI. When the user submits an invoice, the Client encrypts and forwards the invoice data to one of the Front End Servers. The Front End Server obtains the location of a Database Server from the Name Server, and forwards the invoice data to that Database Server. The Database Server decrypts and saves the data. The sequence of events for extracting a Summary Report is similar. The Client forwards a request to the Database server for a Report through the Front End Server. The Database Server creates a Report, encrypts it and returns it to the Client. The Client decrypts the Report and displays it to the user.

The entire system consists of four different software modules. A description of the processing performed by each module is presented below.

3.2.1 Name Server

The Name Server is the resource manager for the system. Consequently, the software exists at a location well known to the rest of the system to provide services.

The Name Server maintains a list of active Database Servers; all Database Servers are required to register with the Name Server upon startup. When a Front End Server makes a request to the Name Server for the an active Database Server, the Name Server rotates through the list of Database Servers in a round robin fashion, checks to make sure the Database Server is active, and returns the location of the Database Server to the Front End Server. In short, the Name Server provides location transparency to the system, as the Front End Servers are not required to maintain a list of working Database Servers, and load balancing of the Database Servers for scalability.

Additionally, the Name Server maintains the Encryption Key used by the system for secure data communications. Client and Database Servers use this Key in conjunction with the Blowfish Secret Key algorithm to encrypt data transmissions. The Encryption Key is obtained from the Name Server through a Diffie-Hellman Public Key exchange to ensure the Encryption Key is not compromised. Diffie-Hellman allows for secure communications over a non-secure network involving peers that may not trust each other. Client and Database Server modules are required to obtain the Encryption Key, which is used later to encrypt communication data, from the Name Server.

3.2.2 Database Server

As the name suggests, Database Servers maintain a store of sales information. Sales data is received from the Client and inserted into the existing database. The Database Server also prepares sales summary reports when requested by the Client.

Upon startup, the Database Server registers its location with the Name Server to announce its availability. The Database Server also obtains an Encryption Key through a Diffie-Hellman exchange with the Name Server. Diffie-Hellman allows for secure communications over a non-secure network between peers that may not trust each other. The Encryption Key is used with the Blowfish cipher to decrypt sales data it receives from the Client, and to encrypt the sales summary report to be sent to the Client. All data transmission in the system is encrypted with the Blowfish Secret Key algorithm.

Multiple copies of the Database Server may be started at various locations on a network. This redundancy of Database Servers promotes fault tolerance and scalability in the system. The system is fault tolerant, because single or multiple Database Server failures will not cripple the system, so long as at least one Database Server remains active. The system is scalable, because Database Servers work in a load balanced manner, and additional Database Servers may be added to the system to increase the work handling capacity of the system. The distributed nature of the Database Servers allows the entire system work in a safe and scalable manner. The Database Servers may be brought online or shutdown without affecting the system, as long as at least one Database Server is active at all times.

3.2.3 Front End Server

The two Front End Server provides data transfer services for the Client and Database Servers. All data transmission between the two modules travels through the Front End Servers. The main function of the Front End Server is to provide location transparency of the Database Servers to the Client, since the Clients must only know the location of the two Front End Servers. Two Front End Servers also provide for limited fault tolerance, as the failure of one does not affect the system. The Front End Servers may be brought online or shutdown without affecting the system, as long as one Front End Server is active at all times.

3.2.4 Client

The Client is the interface between the user and the rest of the ADSFPOSS system. The user is presented with a graphical user interface (GUI) program that allows her to enter invoice data or retrieve a sales summary report.

Upon startup, the Client obtains an Encryption Key through a Diffie-Hellman exchange with the Name Server. Diffie-Hellman allows for secure communications over a non-secure network between peers that may not trust each other. The Encryption Key is used with the Blowfish cipher to encrypt invoice sales data the Client sends to the central database, and to decrypt the summary sales report that it receives. All data transmission in the system is encrypted with the Blowfish Secret Key algorithm.

The primary form of the Client is a sales invoicing interface. The user may enter sales data such as customer information and sales data. When the data entry is complete, the user may submit the sales form to the central database. The secondary form of the Client is a summary sales reporting interface. There, the user may retrieve a summary sales report of the central database.

Multiple instances of the Client program may be instantiated or shutdown without affecting the system.

3.3 Functional Capability

3.3.1 Distributed System

Just as the name suggests, a major component of the ADSFPOSS system is its distributed nature. A distributed system allows complex issues to be solved over many resources instead of a single one. This allows a distributed system to be scalable and fault tolerant.

ADSFPOSS has four main components (Name Server, Database Server, Front End Server, and Client) that exist separately and independently. Each component can live on separate computers that are part of a connected network. Multiple copies of the Database Servers can individually execute on different computers. Likewise, the two Front End Servers can run on two different computers. The Client, by nature, runs on a computer per process.

The Database Servers are capable of running on different computers by design. Multiple Database Servers promote fault tolerance, as the failure of one server does not affect the overall operation of the ADSFPOSS system. Additionally, Database Servers can be added as workload increases. The Name Server allocates Database Server resources on a load balanced, round robin fashion, so the system is scalable to meet heightened demands. Two Front End Servers also promote the reliability and fault tolerance of the system.

The technology that makes the distributed nature of ADSFPOSS possible is Java Remote Method Invocation (RMI). RMI allows a software program to invoke functionalities provided by other applications that may exist on a different computer as if the remote application was part of the native software program. Additionally, RMI provides capabilities to facilitate name server functionalities and data transfers. In summary, RMI is a high-level application program interface (API) that allows development of distributed application that is fault tolerant and scalable.

3.3.2 Security

ADSFPOSS implements two levels of security at the application level. As part of the startup routine for the Client and Database Servers, the applications communicate with the Name Server over a Diffie-Hellman public key encryption scheme to obtain an Encryption Key. Once the Encryption Key is obtained, the Client and Database Servers communicate with each other over a Blowfish secret key encryption scheme.

Diffie-Hellman is an asymmetric, public key encryption scheme that allows two parties that may not trust each other to communicate securely over a non-trusted network. Diffie-Hellman requires each party to publish a public key. With its counterpart’s public key, each party is able to derive a common secret key. The common secret key is used to encrypt and decrypt communications between the pair.

Blowfish is a symmetric, secret key encryption scheme that requires two parties to share a common secret key. With the secret key, the two parties encrypt and decrypt communications with the Blowfish cipher to ensure secure communications.

3.3.3 Graphical User Interface (GUI)

A user will interface with the ADSFPOSS system via the Client GUI. The Client GUI presents the user with an Invoice form where the user can enter all sales data. A second form on the Client GUI is the Report form where the user can retrieve a summary report of all sales.

The Client GUI will be developed using Java Swing [5]. The two main advantage of using Java Swing are the platform independence that Java offers and the ability to take advantage of the Java RMI framework. Platform independence allows the Client GUI program to be run any platform that supports Java, which is virtually any computer system of any consequence. Java RMI is described in section 3.3.1.

3.3.4 Database

The Database Servers maintain a store of sales records in a flat text file. The advantage of a flat text file is that it’s human readable and editable, and the data is easily extracted. However, search in a text file is linear and takes O(n) time. A future enhancement to the system is the conversion of the text database to a binary file, or more appropriately, a SQL Database Management System.

4. Testing

4.1 Test Plan

The purpose of this test plan is to ensure that ADSFPOSS is individually tested and demonstrated to be operating properly and consistent with design documentation.

ADSFPOSS will be tested in two stages. The first stage involves testing of individual modules for algorithm consistency and proper operations. The second stage involves testing the integration of all modules by evaluating responses to various requests sent to each component.

The ADSFPOSS unit testing will:

1. Verify all requirements and functional capabilities allocated to the task.

2. Verify all computations using both nominal and extreme values.

3. Verify all input and output options, formats, error and information messages.

4. Test all options at each branch point of each module.

5. Ensure that each module fully satisfies (wholly or its assigned portion) the performance and design requirements.

6. Ensure the capability to properly handle erroneous inputs. (Unusual input data points and points or ranges of potential failure should be verified, overflow and boundary conditions exercised, etc.).

7. Verification of all internal/external interface requirements.

The test cases for the ADSFPOSS unit test are identified in Table 4.

|Test Case ID |Description |

|TC.01 |Software Initialization |

| |This test case will verify that each component of the ADSFPOSS system shall execute on startup from a |

| |command prompt on a computer platform containing the Java 2 Runtime Environment. The startup sequence of |

| |the components shall be performed exactly as follows: Name Server, Front End Servers and Database Server(s),|

| |and Client(s). |

|TC.02 |Software Termination |

| |This test case will verify that each component of the ADSFPOSS system shall terminate at the user’s command.|

|TC.03 |Name Service |

| |All software servers, other than the Name Server, shall register with the Name Server upon startup. |

|TC.04 |Encryption |

| |All data exchanged amongst software components shall be secured by encryption. |

|TC.05 |Database Servers |

| |The Database Servers shall be capable of being redundant and fault tolerant and maintain a central database.|

|TC.06 |Front End Servers |

| |The Front End Servers shall be redundant (two Front End Servers) and fault tolerant. |

|TC.07 |Client |

| |The Client shall be presented in a graphical user interface format and the system shall be capable of |

| |handling multiple Client connections. |

|TC.08 |Data Communications |

| |All data communications between software components shall utilize Java Remote Method Invocation (RMI). |

|TC.09 |Distributed System |

| |Each software component shall be capable of executing on different platforms on a TCP/IP network. |

Table 4: Test Cases

The mapping of requirements and test cases is shown on Table 5.

|Requirement ID |TEST Case ID |

| |TC.01 |TC.02 |

|TC.01 |This test will pass if all the software modules in |On a computer platform containing the Java 2 Runtime |

| |the ADSFPOSS system execute on startup. |Environment, execute each software module in the |

| | |following sequence: Name Server, two Front End Server, |

| | |one or more multiple instances of the Database Server, |

| | |and one or more instances of the Client. |

|TC.02 |This test will pass if all the software modules in |When all the software modules in the ADSFPOSS system have|

| |the ADSFPOSS system terminate at the user’s command. |begin execution as described Test Case TC.01, terminate |

| | |all server programs with the CTRL-X keystroke sequence |

| | |and terminate the Client GUI by choosing the FILE/QUIT |

| | |sequence from the menu bar. |

|TC.03 |This test will pass if all server modules, other than|Execute the Name Server module. When other server |

| |the Name Server, in the ADSFPOSS system register with|modules execute, the Name Server will acknowledge |

| |the Name Server upon startup. |registration of each server through standard out |

| | |messages. |

|TC.04 |This test will pass if all server modules exchange |During message exchange sequences, view and verify that |

| |data securely through encryption. |message passed between modules maintain data integrity. |

|TC.05 |This test will pass if multiple instances of the |When all the software modules in the ADSFPOSS system have|

| |Database Server may be executed, terminated and |begin execution as described Test Case TC.01, Database |

| |re-instantiated without affecting the rest of the |Servers may be instantiated and terminated at will. All |

| |ADSFPOSS system. All the Database Servers must |database updates will be reflected in the same database |

| |update and maintain the same database file. |file. |

|TC.06 |This test will pass if the two Front End Servers |When all the software modules in the ADSFPOSS system have|

| |maybe be executed or terminated at will without |begin execution as described Test Case TC.01, the two |

| |affecting the rest of the ADSFPOSS system. One |Front End Servers may be instantiated and terminated at |

| |instance of the Front End Server must be executing at|will. However, one Front End Server must be executing at|

| |all times, however. |all times. |

|TC.07 |This test will pass if one or more instances of the |When all the software modules in the ADSFPOSS system have|

| |Client module may be executed. |begin execution as described Test Case TC.01, one or more|

| | |instances of the Client module may be instantiated or |

| | |terminated at will. |

|TC.08 |This test will pass if all data communications |Inspect ADSFPOSS source code visually. |

| |between software modules utilize Java RMI. | |

|TC.09 |This test will pass if all the software components in|When all the software modules in the ADSFPOSS system have|

| |the ADSFPOSS system may execute on different |begin execution as described Test Case TC.01, each |

| |platforms on a TCP/IP network. |software module may execute on a different computer |

| | |platform on a TCP/IP network. The Name Server must |

| | |execute on a designated platform. |

Table 6: Test Case Test Procedures

Operations

The ADSFPOSS system comprises three server components (Name Server, Front End Server, and Database Server) and one client module. Together, the four pieces form the distributed, fault tolerant, and secure architecture of the system. The components of the system are integrally dependant on one and another, and the startup sequence is essential for the proper operation of the system. The execution sequence is as follows.

1. Name Server

2. Two Front End Servers

3. One or more instances of the Database Server

4. One or more instances of the Client

The Name Server is the resource manager of the system and must be executed prior to all other components. As each of the remaining servers begins execution, they are required to register with the Name Server. Consequently, the Name Server is aware of all resources available in the system and will allocate resources in a load-balanced fashion when requested. The two Front End Servers follow the Name Server in execution. One or both of the Front End Servers must be instantiated for the system to operate. Subsequently, one or more instances of the Database Servers may be executed. When all three servers are operational, one or more Clients may connect to the system.

Once the system is up and running, the Front End Servers and Database Servers can be brought up or taken down at will, with the caveat that at least one Front End Server and one Database Server must be executing at all times. There are only two Front End Servers, but any number of Database Servers (one or more) can be active at any given time. This redundancy leads to fault tolerance and scalability in the system. The Client(s) can attach and detach from the system at any given time.

Conclusions

6.1 Summary

The purpose of this project is to develop an Enterprise level Point of Sale system. The end user sees the current implementation of ADSFPOSS as rudimentary; she sees that the system supports two modes of operation, posting invoices and retrieving reports. However, underneath the surface, the architecture of the system lends it to be Enterprise in nature. Internally, ADSFPOSS is scalable, so when the system is stressed, more resources can be added. The system is also secure, which is appropriate for financial applications. More over, the software is fault tolerant so single failures does not bring down the entire system.

ADSFPOSS, as it is in its current form, is very much a school project that demonstrates a distributed software system. However, additional features and upgrades in a future implementation could make it a commercial grade, fully featured Point of Sale system.

6.2 Future Implementation and Upgrades

As stated in the previous Section 6.1, the current implementation of ADSFPOSS is rudimentary. Although the architecture of the system makes it suitable for Enterprise level applications, ADSFPOSS lacks features a fully functional Point of Sale System requires. Additional features may include more comprehensive invoicing form, a detailed reporting system, a SQL Database Management System to store data, and inventory control features.. As a networked application, the system would be enhanced through the support of wireless client features, perhaps through a PDA, and web based access.

Appendix

1 Source Code

Appendix A: Source Code

BinConverter.java

package clientPkg;

/**

* some helper routines for data conversion,

* all data is treated in network byte order

* @author Markus Hahn

* @version 16 May 2000

*/

public class BinConverter {

/**

* gets bytes from an array into a long

* @param buffer where to get the bytes

* @param nStartIndex index from where to read the data

* @return the 64bit integer

*/

public static long byteArrayToLong(byte[] buffer,

int nStartIndex)

{

return (((long)buffer[nStartIndex]) >> 40) & 0x0ff);

buffer[nStartIndex + 3] = (byte) ((lValue >>> 32) & 0x0ff);

buffer[nStartIndex + 4] = (byte) ((lValue >>> 24) & 0x0ff);

buffer[nStartIndex + 5] = (byte) ((lValue >>> 16) & 0x0ff);

buffer[nStartIndex + 6] = (byte) ((lValue >>> 8) & 0x0ff);

buffer[nStartIndex + 7] = (byte) lValue;

}

/**

* converts values from an integer array to a long

* @param buffer where to get the bytes

* @param nStartIndex index from where to read the data

* @return the 64bit integer

*/

public static long intArrayToLong(int[] buffer,

int nStartIndex)

{

return (((long) buffer[nStartIndex]) >> 32);

buffer[nStartIndex + 1] = (int) lValue;

}

/**

* makes a long from two integers (treated unsigned)

* @param nLo lower 32bits

* @param nHi higher 32bits

* @return the built long

*/

public static long makeLong(int nLo,

int nHi)

{

return (((long)nHi >> 32));

}

// our table for binhex conversion

final static char[] HEXTAB = { '0', '1', '2', '3', '4', '5', '6', '7',

'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

/**

* converts a byte array to a binhex string

* @param data the byte array

* @return the binhex string

*/

public static String bytesToBinHex(byte[] data)

{

// just map the call

return bytesToBinHex(data, 0, data.length);

}

/**

* converts a byte array to a binhex string

* @param data the byte array

* @param nStartPos start index where to get the bytes

* @param nNumOfBytes number of bytes to convert

* @return the binhex string

*/

public static String bytesToBinHex(byte[] data,

int nStartPos,

int nNumOfBytes)

{

StringBuffer sbuf = new StringBuffer();

sbuf.setLength(nNumOfBytes > 4) & 0x0f]);

sbuf.setCharAt(nPos++, HEXTAB[data[nI + nStartPos] & 0x0f]);

}

return sbuf.toString();

}

/**

* converts a binhex string back into a byte array

* (invalid codes will be skipped)

* @param sBinHex binhex string

* @param data the target array

* @param nSrcPos from which character in the string the conversion should

* begin, remember that (nSrcPos modulo 2) should equals 0 normally

* @param nDstPos to store the bytes from which position in the array

* @param nNumOfBytes number of bytes to extract

* @return number of extracted bytes

*/

public static int binHexToBytes(String sBinHex,

byte[] data,

int nSrcPos,

int nDstPos,

int nNumOfBytes)

{

// check for correct ranges

int nStrLen = sBinHex.length();

int nAvailBytes = (nStrLen - nSrcPos) >> 1;

if (nAvailBytes < nNumOfBytes)

{

nNumOfBytes = nAvailBytes;

}

int nOutputCapacity = data.length - nDstPos;

if (nNumOfBytes > nOutputCapacity)

{

nNumOfBytes = nOutputCapacity;

}

// convert now

int nResult = 0;

for (int nI = 0; nI < nNumOfBytes; nI++)

{

byte bActByte = 0;

boolean blConvertOK = true;

for (int nJ = 0; nJ < 2; nJ++)

{

bActByte 1);

int nSBufPos = 0;

while (nNumOfBytes > 0)

{

sbuf.setCharAt(nSBufPos++,

(char) ( ( (int) data[nStartPos] > 32);

m_pbox[nI+1] = (int) (lZero & 0x0ffffffffL);

}

for (nI = 0; nI < SBOX_ENTRIES; nI += 2)

{

lZero = encryptBlock(lZero);

m_sbox1[nI] = (int) (lZero >>> 32);

m_sbox1[nI+1] = (int) (lZero & 0x0ffffffffL);

}

for (nI = 0; nI < SBOX_ENTRIES; nI += 2)

{

lZero = encryptBlock(lZero);

m_sbox2[nI] = (int) (lZero >>> 32);

m_sbox2[nI+1] = (int) (lZero & 0x0ffffffffL);

}

for (nI = 0; nI < SBOX_ENTRIES; nI += 2)

{

lZero = encryptBlock(lZero);

m_sbox3[nI] = (int) (lZero >>> 32);

m_sbox3[nI+1] = (int) (lZero & 0x0ffffffffL);

}

for (nI = 0; nI < SBOX_ENTRIES; nI += 2)

{

lZero = encryptBlock(lZero);

m_sbox4[nI] = (int) (lZero >>> 32);

m_sbox4[nI+1] = (int) (lZero & 0x0ffffffffL);

}

}

/**

* to clear data in the boxes before an instance is freed

*/

public void cleanUp()

{

int nI;

for (nI = 0; nI < PBOX_ENTRIES; nI++)

{

m_pbox[nI] = 0;

}

for (nI = 0; nI < SBOX_ENTRIES; nI++)

{

m_sbox1[nI] = m_sbox2[nI] = m_sbox3[nI] = m_sbox4[nI] = 0;

}

}

/**

* selftest routine, to check e.g. for a valid class file transmission

* @return true: selftest passed / false: selftest failed

*/

public static boolean selfTest()

{

// test vector #1 (checking for the "signed bug")

byte[] testKey1 = { (byte) 0x1c, (byte) 0x58, (byte) 0x7f, (byte) 0x1c,

(byte) 0x13, (byte) 0x92, (byte) 0x4f, (byte) 0xef };

int[] tv_p1 = { 0x30553228, 0x6d6f295a };

int[] tv_c1 = { 0x55cb3774, 0xd13ef201 };

int[] tv_t1 = new int[2];

// test vector #2 (offical vector by Bruce Schneier)

String sTestKey2 = "Who is John Galt?";

byte[] testKey2 = sTestKey2.getBytes();

int[] tv_p2 = { 0xfedcba98, 0x76543210 };

int[] tv_c2 = { 0xcc91732b, 0x8022f684 };

int[] tv_t2 = new int[2];

// start the tests, check for a proper decryption, too

BlowfishECB testbf1 = new BlowfishECB(testKey1);

testbf1.encrypt(tv_p1, tv_t1);

if ((tv_t1[0] != tv_c1[0]) ||

(tv_t1[1] != tv_c1[1]))

{

return false;

}

testbf1.decrypt(tv_t1);

if ((tv_t1[0] != tv_p1[0]) ||

(tv_t1[1] != tv_p1[1]))

{

return false;

}

BlowfishECB testbf2 = new BlowfishECB(testKey2);

testbf2.encrypt(tv_p2, tv_t2);

if ((tv_t2[0] != tv_c2[0]) ||

(tv_t2[1] != tv_c2[1]))

{

return false;

}

testbf2.decrypt(tv_t2);

if ((tv_t2[0] != tv_p2[0]) ||

(tv_t2[1] != tv_p2[1]))

{

return false;

}

// all tests passed

return true;

}

// internal routine to encrypt a 64bit block

protected long encryptBlock(long lPlainBlock)

{

// split the block in two 32 bit halves

int nLeft = BinConverter.longHi32(lPlainBlock);

int nRight = BinConverter.longLo32(lPlainBlock);

// encrypt the block, gain more speed by unrooling the loop

// (we avoid swapping by using nLeft and nRight alternating

// at odd an even loop nubers)

// unrolled loop #1 (odd)

nLeft ^= m_pbox[0];

nRight ^=

( (m_sbox1[nLeft >>> 24] + m_sbox2[ (nLeft >>> 16) & 0x0ff]) ^

m_sbox3[ (nLeft >>> 8) & 0x0ff]) + m_sbox4[nLeft & 0x0ff];

// unrolled loop #2 (even)

nRight ^= m_pbox[1];

nLeft ^=

( (m_sbox1[nRight >>> 24] + m_sbox2[ (nRight >>> 16) & 0x0ff]) ^

m_sbox3[ (nRight >>> 8) & 0x0ff]) + m_sbox4[nRight & 0x0ff];

// unrolled loop #3 (odd)

nLeft ^= m_pbox[2];

nRight ^=

( (m_sbox1[nLeft >>> 24] + m_sbox2[ (nLeft >>> 16) & 0x0ff]) ^

m_sbox3[ (nLeft >>> 8) & 0x0ff]) + m_sbox4[nLeft & 0x0ff];

// unrolled loop #4 (even)

nRight ^= m_pbox[3];

nLeft ^=

( (m_sbox1[nRight >>> 24] + m_sbox2[ (nRight >>> 16) & 0x0ff]) ^

m_sbox3[ (nRight >>> 8) & 0x0ff]) + m_sbox4[nRight & 0x0ff];

// unrolled loop #5 (odd)

nLeft ^= m_pbox[4];

nRight ^=

( (m_sbox1[nLeft >>> 24] + m_sbox2[ (nLeft >>> 16) & 0x0ff]) ^

m_sbox3[ (nLeft >>> 8) & 0x0ff]) + m_sbox4[nLeft & 0x0ff];

// unrolled loop #6 (even)

nRight ^= m_pbox[5];

nLeft ^=

( (m_sbox1[nRight >>> 24] + m_sbox2[ (nRight >>> 16) & 0x0ff]) ^

m_sbox3[ (nRight >>> 8) & 0x0ff]) + m_sbox4[nRight & 0x0ff];

// unrolled loop #7 (odd)

nLeft ^= m_pbox[6];

nRight ^=

( (m_sbox1[nLeft >>> 24] + m_sbox2[ (nLeft >>> 16) & 0x0ff]) ^

m_sbox3[ (nLeft >>> 8) & 0x0ff]) + m_sbox4[nLeft & 0x0ff];

// unrolled loop #8 (even)

nRight ^= m_pbox[7];

nLeft ^=

( (m_sbox1[nRight >>> 24] + m_sbox2[ (nRight >>> 16) & 0x0ff]) ^

m_sbox3[ (nRight >>> 8) & 0x0ff]) + m_sbox4[nRight & 0x0ff];

// unrolled loop #9 (odd)

nLeft ^= m_pbox[8];

nRight ^=

( (m_sbox1[nLeft >>> 24] + m_sbox2[ (nLeft >>> 16) & 0x0ff]) ^

m_sbox3[ (nLeft >>> 8) & 0x0ff]) + m_sbox4[nLeft & 0x0ff];

// unrolled loop #10 (even)

nRight ^= m_pbox[9];

nLeft ^=

( (m_sbox1[nRight >>> 24] + m_sbox2[ (nRight >>> 16) & 0x0ff]) ^

m_sbox3[ (nRight >>> 8) & 0x0ff]) + m_sbox4[nRight & 0x0ff];

// unrolled loop #11 (odd)

nLeft ^= m_pbox[10];

nRight ^=

( (m_sbox1[nLeft >>> 24] + m_sbox2[ (nLeft >>> 16) & 0x0ff]) ^

m_sbox3[ (nLeft >>> 8) & 0x0ff]) + m_sbox4[nLeft & 0x0ff];

// unrolled loop #12 (even)

nRight ^= m_pbox[11];

nLeft ^=

( (m_sbox1[nRight >>> 24] + m_sbox2[ (nRight >>> 16) & 0x0ff]) ^

m_sbox3[ (nRight >>> 8) & 0x0ff]) + m_sbox4[nRight & 0x0ff];

// unrolled loop #13 (odd)

nLeft ^= m_pbox[12];

nRight ^=

( (m_sbox1[nLeft >>> 24] + m_sbox2[ (nLeft >>> 16) & 0x0ff]) ^

m_sbox3[ (nLeft >>> 8) & 0x0ff]) + m_sbox4[nLeft & 0x0ff];

// unrolled loop #14 (even)

nRight ^= m_pbox[13];

nLeft ^=

( (m_sbox1[nRight >>> 24] + m_sbox2[ (nRight >>> 16) & 0x0ff]) ^

m_sbox3[ (nRight >>> 8) & 0x0ff]) + m_sbox4[nRight & 0x0ff];

// unrolled loop #15 (odd)

nLeft ^= m_pbox[14];

nRight ^=

( (m_sbox1[nLeft >>> 24] + m_sbox2[ (nLeft >>> 16) & 0x0ff]) ^

m_sbox3[ (nLeft >>> 8) & 0x0ff]) + m_sbox4[nLeft & 0x0ff];

// unrolled loop #16 (even)

nRight ^= m_pbox[15];

nLeft ^=

( (m_sbox1[nRight >>> 24] + m_sbox2[ (nRight >>> 16) & 0x0ff]) ^

m_sbox3[ (nRight >>> 8) & 0x0ff]) + m_sbox4[nRight & 0x0ff];

// swap and finalize

int nSwap = nRight;

nRight = nLeft ^ m_pbox[16];

nLeft = nSwap ^ m_pbox[17];

// reassemble and return the block

return BinConverter.makeLong(nRight, nLeft);

}

// internal routine to decrypt a 64bit block

protected long decryptBlock(long lCipherBlock)

{

// split the block in two 32 bit halves

int nLeft = BinConverter.longHi32(lCipherBlock);

int nRight = BinConverter.longLo32(lCipherBlock);

// decrypt the block, gain more speed by unrooling the loop

// (we avoid swaping by using nLeft and nRight alternating

// at odd an even loop nubers)

// unrolled loop #1 (odd)

nLeft ^= m_pbox[17];

nRight ^=

( (m_sbox1[nLeft >>> 24] + m_sbox2[ (nLeft >>> 16) & 0x0ff]) ^

m_sbox3[ (nLeft >>> 8) & 0x0ff]) + m_sbox4[nLeft & 0x0ff];

// unrolled loop #2 (even)

nRight ^= m_pbox[16];

nLeft ^=

( (m_sbox1[nRight >>> 24] + m_sbox2[ (nRight >>> 16) & 0x0ff]) ^

m_sbox3[ (nRight >>> 8) & 0x0ff]) + m_sbox4[nRight & 0x0ff];

// unrolled loop #3 (odd)

nLeft ^= m_pbox[15];

nRight ^=

( (m_sbox1[nLeft >>> 24] + m_sbox2[ (nLeft >>> 16) & 0x0ff]) ^

m_sbox3[ (nLeft >>> 8) & 0x0ff]) + m_sbox4[nLeft & 0x0ff];

// unrolled loop #4 (even)

nRight ^= m_pbox[14];

nLeft ^=

( (m_sbox1[nRight >>> 24] + m_sbox2[ (nRight >>> 16) & 0x0ff]) ^

m_sbox3[ (nRight >>> 8) & 0x0ff]) + m_sbox4[nRight & 0x0ff];

// unrolled loop #5 (odd)

nLeft ^= m_pbox[13];

nRight ^=

( (m_sbox1[nLeft >>> 24] + m_sbox2[ (nLeft >>> 16) & 0x0ff]) ^

m_sbox3[ (nLeft >>> 8) & 0x0ff]) + m_sbox4[nLeft & 0x0ff];

// unrolled loop #6 (even)

nRight ^= m_pbox[12];

nLeft ^=

( (m_sbox1[nRight >>> 24] + m_sbox2[ (nRight >>> 16) & 0x0ff]) ^

m_sbox3[ (nRight >>> 8) & 0x0ff]) + m_sbox4[nRight & 0x0ff];

// unrolled loop #7 (odd)

nLeft ^= m_pbox[11];

nRight ^=

( (m_sbox1[nLeft >>> 24] + m_sbox2[ (nLeft >>> 16) & 0x0ff]) ^

m_sbox3[ (nLeft >>> 8) & 0x0ff]) + m_sbox4[nLeft & 0x0ff];

// unrolled loop #8 (even)

nRight ^= m_pbox[10];

nLeft ^=

( (m_sbox1[nRight >>> 24] + m_sbox2[ (nRight >>> 16) & 0x0ff]) ^

m_sbox3[ (nRight >>> 8) & 0x0ff]) + m_sbox4[nRight & 0x0ff];

// unrolled loop #9 (odd)

nLeft ^= m_pbox[9];

nRight ^=

( (m_sbox1[nLeft >>> 24] + m_sbox2[ (nLeft >>> 16) & 0x0ff]) ^

m_sbox3[ (nLeft >>> 8) & 0x0ff]) + m_sbox4[nLeft & 0x0ff];

// unrolled loop #10 (even)

nRight ^= m_pbox[8];

nLeft ^=

( (m_sbox1[nRight >>> 24] + m_sbox2[ (nRight >>> 16) & 0x0ff]) ^

m_sbox3[ (nRight >>> 8) & 0x0ff]) + m_sbox4[nRight & 0x0ff];

// unrolled loop #11 (odd)

nLeft ^= m_pbox[7];

nRight ^=

( (m_sbox1[nLeft >>> 24] + m_sbox2[ (nLeft >>> 16) & 0x0ff]) ^

m_sbox3[ (nLeft >>> 8) & 0x0ff]) + m_sbox4[nLeft & 0x0ff];

// unrolled loop #12 (even)

nRight ^= m_pbox[6];

nLeft ^=

( (m_sbox1[nRight >>> 24] + m_sbox2[ (nRight >>> 16) & 0x0ff]) ^

m_sbox3[ (nRight >>> 8) & 0x0ff]) + m_sbox4[nRight & 0x0ff];

// unrolled loop #13 (odd)

nLeft ^= m_pbox[5];

nRight ^=

( (m_sbox1[nLeft >>> 24] + m_sbox2[ (nLeft >>> 16) & 0x0ff]) ^

m_sbox3[ (nLeft >>> 8) & 0x0ff]) + m_sbox4[nLeft & 0x0ff];

// unrolled loop #14 (even)

nRight ^= m_pbox[4];

nLeft ^=

( (m_sbox1[nRight >>> 24] + m_sbox2[ (nRight >>> 16) & 0x0ff]) ^

m_sbox3[ (nRight >>> 8) & 0x0ff]) + m_sbox4[nRight & 0x0ff];

// unrolled loop #15 (odd)

nLeft ^= m_pbox[3];

nRight ^=

( (m_sbox1[nLeft >>> 24] + m_sbox2[ (nLeft >>> 16) & 0x0ff]) ^

m_sbox3[ (nLeft >>> 8) & 0x0ff]) + m_sbox4[nLeft & 0x0ff];

// unrolled loop #16 (even)

nRight ^= m_pbox[2];

nLeft ^=

( (m_sbox1[nRight >>> 24] + m_sbox2[ (nRight >>> 16) & 0x0ff]) ^

m_sbox3[ (nRight >>> 8) & 0x0ff]) + m_sbox4[nRight & 0x0ff];

// swap and finalize

int nSwap = nRight;

nRight = nLeft ^ m_pbox[1];

nLeft = nSwap ^ m_pbox[0];

// reassemble and return the block

return BinConverter.makeLong(nRight, nLeft);

}

/**

* encrypts a byte buffer (should be aligned to an 8 byte border)

* to another buffer (of the same size or bigger)

* @param inbuffer buffer with plaintext data

* @param outbuffer buffer to get the ciphertext data

*/

public void encrypt(byte[] inbuffer,

byte[] outbuffer)

{

int nLen = inbuffer.length;

long lTemp;

for (int nI = 0; nI < nLen; nI +=8)

{

// encrypt a temporary 64bit block

lTemp = BinConverter.byteArrayToLong(inbuffer, nI);

lTemp = encryptBlock(lTemp);

BinConverter.longToByteArray(lTemp, outbuffer, nI);

}

}

/**

* encrypts a byte buffer (should be aligned to an 8 byte border) to itself

* @param buffer buffer to encrypt

*/

public void encrypt(byte[] buffer)

{

int nLen = buffer.length;

long lTemp;

for (int nI = 0; nI < nLen; nI +=8)

{

// encrypt a temporary 64bit block

lTemp = BinConverter.byteArrayToLong(buffer, nI);

lTemp = encryptBlock(lTemp);

BinConverter.longToByteArray(lTemp, buffer, nI);

}

}

/**

* encrypts an integer buffer (should be aligned to an

* two integer border) to another int buffer (of the

* same size or bigger)

* @param inbuffer buffer with plaintext data

* @param outBuffer buffer to get the ciphertext data

*/

public void encrypt(int[] inbuffer,

int[] outbuffer)

{

int nLen = inbuffer.length;

long lTemp;

for (int nI = 0; nI < nLen; nI +=2)

{

// encrypt a temporary 64bit block

lTemp = BinConverter.intArrayToLong(inbuffer, nI);

lTemp = encryptBlock(lTemp);

BinConverter.longToIntArray(lTemp, outbuffer, nI);

}

}

/**

* encrypts an int buffer (should be aligned to a

* two integer border)

* @param buffer buffer to encrypt

*/

public void encrypt(int[] buffer)

{

int nLen = buffer.length;

long lTemp;

for (int nI = 0; nI < nLen; nI +=2)

{

// encrypt a temporary 64bit block

lTemp = BinConverter.intArrayToLong(buffer, nI);

lTemp = encryptBlock(lTemp);

BinConverter.longToIntArray(lTemp, buffer, nI);

}

}

/**

* encrypts a long buffer to another long buffer (of the same size or bigger)

* @param inbuffer buffer with plaintext data

* @param outbuffer buffer to get the ciphertext data

*/

public void encrypt(long[] inbuffer,

long[] outbuffer)

{

int nLen = inbuffer.length;

for (int nI = 0; nI < nLen; nI++)

{

outbuffer[nI] = encryptBlock(inbuffer[nI]);

}

}

/**

* encrypts a long buffer to itself

* @param buffer buffer to encrypt

*/

public void encrypt(long[] buffer)

{

int nLen = buffer.length;

for (int nI = 0; nI < nLen; nI++)

{

buffer[nI] = encryptBlock(buffer[nI]);

}

}

/**

* decrypts a byte buffer (should be aligned to an 8 byte border)

* to another byte buffer (of the same size or bigger)

* @param inbuffer buffer with ciphertext data

* @param outBuffer buffer to get the plaintext data

*/

public void decrypt(byte[] inbuffer,

byte[] outbuffer)

{

int nLen = inbuffer.length;

long lTemp;

for (int nI = 0; nI < nLen; nI +=8)

{

// decrypt a temporary 64bit block

lTemp = BinConverter.byteArrayToLong(inbuffer, nI);

lTemp = decryptBlock(lTemp);

BinConverter.longToByteArray(lTemp, outbuffer, nI);

}

}

/**

* decrypts a byte buffer (should be aligned to an 8 byte border) to itself

* @param buffer buffer to decrypt

*/

public void decrypt(byte[] buffer)

{

int nLen = buffer.length;

long lTemp;

for (int nI = 0; nI < nLen; nI +=8)

{

// decrypt over a temporary 64bit block

lTemp = BinConverter.byteArrayToLong(buffer, nI);

lTemp = decryptBlock(lTemp);

BinConverter.longToByteArray(lTemp, buffer, nI);

}

}

/**

* decrypts an integer buffer (should be aligned to an

* two integer border) to another int buffer (of the same size or bigger)

* @param inbuffer buffer with ciphertext data

* @param outbuffer buffer to get the plaintext data

*/

public void decrypt(int[] inbuffer,

int[] outbuffer)

{

int nLen = inbuffer.length;

long lTemp;

for (int nI = 0; nI < nLen; nI +=2)

{

// decrypt a temporary 64bit block

lTemp = BinConverter.intArrayToLong(inbuffer, nI);

lTemp = decryptBlock(lTemp);

BinConverter.longToIntArray(lTemp, outbuffer, nI);

}

}

/**

* decrypts an int buffer (should be aligned to an

* two integer border)

* @param buffer buffer to decrypt

*/

public void decrypt(int[] buffer)

{

int nLen = buffer.length;

long lTemp;

for (int nI = 0; nI < nLen; nI +=2)

{

// decrypt a temporary 64bit block

lTemp = BinConverter.intArrayToLong(buffer, nI);

lTemp = decryptBlock(lTemp);

BinConverter.longToIntArray(lTemp, buffer, nI);

}

}

/**

* decrypts a long buffer to another long buffer (of the same size or bigger)

* @param inbuffer buffer with ciphertext data

* @param outbuffer buffer to get the plaintext data

*/

public void decrypt(long[] inbuffer,

long[] outbuffer)

{

int nLen = inbuffer.length;

for (int nI = 0; nI < nLen; nI++)

{

outbuffer[nI] = decryptBlock(inbuffer[nI]);

}

}

/**

* decrypts a long buffer to itself

* @param buffer buffer to decrypt

*/

public void decrypt(long[] buffer) {

int nLen = buffer.length;

for (int nI = 0; nI < nLen; nI++)

{

buffer[nI] = decryptBlock(buffer[nI]);

}

}

// the boxes init. data,

// FIXME: it might be better to create them at runtime to make the class

// file smaller, e.g. by calculating the hexdigits of pi (default)

// or just a fixed random sequence (out of the standard)

final static int pbox_init[] = {

0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,

0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,

0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b };

final static int sbox_init_1[] = {

0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,

0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,

0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,

0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,

0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,

0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,

0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,

0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,

0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,

0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,

0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,

0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,

0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,

0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,

0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,

0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,

0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,

0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,

0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,

0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,

0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,

0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,

0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,

0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,

0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,

0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,

0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,

0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,

0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,

0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,

0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,

0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,

0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,

0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,

0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,

0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,

0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,

0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,

0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,

0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,

0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,

0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,

0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a};

final static int sbox_init_2[] = {

0x4b7a70e9, 0xb5b32944,

0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,

0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29,

0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,

0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26,

0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,

0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c,

0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,

0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 0x7ca92ff6,

0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,

0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f,

0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,

0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810,

0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,

0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa,

0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,

0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55,

0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,

0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1,

0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,

0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0xc6150eba, 0x94e2ea78,

0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,

0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883,

0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,

0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170,

0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,

0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7,

0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,

0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099,

0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,

0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263,

0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,

0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3,

0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,

0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7,

0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,

0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d,

0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,

0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460,

0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,

0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484,

0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,

0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a,

0xe6e39f2b, 0xdb83adf7};

final static int sbox_init_3[] = {

0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,

0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a,

0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,

0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785,

0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,

0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900,

0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,

0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9,

0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,

0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397,

0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,

0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9,

0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,

0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f,

0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,

0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e,

0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,

0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd,

0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,

0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8,

0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,

0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c,

0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,

0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b,

0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,

0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386,

0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,

0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0,

0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,

0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2,

0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,

0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770,

0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,

0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c,

0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,

0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa,

0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,

0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63,

0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,

0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9,

0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,

0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4,

0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0};

final static int sbox_init_4[] = {

0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,

0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,

0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,

0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,

0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,

0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,

0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,

0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,

0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,

0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,

0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,

0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,

0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,

0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,

0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,

0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,

0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,

0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,

0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,

0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,

0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,

0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,

0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,

0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,

0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,

0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,

0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,

0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,

0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,

0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,

0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,

0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,

0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,

0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,

0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,

0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,

0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,

0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,

0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,

0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,

0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,

0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,

0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6};

}

clientClass.java

package clientPkg;

import javax.swing.UIManager;

import java.awt.*;

import java.rmi.*;

/*

* class: clientClass

* description: clientClass sets the default values for generating client

* user interface (ui). the actual ui is generated by

* clientFrame.

* inputs: none

* outputs: none

* return value: none

*/

public class clientClass

{

boolean packFrame = false;

/*

* function: clientClass

* description: constructor

* inputs: none

* outputs: none

* return value: none

*/

public clientClass()

{

clientFrame frame = new clientFrame();

// pack or validate ui frame

if (packFrame)

frame.pack();

else

frame.validate();

// center the window

Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

Dimension frameSize = frame.getSize();

if (frameSize.height > screenSize.height)

{

frameSize.height = screenSize.height;

}

if (frameSize.width > screenSize.width)

{

frameSize.width = screenSize.width;

}

frame.setLocation((screenSize.width - frameSize.width) / 2,

(screenSize.height - frameSize.height) / 2);

frame.setVisible(true);

}

/*

* function: main

* description: set look and feel and contruct ui

* inputs: none

* outputs: none

* return value: none

*/

public static void main(String[] args)

{

try

{

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

}

catch(Exception e)

{

e.printStackTrace();

}

new clientClass();

}

}

clientFrame.java

package clientPkg;

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import com.borland.jbcl.layout.*;

import javax.swing.border.*;

import java.rmi.*;

import java.io.*;

import java.util.*;

import java.lang.*;

import java.text.DecimalFormat;

import java.math.BigInteger;

import java.security.*;

import java.security.spec.*;

import java.security.interfaces.*;

import javax.crypto.*;

import javax.crypto.spec.*;

import javax.crypto.interfaces.*;

import com.sun.crypto.provider.SunJCE;

/*

* class: clientFrame

* description: clientFrame generates the user interface (ui), the controls,

* and the functionality of the controls

* inputs: none

* outputs: none

* return value: none

*/

public class clientFrame extends JFrame

{

nameSvrInterface objNameSvr;

frontEndSvrInterface objFrontEndSvr;

encReport objEncReport;

byte[] byteSecretKey;

JPanel contentPane;

JMenuBar jMenuBar1 = new JMenuBar();

JMenu jMenuFile = new JMenu();

JMenuItem jMenuFileExit = new JMenuItem();

JMenu jMenuHelp = new JMenu();

JMenuItem jMenuHelpAbout = new JMenuItem();

JToolBar jToolBar = new JToolBar();

JButton jButton1 = new JButton();

JButton jButton2 = new JButton();

JButton jButton3 = new JButton();

ImageIcon image1;

ImageIcon image2;

ImageIcon image3;

JLabel statusBar = new JLabel();

JTabbedPane jTabbedPane1 = new JTabbedPane();

JPanel report = new JPanel();

JScrollPane textPad = new JScrollPane();

GridBagLayout gridBagLayout1 = new GridBagLayout();

JPanel invoice = new JPanel();

JPanel addPanel = new JPanel();

JLabel lbBillName = new JLabel();

JTextField tfBillName = new JTextField();

JLabel lbShipName = new JLabel();

JTextField tfShipName = new JTextField();

JTextField tfShipAddress = new JTextField();

JLabel lbBillAddress = new JLabel();

JLabel lbShipAddress = new JLabel();

JTextField tfBillAddress = new JTextField();

JTextField tfShipState = new JTextField();

JLabel lbBillState = new JLabel();

JTextField tfBillState = new JTextField();

JLabel lbShipState = new JLabel();

JTextField tfShipCity = new JTextField();

JLabel lbShipCity = new JLabel();

JTextField tfBillCity = new JTextField();

JLabel lbBillCity = new JLabel();

JTextField tfShipZip = new JTextField();

JLabel lbBillZip = new JLabel();

JTextField tfBillZip = new JTextField();

JLabel lbShipZip = new JLabel();

JLabel lbBillInfo = new JLabel();

TitledBorder titledBorder1;

JLabel lbShipInfo = new JLabel();

JComboBox cbItem0 = new JComboBox();

JLabel lbExtend0 = new JLabel();

JLabel lbPrice0 = new JLabel();

JLabel lbExtend1 = new JLabel();

JComboBox cbQty1 = new JComboBox();

JComboBox cbItem1 = new JComboBox();

JLabel lbPrice1 = new JLabel();

JLabel lbPrice2 = new JLabel();

JComboBox cbQty2 = new JComboBox();

JLabel lbExtend2 = new JLabel();

JComboBox cbItem2 = new JComboBox();

JComboBox cbItem3 = new JComboBox();

JComboBox cbQty3 = new JComboBox();

JLabel lbPrice3 = new JLabel();

JLabel lbExtend3 = new JLabel();

JLabel lbExtend4 = new JLabel();

JComboBox cbQty4 = new JComboBox();

JComboBox cbItem4 = new JComboBox();

JLabel lbPrice4 = new JLabel();

JLabel lbQty = new JLabel();

JLabel lbItem = new JLabel();

JLabel lbPrice = new JLabel();

JLabel lbExtend = new JLabel();

JLabel lbTotalNum = new JLabel();

JLabel lbSubTotalNum = new JLabel();

JLabel lbTaxNum = new JLabel();

JLabel lbTax = new JLabel();

JLabel lbTotal = new JLabel();

JLabel lbSubTotal = new JLabel();

JComboBox cbQty0 = new JComboBox();

JButton butSubmit = new JButton();

JButton butClear = new JButton();

TitledBorder titledBorder2;

JButton butGetReport = new JButton();

JTextArea taReport = new JTextArea();

TitledBorder titledBorder3;

// the 1024 bit Diffie-Hellman modulus values used by SKIP

private static final byte skip1024ModulusBytes[] =

{

(byte) 0xF4, (byte) 0x88, (byte) 0xFD, (byte) 0x58,

(byte) 0x4E, (byte) 0x49, (byte) 0xDB, (byte) 0xCD,

(byte) 0x20, (byte) 0xB4, (byte) 0x9D, (byte) 0xE4,

(byte) 0x91, (byte) 0x07, (byte) 0x36, (byte) 0x6B,

(byte) 0x33, (byte) 0x6C, (byte) 0x38, (byte) 0x0D,

(byte) 0x45, (byte) 0x1D, (byte) 0x0F, (byte) 0x7C,

(byte) 0x88, (byte) 0xB3, (byte) 0x1C, (byte) 0x7C,

(byte) 0x5B, (byte) 0x2D, (byte) 0x8E, (byte) 0xF6,

(byte) 0xF3, (byte) 0xC9, (byte) 0x23, (byte) 0xC0,

(byte) 0x43, (byte) 0xF0, (byte) 0xA5, (byte) 0x5B,

(byte) 0x18, (byte) 0x8D, (byte) 0x8E, (byte) 0xBB,

(byte) 0x55, (byte) 0x8C, (byte) 0xB8, (byte) 0x5D,

(byte) 0x38, (byte) 0xD3, (byte) 0x34, (byte) 0xFD,

(byte) 0x7C, (byte) 0x17, (byte) 0x57, (byte) 0x43,

(byte) 0xA3, (byte) 0x1D, (byte) 0x18, (byte) 0x6C,

(byte) 0xDE, (byte) 0x33, (byte) 0x21, (byte) 0x2C,

(byte) 0xB5, (byte) 0x2A, (byte) 0xFF, (byte) 0x3C,

(byte) 0xE1, (byte) 0xB1, (byte) 0x29, (byte) 0x40,

(byte) 0x18, (byte) 0x11, (byte) 0x8D, (byte) 0x7C,

(byte) 0x84, (byte) 0xA7, (byte) 0x0A, (byte) 0x72,

(byte) 0xD6, (byte) 0x86, (byte) 0xC4, (byte) 0x03,

(byte) 0x19, (byte) 0xC8, (byte) 0x07, (byte) 0x29,

(byte) 0x7A, (byte) 0xCA, (byte) 0x95, (byte) 0x0C,

(byte) 0xD9, (byte) 0x96, (byte) 0x9F, (byte) 0xAB,

(byte) 0xD0, (byte) 0x0A, (byte) 0x50, (byte) 0x9B,

(byte) 0x02, (byte) 0x46, (byte) 0xD3, (byte) 0x08,

(byte) 0x3D, (byte) 0x66, (byte) 0xA4, (byte) 0x5D,

(byte) 0x41, (byte) 0x9F, (byte) 0x9C, (byte) 0x7C,

(byte) 0xBD, (byte) 0x89, (byte) 0x4B, (byte) 0x22,

(byte) 0x19, (byte) 0x26, (byte) 0xBA, (byte) 0xAB,

(byte) 0xA2, (byte) 0x5E, (byte) 0xC3, (byte) 0x55,

(byte) 0xE9, (byte) 0x2F, (byte) 0x78, (byte) 0xC7

};

// the SKIP 1024 bit modulus

private static final BigInteger skip1024Modulus

= new BigInteger(1, skip1024ModulusBytes);

// the base used with the SKIP 1024 bit modulus

private static final BigInteger skip1024Base = BigInteger.valueOf(2);

/*

* function: clientFrame

* description: constructor

* inputs: none

* outputs: none

* return value: none

*/

public clientFrame()

{

enableEvents(AWTEvent.WINDOW_EVENT_MASK);

try

{

// build gui

jbInit();

}

catch(Exception e)

{

e.printStackTrace();

}

// use Diffie-Hellman to get secret key

try

{

pubKeyClient();

}

catch (Exception except)

{

System.out.println ("butSubmit error: " + except.getMessage());

}

}

/*

* function: pubKeyClient

* description: pubKeyClient uses the Diffie-Hellman algorithm to

* communicate with the name server via public key

* encryption. pubKeyClient generates its own public key,

* sends the public key to the name server. The name server

* generates a secret key with pubKeyClient's public key,

* and encodes a message for pubKeyClient with the secret

* key. pubKeyClient will decode the encrypted message with

* the its public key. the message is the key that will be

* used by blowfish to encrypt and decrypt data.

* inputs: none

* outputs: none

* return value: none

*/

public void pubKeyClient () throws Exception

{

String strNameSvrLoc = "rmi://127.0.0.1:6969/nameSvr";

// locate name server

try

{

objNameSvr = (nameSvrInterface) Naming.lookup(strNameSvrLoc);

}

catch (Exception except)

{

System.out.println ("pubKeyClient error: " + except.getMessage());

}

// use some pre-generated, default Skip DH parameters

DHParameterSpec dhSkipParamSpec =

new DHParameterSpec(skip1024Modulus, skip1024Base);

// app generates its own key pair from parameters above

KeyPairGenerator clientKpairGen = KeyPairGenerator.getInstance("DH");

clientKpairGen.initialize(dhSkipParamSpec);

KeyPair clientKpair = clientKpairGen.generateKeyPair();

// app creates and initializes own DH KeyAgreement object

KeyAgreement clientKeyAgree = KeyAgreement.getInstance("DH");

clientKeyAgree.init(clientKpair.getPrivate());

// app encodes own public key

byte[] clientPubKeyEnc = clientKpair.getPublic().getEncoded();

// app generates a copy of the server's public key from the server's

// encoded public key

KeyFactory clientKeyFac = KeyFactory.getInstance("DH");

X509EncodedKeySpec x509KeySpec =

new X509EncodedKeySpec(objNameSvr.getServerPubKeyEnc(clientPubKeyEnc));

PublicKey serverPubKey = clientKeyFac.generatePublic(x509KeySpec);

clientKeyAgree.doPhase(serverPubKey, true);

// generate secret key

SecretKey clientDesKey = clientKeyAgree.generateSecret("DES");

// get server's encoded message and decode it

byte[] ciphertext = objNameSvr.getServerEncMsg();

Cipher clientCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");

clientCipher.init(Cipher.DECRYPT_MODE, clientDesKey);

//byte[] recovered = clientCipher.doFinal(ciphertext);

byteSecretKey = clientCipher.doFinal(ciphertext);

// for information purpose only. compares received message with actual

// message to make sure correct data is received.

byte[] cleartext = new byte[20];

for (int i = 0; i < 20; i++)

cleartext[i] = (byte) ( (i + 1) & 0xff);

if (!java.util.Arrays.equals(cleartext, byteSecretKey))

System.out.println ("DES in CBC mode recovered text is " +

"different from cleartext");

else

{

System.out.println("DES in ECB mode recovered text is " +

"same as cleartext");

for (int i = 0; i < byteSecretKey.length; i++)

System.out.print(byteSecretKey[i] + " ");

System.out.println ();

for (int i = 0; i < cleartext.length; i++)

System.out.print(cleartext[i] + " ");

System.out.println ();

}

}

/*

* function: jbInit

* description: creates and places widgets on ui

* inputs: none

* outputs: none

* return value: none

*/

private void jbInit() throws Exception

{

// create widgets

image1 =

new ImageIcon(clientPkg.clientFrame.class.getResource("openFile.png"));

image2 =

new ImageIcon(clientPkg.clientFrame.class.getResource("closeFile.png"));

image3 = new ImageIcon(clientPkg.clientFrame.class.getResource("help.png"));

contentPane = (JPanel) this.getContentPane();

titledBorder1 = new TitledBorder("");

titledBorder2 = new TitledBorder("");

titledBorder3 = new TitledBorder("");

contentPane.setLayout(gridBagLayout1);

this.setSize(new Dimension(528, 613));

this.setTitle("Client");

statusBar.setBorder(BorderFactory.createLoweredBevelBorder());

statusBar.setText(" ");

jMenuFile.setText("File");

jMenuFileExit.setText("Exit");

jMenuFileExit.addActionListener

(new clientFrame_jMenuFileExit_ActionAdapter(this));

jMenuHelp.setText("Help");

jMenuHelpAbout.setText("About");

jMenuHelpAbout.addActionListener

(new clientFrame_jMenuHelpAbout_ActionAdapter(this));

jButton1.setIcon(image1);

jButton1.addActionListener(new clientFrame_jButton1_actionAdapter(this));

jButton1.setToolTipText("Open File");

jButton2.setIcon(image2);

jButton2.setToolTipText("Close File");

jButton3.setIcon(image3);

jButton3.setToolTipText("Help");

invoice.setLayout(null);

addPanel.setBackground(Color.lightGray);

addPanel.setLayout(null);

invoice.setAlignmentX((float) 0.5);

invoice.setBorder(BorderFactory.createLineBorder(Color.black));

lbBillName.setText("Name");

lbBillName.setBounds(new Rectangle(8, 53, 75, 25));

tfBillName.setText("");

tfBillName.setBounds(new Rectangle(101, 53, 150, 25));

lbShipName.setText("Name");

lbShipName.setBounds(new Rectangle(266, 53, 75, 25));

tfShipName.setText("");

tfShipName.setBounds(new Rectangle(358, 53, 150, 25));

tfShipName.addActionListener

(new clientFrame_tfShipName_actionAdapter(this));

tfShipAddress.setText("");

tfShipAddress.setBounds(new Rectangle(358, 79, 150, 25));

lbBillAddress.setText("Address");

lbBillAddress.setBounds(new Rectangle(8, 79, 75, 25));

lbShipAddress.setText("Address");

lbShipAddress.setBounds(new Rectangle(266, 79, 75, 25));

tfBillAddress.setText("");

tfBillAddress.setBounds(new Rectangle(101, 79, 150, 25));

tfShipState.setText("");

tfShipState.setBounds(new Rectangle(358, 131, 150, 25));

lbBillState.setText("State");

lbBillState.setBounds(new Rectangle(9, 131, 75, 25));

tfBillState.setText("");

tfBillState.setBounds(new Rectangle(101, 131, 150, 25));

lbShipState.setRequestFocusEnabled(false);

lbShipState.setText("State");

lbShipState.setBounds(new Rectangle(267, 131, 75, 25));

tfShipCity.setText("");

tfShipCity.setBounds(new Rectangle(358, 105, 150, 25));

lbShipCity.setText("City");

lbShipCity.setBounds(new Rectangle(266, 105, 75, 25));

tfBillCity.setText("");

tfBillCity.setBounds(new Rectangle(101, 105, 150, 25));

lbBillCity.setText("City");

lbBillCity.setBounds(new Rectangle(8, 105, 75, 25));

tfShipZip.setText("");

tfShipZip.setBounds(new Rectangle(358, 157, 150, 25));

tfShipZip.addActionListener(new clientFrame_tfShipZip_actionAdapter(this));

lbBillZip.setText("Zip Code");

lbBillZip.setBounds(new Rectangle(9, 157, 75, 25));

tfBillZip.setText("");

tfBillZip.setBounds(new Rectangle(101, 157, 150, 25));

lbShipZip.setText("Zip Code");

lbShipZip.setBounds(new Rectangle(267, 157, 75, 25));

lbBillInfo.setBackground(Color.lightGray);

lbBillInfo.setBorder(BorderFactory.createEtchedBorder());

lbBillInfo.setHorizontalAlignment(SwingConstants.CENTER);

lbBillInfo.setHorizontalTextPosition(SwingConstants.CENTER);

lbBillInfo.setText("Billing Information");

lbBillInfo.setBounds(new Rectangle(6, 24, 245, 26));

lbShipInfo.setBorder(BorderFactory.createEtchedBorder());

lbShipInfo.setHorizontalAlignment(SwingConstants.CENTER);

lbShipInfo.setHorizontalTextPosition(SwingConstants.CENTER);

lbShipInfo.setText("Shipping Information");

lbShipInfo.setBounds(new Rectangle(263, 24, 245, 26));

cbItem0.setBounds(new Rectangle(57, 233, 301, 25));

cbItem0.addActionListener(new clientFrame_cbItem0_actionAdapter(this));

lbExtend0.setBorder(BorderFactory.createLoweredBevelBorder());

lbExtend0.setHorizontalAlignment(SwingConstants.RIGHT);

lbExtend0.setText("0.00");

lbExtend0.setBounds(new Rectangle(433, 233, 75, 25));

lbPrice0.setBorder(BorderFactory.createLoweredBevelBorder());

lbPrice0.setDebugGraphicsOptions(0);

lbPrice0.setHorizontalAlignment(SwingConstants.RIGHT);

lbPrice0.setText("0.00");

lbPrice0.setBounds(new Rectangle(358, 233, 75, 25));

lbExtend1.setForeground(Color.black);

lbExtend1.setBorder(BorderFactory.createLoweredBevelBorder());

lbExtend1.setHorizontalAlignment(SwingConstants.RIGHT);

lbExtend1.setText("0.00");

lbExtend1.setBounds(new Rectangle(433, 259, 75, 25));

cbQty1.setBounds(new Rectangle(6, 259, 50, 25));

cbQty1.addActionListener(new clientFrame_cbQty1_actionAdapter(this));

cbItem1.setBounds(new Rectangle(57, 259, 301, 25));

cbItem1.addActionListener(new clientFrame_cbItem1_actionAdapter(this));

lbPrice1.setBorder(BorderFactory.createLoweredBevelBorder());

lbPrice1.setHorizontalAlignment(SwingConstants.RIGHT);

lbPrice1.setText("0.00");

lbPrice1.setBounds(new Rectangle(358, 259, 75, 25));

lbPrice2.setBorder(BorderFactory.createLoweredBevelBorder());

lbPrice2.setHorizontalAlignment(SwingConstants.RIGHT);

lbPrice2.setText("0.00");

lbPrice2.setBounds(new Rectangle(358, 284, 75, 25));

cbQty2.setBounds(new Rectangle(6, 284, 50, 25));

cbQty2.addActionListener(new clientFrame_cbQty2_actionAdapter(this));

lbExtend2.setBorder(BorderFactory.createLoweredBevelBorder());

lbExtend2.setHorizontalAlignment(SwingConstants.RIGHT);

lbExtend2.setText("0.00");

lbExtend2.setBounds(new Rectangle(433, 284, 75, 25));

cbItem2.setBounds(new Rectangle(57, 284, 301, 25));

cbItem2.addActionListener(new clientFrame_cbItem2_actionAdapter(this));

cbItem3.setBounds(new Rectangle(57, 309, 301, 25));

cbItem3.addActionListener(new clientFrame_cbItem3_actionAdapter(this));

cbQty3.setBounds(new Rectangle(6, 309, 50, 25));

cbQty3.addActionListener(new clientFrame_cbQty3_actionAdapter(this));

lbPrice3.setBorder(BorderFactory.createLoweredBevelBorder());

lbPrice3.setHorizontalAlignment(SwingConstants.RIGHT);

lbPrice3.setText("0.00");

lbPrice3.setBounds(new Rectangle(358, 309, 75, 25));

lbExtend3.setBorder(BorderFactory.createLoweredBevelBorder());

lbExtend3.setHorizontalAlignment(SwingConstants.RIGHT);

lbExtend3.setText("0.00");

lbExtend3.setBounds(new Rectangle(433, 309, 75, 25));

lbExtend4.setBorder(BorderFactory.createLoweredBevelBorder());

lbExtend4.setHorizontalAlignment(SwingConstants.RIGHT);

lbExtend4.setText("0.00");

lbExtend4.setBounds(new Rectangle(433, 334, 75, 25));

cbQty4.setDoubleBuffered(false);

cbQty4.setSelectedIndex(-1);

cbQty4.setBounds(new Rectangle(6, 334, 50, 25));

cbQty4.addActionListener(new clientFrame_cbQty4_actionAdapter(this));

cbItem4.setBounds(new Rectangle(57, 334, 301, 25));

cbItem4.addActionListener(new clientFrame_cbItem4_actionAdapter(this));

lbPrice4.setBorder(BorderFactory.createLoweredBevelBorder());

lbPrice4.setHorizontalAlignment(SwingConstants.RIGHT);

lbPrice4.setText ("0.00");

lbPrice4.setBounds(new Rectangle(358, 334, 75, 25));

lbQty.setBorder(BorderFactory.createEtchedBorder());

lbQty.setHorizontalAlignment(SwingConstants.CENTER);

lbQty.setText("Qty");

lbQty.setBounds(new Rectangle(6, 204, 50, 26));

lbItem.setBorder(BorderFactory.createEtchedBorder());

lbItem.setHorizontalAlignment(SwingConstants.CENTER);

lbItem.setText("Item");

lbItem.setBounds(new Rectangle(57, 204, 301, 26));

lbPrice.setBorder(BorderFactory.createEtchedBorder());

lbPrice.setHorizontalAlignment(SwingConstants.CENTER);

lbPrice.setText("Price");

lbPrice.setBounds(new Rectangle(358, 204, 75, 26));

lbExtend.setBorder(BorderFactory.createEtchedBorder());

lbExtend.setHorizontalAlignment(SwingConstants.CENTER);

lbExtend.setText("Extend");

lbExtend.setBounds(new Rectangle(433, 204, 75, 26));

lbTotalNum.setBorder(BorderFactory.createLoweredBevelBorder());

lbTotalNum.setHorizontalAlignment(SwingConstants.RIGHT);

lbTotalNum.setBounds(new Rectangle(433, 432, 75, 25));

lbSubTotalNum.setBorder(BorderFactory.createLoweredBevelBorder());

lbSubTotalNum.setHorizontalAlignment(SwingConstants.RIGHT);

lbSubTotalNum.setBounds(new Rectangle(433, 380, 75, 25));

lbTaxNum.setBorder(BorderFactory.createLoweredBevelBorder());

lbTaxNum.setHorizontalAlignment(SwingConstants.RIGHT);

lbTaxNum.setBounds(new Rectangle(433, 406, 75, 25));

lbTax.setBorder(BorderFactory.createLoweredBevelBorder());

lbTax.setHorizontalAlignment(SwingConstants.LEFT);

lbTax.setText("Tax");

lbTax.setBounds(new Rectangle(333, 406, 100, 25));

lbTotal.setBorder(BorderFactory.createLoweredBevelBorder());

lbTotal.setText("Total");

lbTotal.setBounds(new Rectangle(333, 432, 100, 25));

lbSubTotal.setBorder(BorderFactory.createLoweredBevelBorder());

lbSubTotal.setText("Sub-Total");

lbSubTotal.setBounds(new Rectangle(333, 380, 100, 25));

cbQty0.setMinimumSize(new Dimension(30, 24));

cbQty0.setOpaque(true);

cbQty0.setPreferredSize(new Dimension(30, 24));

cbQty0.setRequestFocusEnabled(false);

cbQty0.setToolTipText("");

cbQty0.setEditable(false);

cbQty0.setEditor(null);

cbQty0.setBounds(new Rectangle(6, 233, 50, 25));

cbQty0.addActionListener(new clientFrame_cbQty0_actionAdapter(this));

butSubmit.setBounds(new Rectangle(6, 3, 245, 19));

butSubmit.setText("Submit Invoice");

butSubmit.addActionListener(new clientFrame_butSubmit_actionAdapter(this));

butClear.setBounds(new Rectangle(263, 3, 245, 19));

butClear.setText("Clear Invoice");

butClear.addActionListener(new clientFrame_butClear_actionAdapter(this));

report.setLayout(null);

butGetReport.setBounds(new Rectangle(11, 10, 493, 23));

butGetReport.setActionCommand("jButton4");

butGetReport.setText("Get Report");

butGetReport.addActionListener

(new clientFrame_butGetReport_actionAdapter(this));

taReport.setBorder(BorderFactory.createLoweredBevelBorder());

taReport.setTabSize(5);

taReport.setBounds(new Rectangle(11, 42, 493, 491));

// place widgets on ui

jToolBar.add(jButton1);

jToolBar.add(jButton2);

jToolBar.add(jButton3);

contentPane.add(statusBar,

new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0,

GridBagConstraints.SOUTH,

GridBagConstraints.HORIZONTAL,

new Insets(0, 0, 0, 0),

0, 0));

jMenuFile.add(jMenuFileExit);

jMenuHelp.add(jMenuHelpAbout);

jMenuBar1.add(jMenuFile);

jMenuBar1.add(jMenuHelp);

this.setJMenuBar(jMenuBar1);

contentPane.add(jToolBar,

new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0,

GridBagConstraints.NORTH,

GridBagConstraints.HORIZONTAL,

new Insets(0, 0, 0, 0),

0, 0));

contentPane.add(jTabbedPane1,

new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,

GridBagConstraints.CENTER,

GridBagConstraints.BOTH,

new Insets(0, 0, 0, 0),

0, 0));

jTabbedPane1.add(invoice, "invoice");

jTabbedPane1.add(report, "Report");

jTabbedPane1.add(textPad, "Text Pad");

invoice.add(addPanel, null);

invoice.add(tfShipName, null);

invoice.add(lbBillName, null);

invoice.add(tfBillName, null);

invoice.add(lbShipName, null);

invoice.add(tfShipAddress, null);

invoice.add(lbBillAddress, null);

invoice.add(lbShipAddress, null);

invoice.add(tfBillAddress, null);

invoice.add(tfShipCity, null);

invoice.add(lbShipCity, null);

invoice.add(tfBillCity, null);

invoice.add(lbBillCity, null);

invoice.add(tfBillState, null);

invoice.add(lbShipState, null);

invoice.add(lbBillState, null);

invoice.add(tfShipState, null);

invoice.add(tfShipZip, null);

invoice.add(lbBillZip, null);

invoice.add(tfBillZip, null);

invoice.add(lbShipZip, null);

invoice.add(lbShipInfo, null);

invoice.add(lbBillInfo, null);

invoice.add(lbExtend0, null);

invoice.add(cbItem0, null);

invoice.add(lbPrice0, null);

invoice.add(lbExtend1, null);

invoice.add(cbQty1, null);

invoice.add(cbItem1, null);

invoice.add(lbPrice1, null);

invoice.add(lbPrice2, null);

invoice.add(cbQty2, null);

invoice.add(lbExtend2, null);

invoice.add(cbItem2, null);

invoice.add(cbItem3, null);

invoice.add(cbQty3, null);

invoice.add(lbPrice3, null);

invoice.add(lbExtend3, null);

invoice.add(lbExtend4, null);

invoice.add(cbQty4, null);

invoice.add(cbItem4, null);

invoice.add(lbPrice4, null);

invoice.add(lbItem, null);

invoice.add(lbPrice, null);

invoice.add(lbExtend, null);

invoice.add(lbQty, null);

invoice.add(lbSubTotal, null);

invoice.add(lbSubTotalNum, null);

invoice.add(lbTaxNum, null);

invoice.add(lbTax, null);

invoice.add(cbQty0, null);

invoice.add(butSubmit, null);

invoice.add(butClear, null);

invoice.add(lbTotalNum, null);

invoice.add(lbTotal, null);

report.add(butGetReport, null);

report.add(taReport, null);

// set default values in widgets

createQtyCB(cbQty0);

createQtyCB(cbQty1);

createQtyCB(cbQty2);

createQtyCB(cbQty3);

createQtyCB(cbQty4);

createItemCB(cbItem0);

createItemCB(cbItem1);

createItemCB(cbItem2);

createItemCB(cbItem3);

createItemCB(cbItem4);

lbSubTotalNum.setText("0.00");

lbTaxNum.setText("0.00");

lbTotalNum.setText(new DecimalFormat("#######0.00").format(0.00));

}

/*

* function: createQtyCB

* description: set default values for quantity combo boxes

* inputs: JComboBox cbQty, quantity combo box

* outputs: none

* return value: none

*/

public void createQtyCB(JComboBox cbQty)

{

cbQty.addItem ("");

cbQty.addItem ("1");

cbQty.addItem ("2");

cbQty.addItem ("3");

cbQty.addItem ("4");

cbQty.addItem ("5");

cbQty.addItem ("6");

cbQty.addItem ("7");

cbQty.addItem ("8");

cbQty.addItem ("9");

cbQty.addItem ("10");

}

/*

* function: createItemCB

* description: set default values for item combo boxes

* inputs: JComboBox cbItem, item combo box

* outputs: none

* return value: none

*/

public void createItemCB(JComboBox cbItem)

{

cbItem.addItem("");

cbItem.addItem("CPU");

cbItem.addItem("Keyboard");

cbItem.addItem("Memory");

cbItem.addItem("Monitor");

}

/*

* function: jMenuFileExit_actionPerformed

* description: file/exit action performed

* inputs: none

* outputs: none

* return value: none

*/

public void jMenuFileExit_actionPerformed(ActionEvent e)

{

System.exit(0);

}

/*

* function: jMenuhelpAbout_actionPerformed

* description: help/about action performed

* inputs: none

* outputs: none

* return value: none

*/

public void jMenuHelpAbout_actionPerformed(ActionEvent e)

{

clientFrame_AboutBox dlg = new clientFrame_AboutBox(this);

Dimension dlgSize = dlg.getPreferredSize();

Dimension frmSize = getSize();

Point loc = getLocation();

dlg.setLocation((frmSize.width - dlgSize.width) / 2 +

loc.x, (frmSize.height - dlgSize.height) / 2 + loc.y);

dlg.setModal(true);

dlg.pack();

dlg.show();

}

/*

* function: processWindowEvent

* description: overridden method to exit when window is closed

* inputs: WindowEvent e, window event

* outputs: none

* return value: none

*/

protected void processWindowEvent(WindowEvent e)

{

super.processWindowEvent(e);

if (e.getID() == WindowEvent.WINDOW_CLOSING)

{

jMenuFileExit_actionPerformed(null);

}

}

/*

* function: butClear_actionPerformed

* description: button event to clear widgets in ui

* inputs: ActionEvent e, action event

* outputs: none

* return value: none

*/

void butClear_actionPerformed(ActionEvent e)

{

tfBillName.setText("");

tfBillAddress.setText("");

tfBillCity.setText("");

tfBillState.setText("");

tfBillZip.setText("");

tfShipName.setText("");

tfShipAddress.setText("");

tfShipCity.setText("");

tfShipState.setText("");

tfShipZip.setText("");

cbQty0.setSelectedItem("");

cbQty1.setSelectedItem("");

cbQty2.setSelectedItem("");

cbQty3.setSelectedItem("");

cbQty4.setSelectedItem("");

cbItem0.setSelectedItem("");

cbItem1.setSelectedItem("");

cbItem2.setSelectedItem("");

cbItem3.setSelectedItem("");

cbItem4.setSelectedItem("");

statusBar.setText(" ");

}

/*

* function: tfShipName_actionPerformed

* description: text field action performed

* inputs: ActionEvent e, action event

* outputs: none

* return value: none

*/

void tfShipName_actionPerformed(ActionEvent e)

{

}

/*

* function: tfShipZip_actionPerformed

* description: text field action performed

* inputs: ActionEvent e, action event

* outputs: none

* return value: none

*/

void tfShipZip_actionPerformed(ActionEvent e)

{

}

/*

* function: updatePrice

* description: update prices based on cbItem# selection. if a quantity

* is not chosen, prices are set by item chosen; else, price

* and extend price are both set.

* inputs: JComboBox cbQty, quantity combo box

* JComboBox cbItem, item combo box

* JLabel lbPrice, price label

* JLabel lbExtended, extended price label

* outputs: none

* return value: none

*/

public void updatePrice (JComboBox cbQty,

JComboBox cbItem,

JLabel lbPrice,

JLabel lbExtend)

{

Object objItem = cbItem.getSelectedItem ();

String strItem = objItem.toString ();

Object objQty = cbQty.getSelectedItem ();

String strQty = objQty.toString();

if (strQty.equals(""))

{

if (strItem.equals(""))

lbPrice.setText("0.00");

if (strItem.equals("CPU"))

lbPrice.setText("299.00");

if (strItem.equals("Keyboard"))

lbPrice.setText("59.00");

if (strItem.equals("Memory"))

lbPrice.setText("129.00");

if (strItem.equals("Monitor"))

lbPrice.setText("359.00");

}

else

{

if (strItem.equals(""))

{

lbPrice.setText("0.00");

lbExtend.setText("0.00");

}

if (strItem.equals("CPU"))

{

lbPrice.setText("299.00");

lbExtend.setText

(new DecimalFormat("#######0.00").format(Float.parseFloat(strQty) *

Float.parseFloat(lbPrice.getText())));

}

if (strItem.equals("Keyboard"))

{

lbPrice.setText("59.00");

lbExtend.setText

(new DecimalFormat("#######0.00").format(Float.parseFloat(strQty) *

Float.parseFloat(lbPrice.getText())));

}

if (strItem.equals("Memory"))

{

lbPrice.setText("129.00");

lbExtend.setText

(new DecimalFormat("#######0.00").format(Float.parseFloat(strQty) *

Float.parseFloat(lbPrice.getText())));

}

if (strItem.equals("Monitor"))

{

lbPrice.setText("359.00");

lbExtend.setText

(new DecimalFormat("#######0.00").format(Float.parseFloat(strQty) *

Float.parseFloat(lbPrice.getText())));

}

}

}

/*

* function: updateTotals

* description: update total fields

* inputs:

* outputs: none

* return value: none

*/

public void updateTotals()

{

float sub0 = Float.parseFloat(lbExtend0.getText());

float sub1 = Float.parseFloat(lbExtend1.getText());

float sub2 = Float.parseFloat(lbExtend2.getText());

float sub3 = Float.parseFloat(lbExtend3.getText());

float sub4 = Float.parseFloat(lbExtend4.getText());

float subtotal = sub0 + sub1 + sub2 + sub3 + sub4;

lbSubTotalNum.setText(new DecimalFormat("#######0.00").format(subtotal));

float tax_rate = 0.0775f;

float tax = subtotal * tax_rate;

lbTaxNum.setText(new DecimalFormat("#######0.00").format(tax));

lbTotalNum.setText(new DecimalFormat("#######0.00").format(subtotal + tax));

}

/*

* function: cbItem0_actionPerformed

* description: update the price of item and totals

* inputs:

* outputs: none

* return value: none

*/

void cbItem0_actionPerformed(ActionEvent e)

{

updatePrice(cbQty0, cbItem0, lbPrice0, lbExtend0);

updateTotals ();

}

/*

* function: cbItem1_actionPerformed

* description: update the price of item and totals

* inputs:

* outputs: none

* return value: none

*/

void cbItem1_actionPerformed(ActionEvent e)

{

updatePrice(cbQty1, cbItem1, lbPrice1, lbExtend1);

updateTotals ();

}

/*

* function: cbItem2_actionPerformed

* description: update the price of item and totals

* inputs:

* outputs: none

* return value: none

*/

void cbItem2_actionPerformed(ActionEvent e)

{

updatePrice(cbQty2, cbItem2, lbPrice2, lbExtend2);

updateTotals ();

}

/*

* function: cbItem3_actionPerformed

* description: update the price of item and totals

* inputs:

* outputs: none

* return value: none

*/

void cbItem3_actionPerformed(ActionEvent e)

{

updatePrice(cbQty3, cbItem3, lbPrice3, lbExtend3);

updateTotals ();

}

/*

* function: cbItem4_actionPerformed

* description: update the price of item and totals

* inputs:

* outputs: none

* return value: none

*/

void cbItem4_actionPerformed(ActionEvent e)

{

updatePrice(cbQty4, cbItem4, lbPrice4, lbExtend4);

updateTotals ();

}

/*

* function: updateQty

* description: update prices based on cbQty# selection. if a quantity

* is not chosen, extended prices are set to 0; else, prices

* are set.

* inputs: JComboBox cbQty, quantity combo box

* JComboBox cbItem, item combo box

* JLabel lbPrice, price label

* JLabel lbExtended, extended price label

* outputs: none

* return value: none

*/

public void updateQty (JComboBox cbQty, JComboBox cbItem, JLabel lbPrice, JLabel lbExtend)

{

Object objQty = cbQty.getSelectedItem();

String strQty = objQty.toString();

if (strQty.equals(""))

{

lbExtend.setText("0.00");

}

else

{

Object objItem = cbItem.getSelectedItem();

String strItem = objItem.toString();

if (strItem.equals("")) {

lbPrice.setText("0.00");

lbExtend.setText("0.00");

}

if (strItem.equals("CPU"))

{

lbPrice.setText("299.00");

lbExtend.setText

(new DecimalFormat("#######0.00").format(Float.parseFloat(strQty) *

Float.parseFloat(lbPrice.getText())));

}

if (strItem.equals("Keyboard"))

{

lbPrice.setText("59.00");

lbExtend.setText

(new DecimalFormat("#######0.00").format(Float.parseFloat(strQty) *

Float.parseFloat(lbPrice.getText())));

}

if (strItem.equals("Memory"))

{

lbPrice.setText("129.00");

lbExtend.setText

(new DecimalFormat("#######0.00").format(Float.parseFloat(strQty) *

Float.parseFloat(lbPrice.getText())));

}

if (strItem.equals("Monitor"))

{

lbPrice.setText("359.00");

lbExtend.setText

(new DecimalFormat("#######0.00").format(Float.parseFloat(strQty) *

Float.parseFloat(lbPrice.getText())));

}

}

}

/*

* function: cbQty0_actionPerformed

* description: update the price of item and totals

* inputs: ActionEvent e, action event

* outputs: none

* return value: none

*/

void cbQty0_actionPerformed(ActionEvent e)

{

updateQty(cbQty0, cbItem0, lbPrice0, lbExtend0);

updateTotals();

}

/*

* function: cbQty1_actionPerformed

* description: update the price of item and totals

* inputs: ActionEvent e, action event

* outputs: none

* return value: none

*/

void cbQty1_actionPerformed(ActionEvent e)

{

updateQty(cbQty1, cbItem1, lbPrice1, lbExtend1);

updateTotals();

}

/*

* function: cbQty2_actionPerformed

* description: update the price of item and totals

* inputs: ActionEvent e, action event

* outputs: none

* return value: none

*/

void cbQty2_actionPerformed(ActionEvent e)

{

updateQty(cbQty2, cbItem2, lbPrice2, lbExtend2);

updateTotals();

}

/*

* function: cbQty3_actionPerformed

* description: update the price of item and totals

* inputs: ActionEvent e, action event

* outputs: none

* return value: none

*/

void cbQty3_actionPerformed(ActionEvent e)

{

updateQty(cbQty3, cbItem3, lbPrice3, lbExtend3);

updateTotals();

}

/*

* function: cbQty4_actionPerformed

* description: update the price of item and totals

* inputs: ActionEvent e, action event

* outputs: none

* return value: none

*/

void cbQty4_actionPerformed(ActionEvent e)

{

updateQty(cbQty4, cbItem4, lbPrice4, lbExtend4);

updateTotals();

}

/*

* function: create_message

* description: generate and return a blowfish encrypted message

* inputs: byte[] temp_buf, message in clear text

* int n_MessSize, size of temp_buf

* outputs: none

* return value: byte[], blowfish encrypted message

*/

public byte[] create_message (byte[] temp_buf, int n_MessSize)

{

int nRest;

// align to the next 8 byte border

byte[] messbuf;

nRest = n_MessSize & 7;

if (nRest != 0)

{

messbuf = new byte[(n_MessSize & (~7)) + 8];

System.arraycopy(temp_buf, 0, messbuf, 0, n_MessSize);

for (int nI = n_MessSize; nI < messbuf.length ; nI++)

messbuf[nI] = 0x20;

System.out.println("message with " + n_MessSize + " bytes aligned to " +

messbuf.length + " bytes");

}

else

{

messbuf = new byte[n_MessSize];

System.arraycopy(temp_buf, 0, messbuf, 0, n_MessSize);

}

return (messbuf);

}

/*

* function: butSubmit_actionPerformed

* description: encrypts invoice form data and package the encrypted data

* into an invoice object. each item in the invoice form is

* encrypted using blowfish and inserted into an invoice

* object. the data is send to the front end server 1 to

* be forwarded to the next available database server. if

* front end server 1 is not available, front end server 2

* is called. if neither front end servers are available,

* an error is output to standard output.

* inputs: ActionEvent e, action event

* outputs: none

* return value: none

*/

void butSubmit_actionPerformed(ActionEvent e)

{

boolean blContinue = true;

int i;

byte[] byteKey = new byte[20];

invoice objInvoice = new invoice();

String strFrontEndSvrLoc = "rmi://127.0.0.1:6979/frontEndSvr";

BlowfishECB bfecb = new BlowfishECB(byteSecretKey);

// package and encrypt invoice form data

try

{

objInvoice.byteBillName = tfBillName.getText().getBytes("UTF8");

objInvoice.byteBillName =

create_message(objInvoice.byteBillName,

tfBillName.getText().length());

bfecb.encrypt(objInvoice.byteBillName);

objInvoice.byteBillAddress = tfBillAddress.getText().getBytes("UTF8");

objInvoice.byteBillAddress =

create_message(objInvoice.byteBillAddress,

tfBillAddress.getText().length());

bfecb.encrypt(objInvoice.byteBillAddress);

objInvoice.byteBillCity = tfBillCity.getText().getBytes("UTF8");

objInvoice.byteBillCity =

create_message(objInvoice.byteBillCity,

tfBillCity.getText().length());

bfecb.encrypt(objInvoice.byteBillCity);

objInvoice.byteBillState = tfBillState.getText().getBytes("UTF8");

objInvoice.byteBillState =

create_message(objInvoice.byteBillState,

tfBillState.getText().length());

bfecb.encrypt(objInvoice.byteBillState);

objInvoice.byteBillZip = tfBillZip.getText().getBytes("UTF8");

objInvoice.byteBillZip =

create_message(objInvoice.byteBillZip,

tfBillZip.getText().length());

bfecb.encrypt(objInvoice.byteBillZip);

objInvoice.byteShipName = tfShipName.getText().getBytes("UTF8");

objInvoice.byteShipName =

create_message(objInvoice.byteShipName,

tfShipName.getText().length());

bfecb.encrypt(objInvoice.byteShipName);

objInvoice.byteShipAddress = tfShipAddress.getText().getBytes("UTF8");

objInvoice.byteShipAddress =

create_message(objInvoice.byteShipAddress,

tfShipAddress.getText().length());

bfecb.encrypt(objInvoice.byteShipAddress);

objInvoice.byteShipCity = tfShipCity.getText().getBytes("UTF8");

objInvoice.byteShipCity =

create_message(objInvoice.byteShipCity,

tfShipCity.getText().length());

bfecb.encrypt(objInvoice.byteShipCity);

objInvoice.byteShipState = tfShipState.getText().getBytes("UTF8");

objInvoice.byteShipState =

create_message(objInvoice.byteShipState,

tfShipState.getText().length());

bfecb.encrypt(objInvoice.byteShipState);

objInvoice.byteShipZip = tfShipZip.getText().getBytes("UTF8");

objInvoice.byteShipZip =

create_message(objInvoice.byteShipZip,

tfShipZip.getText().length());

bfecb.encrypt(objInvoice.byteShipZip);

objInvoice.byteQty0 =

cbQty0.getSelectedItem().toString().getBytes("UTF8");

objInvoice.byteQty0 =

create_message(objInvoice.byteQty0,

cbQty0.getSelectedItem().toString().length());

bfecb.encrypt(objInvoice.byteQty0);

objInvoice.byteItem0 =

cbItem0.getSelectedItem().toString().getBytes("UTF8");

objInvoice.byteItem0 =

create_message(objInvoice.byteItem0,

cbItem0.getSelectedItem().toString().length());

bfecb.encrypt(objInvoice.byteItem0);

objInvoice.bytePrice0 = lbPrice0.getText().getBytes("UTF8");

objInvoice.bytePrice0 =

create_message(objInvoice.bytePrice0,

lbPrice0.getText().length());

bfecb.encrypt(objInvoice.bytePrice0);

objInvoice.byteExtend0 = lbExtend0.getText().getBytes("UTF8");

objInvoice.byteExtend0 =

create_message(objInvoice.byteExtend0,

lbExtend0.getText().length());

bfecb.encrypt(objInvoice.byteExtend0);

objInvoice.byteQty1 =

cbQty1.getSelectedItem().toString().getBytes("UTF8");

objInvoice.byteQty1 =

create_message(objInvoice.byteQty1,

cbQty1.getSelectedItem().toString().length());

bfecb.encrypt(objInvoice.byteQty1);

objInvoice.byteItem1 =

cbItem1.getSelectedItem().toString().getBytes("UTF8");

objInvoice.byteItem1 =

create_message(objInvoice.byteItem1,

cbItem1.getSelectedItem().toString().length());

bfecb.encrypt(objInvoice.byteItem1);

objInvoice.bytePrice1 = lbPrice1.getText().getBytes("UTF8");

objInvoice.bytePrice1 =

create_message(objInvoice.bytePrice1,

lbPrice1.getText().length());

bfecb.encrypt(objInvoice.bytePrice1);

objInvoice.byteExtend1 = lbExtend1.getText().getBytes("UTF8");

objInvoice.byteExtend1 =

create_message(objInvoice.byteExtend1,

lbExtend1.getText().length());

bfecb.encrypt(objInvoice.byteExtend1);

objInvoice.byteQty2 =

cbQty2.getSelectedItem().toString().getBytes("UTF8");

objInvoice.byteQty2 =

create_message(objInvoice.byteQty2,

cbQty2.getSelectedItem().toString().length());

bfecb.encrypt(objInvoice.byteQty2);

objInvoice.byteItem2 =

cbItem2.getSelectedItem().toString().getBytes("UTF8");

objInvoice.byteItem2 =

create_message(objInvoice.byteItem2,

cbItem2.getSelectedItem().toString().length());

bfecb.encrypt(objInvoice.byteItem2);

objInvoice.bytePrice2 = lbPrice2.getText().getBytes("UTF8");

objInvoice.bytePrice2 =

create_message(objInvoice.bytePrice2, lbPrice2.getText().length());

bfecb.encrypt(objInvoice.bytePrice2);

objInvoice.byteExtend2 = lbExtend2.getText().getBytes("UTF8");

objInvoice.byteExtend2 =

create_message(objInvoice.byteExtend2, lbExtend2.getText().length());

bfecb.encrypt(objInvoice.byteExtend2);

objInvoice.byteQty3 =

cbQty3.getSelectedItem().toString().getBytes("UTF8");

objInvoice.byteQty3 =

create_message(objInvoice.byteQty3,

cbQty3.getSelectedItem().toString().length());

bfecb.encrypt(objInvoice.byteQty3);

objInvoice.byteItem3 =

cbItem3.getSelectedItem().toString().getBytes("UTF8");

objInvoice.byteItem3 =

create_message(objInvoice.byteItem3,

cbItem3.getSelectedItem().toString().length());

bfecb.encrypt(objInvoice.byteItem3);

objInvoice.bytePrice3 = lbPrice3.getText().getBytes("UTF8");

objInvoice.bytePrice3 =

create_message(objInvoice.bytePrice3,

lbPrice3.getText().length());

bfecb.encrypt(objInvoice.bytePrice3);

objInvoice.byteExtend3 = lbExtend3.getText().getBytes("UTF8");

objInvoice.byteExtend3 =

create_message(objInvoice.byteExtend3, lbExtend3.getText().length());

bfecb.encrypt(objInvoice.byteExtend3);

objInvoice.byteQty4 =

cbQty4.getSelectedItem().toString().getBytes("UTF8");

objInvoice.byteQty4 =

create_message(objInvoice.byteQty4,

cbQty4.getSelectedItem().toString().length());

bfecb.encrypt(objInvoice.byteQty4);

objInvoice.byteItem4 =

cbItem4.getSelectedItem().toString().getBytes("UTF8");

objInvoice.byteItem4 =

create_message(objInvoice.byteItem4,

cbItem4.getSelectedItem().toString().length());

bfecb.encrypt(objInvoice.byteItem4);

objInvoice.bytePrice4 = lbPrice4.getText().getBytes("UTF8");

objInvoice.bytePrice4 =

create_message(objInvoice.bytePrice4, lbPrice4.getText().length());

bfecb.encrypt(objInvoice.bytePrice4);

objInvoice.byteExtend4 = lbExtend4.getText().getBytes("UTF8");

objInvoice.byteExtend4 =

create_message(objInvoice.byteExtend4, lbExtend4.getText().length());

bfecb.encrypt(objInvoice.byteExtend4);

objInvoice.byteSubTotal = lbSubTotalNum.getText().getBytes("UTF8");

objInvoice.byteSubTotal =

create_message(objInvoice.byteSubTotal,

lbSubTotalNum.getText().length());

bfecb.encrypt(objInvoice.byteSubTotal);

objInvoice.byteTax = lbTaxNum.getText().getBytes("UTF8");

objInvoice.byteTax =

create_message(objInvoice.byteTax, lbTaxNum.getText().length());

bfecb.encrypt(objInvoice.byteTax);

objInvoice.byteTotal = lbTotalNum.getText().getBytes("UTF8");

objInvoice.byteTotal =

create_message(objInvoice.byteTotal, lbTotalNum.getText().length());

bfecb.encrypt(objInvoice.byteTotal);

}

catch (Exception except)

{

System.out.println("butSubmit encrypt error: " + except.getMessage());

}

// contact front end server to send data

while (blContinue)

{

try

{

objFrontEndSvr =

(frontEndSvrInterface) Naming.lookup(strFrontEndSvrLoc);

objFrontEndSvr.submitInvoiceToFrontEndSvr(objInvoice);

statusBar.setText("Invoice submission successful.");

blContinue = false;

}

catch (Exception except)

{

if (strFrontEndSvrLoc.equals("rmi://127.0.0.1:6979/frontEndSvr"))

{

strFrontEndSvrLoc = "rmi://127.0.0.1:6980/frontEndSvr";

}

else

{

statusBar.setText ("Invoice submission failed.");

blContinue = false;

}

}

}

// clear invoice form

tfBillName.setText("");

tfBillAddress.setText("");

tfBillCity.setText("");

tfBillState.setText("");

tfBillZip.setText("");

tfShipName.setText("");

tfShipAddress.setText("");

tfShipCity.setText("");

tfShipState.setText("");

tfShipZip.setText("");

cbQty0.setSelectedItem("");

cbQty1.setSelectedItem("");

cbQty2.setSelectedItem("");

cbQty3.setSelectedItem("");

cbQty4.setSelectedItem("");

cbItem0.setSelectedItem("");

cbItem1.setSelectedItem("");

cbItem2.setSelectedItem("");

cbItem3.setSelectedItem("");

cbItem4.setSelectedItem("");

}

/*

* function: butGetReport_actionPerformed

* description: contact front end server to extract a summary report.

* if front end server 1 is not available, front end server 2

* will be contacted. if neither servers are available,

* an error message will be output to standard output.

* the summary report will arrive in a blowfish encrypted

* format. the report will be decrypted and output to the

* client ui.

* inputs: ActionEvent e, action event

* outputs: none

* return value: none

*/

void butGetReport_actionPerformed(ActionEvent e)

{

boolean blContinue = true;

String strTemp;

int i;

report objReport = null;

byte[] byteKey = new byte[20];

String strFrontEndSvrLoc = "rmi://127.0.0.1:6979/frontEndSvr";

BlowfishECB bfecb = new BlowfishECB(byteSecretKey);

while (blContinue)

{

try

{

System.out.println("getReport has been called.");

// contact front end server

objFrontEndSvr =

(frontEndSvrInterface) Naming.lookup(strFrontEndSvrLoc);

objEncReport = objFrontEndSvr.getReport();

objReport = new report();

// blowfish decrypt data message

bfecb.decrypt(objEncReport.byteCpuQty);

strTemp = new String(objEncReport.byteCpuQty, "UTF8");

strTemp = strTemp.trim();

objReport.intCpuQty = Integer.parseInt(strTemp);

bfecb.decrypt(objEncReport.byteCpuPrice);

strTemp = new String(objEncReport.byteCpuPrice, "UTF8");

strTemp = strTemp.trim();

objReport.fltCpuPrice = Float.parseFloat(strTemp);

bfecb.decrypt(objEncReport.byteCpuExtend);

strTemp = new String(objEncReport.byteCpuExtend, "UTF8");

strTemp = strTemp.trim();

objReport.fltCpuExtend = Float.parseFloat(strTemp);

bfecb.decrypt(objEncReport.byteKbQty);

strTemp = new String(objEncReport.byteKbQty, "UTF8");

strTemp = strTemp.trim();

objReport.intKbQty = Integer.parseInt(strTemp);

bfecb.decrypt(objEncReport.byteKbPrice);

strTemp = new String(objEncReport.byteKbPrice, "UTF8");

strTemp = strTemp.trim();

objReport.fltKbPrice = Float.parseFloat(strTemp);

bfecb.decrypt(objEncReport.byteKbExtend);

strTemp = new String(objEncReport.byteKbExtend, "UTF8");

strTemp = strTemp.trim();

objReport.fltKbExtend = Float.parseFloat(strTemp);

bfecb.decrypt(objEncReport.byteMemQty);

strTemp = new String(objEncReport.byteMemQty, "UTF8");

strTemp = strTemp.trim();

objReport.intMemQty = Integer.parseInt(strTemp);

bfecb.decrypt(objEncReport.byteMemPrice);

strTemp = new String(objEncReport.byteMemPrice, "UTF8");

strTemp = strTemp.trim();

objReport.fltMemPrice = Float.parseFloat(strTemp);

bfecb.decrypt(objEncReport.byteMemExtend);

strTemp = new String(objEncReport.byteMemExtend, "UTF8");

strTemp = strTemp.trim();

objReport.fltMemExtend = Float.parseFloat(strTemp);

bfecb.decrypt(objEncReport.byteMonitorQty);

strTemp = new String(objEncReport.byteMonitorQty, "UTF8");

strTemp = strTemp.trim();

objReport.intMonitorQty = Integer.parseInt(strTemp);

bfecb.decrypt(objEncReport.byteMonitorPrice);

strTemp = new String(objEncReport.byteMonitorPrice, "UTF8");

strTemp = strTemp.trim();

objReport.fltMonitorPrice = Float.parseFloat(strTemp);

bfecb.decrypt(objEncReport.byteMonitorExtend);

strTemp = new String(objEncReport.byteMonitorExtend, "UTF8");

strTemp = strTemp.trim();

objReport.fltMonitorExtend = Float.parseFloat(strTemp);

bfecb.decrypt(objEncReport.byteSubTotal);

strTemp = new String(objEncReport.byteSubTotal);

strTemp = strTemp.trim();

objReport.fltSubTotal = Float.parseFloat(strTemp);

bfecb.decrypt(objEncReport.byteTax);

strTemp = new String(objEncReport.byteTax);

strTemp = strTemp.trim();

objReport.fltTax = Float.parseFloat(strTemp);

bfecb.decrypt(objEncReport.byteTotal);

strTemp = new String(objEncReport.byteTotal);

strTemp = strTemp.trim();

objReport.fltTotal = Float.parseFloat(strTemp);

blContinue = false;

}

// contacting front end server has failed. try front end server 2.

// if neither server are available, output error to standard output.

catch (Exception except) {

if (strFrontEndSvrLoc.equals("rmi://127.0.0.1:6979/frontEndSvr")) {

strFrontEndSvrLoc = "rmi://127.0.0.1:6980/frontEndSvr";

}

else {

System.out.println("getReport call has failed.");

blContinue = false;

}

}

}

// output summary report

if (objReport != null)

{

String strReport = new String();

strReport = "Sales Summary Report\n\n";

strReport = strReport + "Qty, Item, Price, Extend\n\n";

strReport = strReport +

objReport.intCpuQty +

", CPU, " +

new DecimalFormat("#######0.00").format(objReport.fltCpuPrice) +

", " +

new DecimalFormat("#######0.00").format(objReport.fltCpuExtend) +

"\n";

strReport = strReport +

objReport.intKbQty +

", Keyboard, " +

new DecimalFormat("#######0.00").format(objReport.fltKbPrice) +

", " +

new DecimalFormat("#######0.00").format(objReport.fltKbExtend) +

"\n";

strReport = strReport +

objReport.intMemQty +

", Memory, " +

new DecimalFormat("#######0.00").format(objReport.fltMemPrice) +

", " +

new DecimalFormat("#######0.00").format(objReport.fltMemExtend) +

"\n";

strReport = strReport +

objReport.intMonitorQty +

", Monitor, " +

new DecimalFormat("#######0.00").format(objReport.fltMonitorPrice) +

", " +

new DecimalFormat("#######0.00").format(objReport.fltMonitorExtend) +

"\n\n";

strReport = strReport +

"SubTotal = " +

new DecimalFormat("#######0.00").format(objReport.fltSubTotal) +

"\n";

strReport = strReport +

"Tax = " +

new DecimalFormat("#######0.00").format(objReport.fltTax) +

"\n";

strReport = strReport +

"Total = " +

new DecimalFormat("#######0.00").format(objReport.fltTotal) +

"\n";

taReport.setText(strReport);

statusBar.setText("Report retrieval successful.");

}

else

{

taReport.setText("No report is available");

statusBar.setText("Report retrieval failed.");

}

}

void jButton1_actionPerformed(ActionEvent e) {

}

}

/*

* class: clientFrame_jMenuFileExit_ActionAdapter

* description: file/exit action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_jMenuFileExit_ActionAdapter implements ActionListener

{

clientFrame adaptee;

clientFrame_jMenuFileExit_ActionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.jMenuFileExit_actionPerformed(e);

}

}

/*

* class: clientFrame_jMenuHelpAbout_ActionAdapter

* description: help/about action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_jMenuHelpAbout_ActionAdapter implements ActionListener

{

clientFrame adaptee;

clientFrame_jMenuHelpAbout_ActionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.jMenuHelpAbout_actionPerformed(e);

}

}

/*

* class: clientFrame_butClear_actionAdapter

* description: butClear action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_butClear_actionAdapter

implements java.awt.event.ActionListener

{

clientFrame adaptee;

clientFrame_butClear_actionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.butClear_actionPerformed(e);

}

}

/*

* class: clientFrame_tfShipName_actionAdapter

* description: tfShipName action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_tfShipName_actionAdapter

implements java.awt.event.ActionListener

{

clientFrame adaptee;

clientFrame_tfShipName_actionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.tfShipName_actionPerformed(e);

}

}

/*

* class: clientFrame_tfShipZip_actionAdapter

* description: tfShipZip action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_tfShipZip_actionAdapter

implements java.awt.event.ActionListener

{

clientFrame adaptee;

clientFrame_tfShipZip_actionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.tfShipZip_actionPerformed(e);

}

}

/*

* class: clientFrame_cbItem0_actionAdapter

* description: cbItem0 action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_cbItem0_actionAdapter

implements java.awt.event.ActionListener

{

clientFrame adaptee;

clientFrame_cbItem0_actionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.cbItem0_actionPerformed(e);

}

}

/*

* class: clientFrame_cbItem1_actionAdapter

* description: cbItem1 action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_cbItem1_actionAdapter

implements java.awt.event.ActionListener

{

clientFrame adaptee;

clientFrame_cbItem1_actionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.cbItem1_actionPerformed(e);

}

}

/*

* class: clientFrame_cbItem2_actionAdapter

* description: cbItem2 action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_cbItem2_actionAdapter

implements java.awt.event.ActionListener

{

clientFrame adaptee;

clientFrame_cbItem2_actionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.cbItem2_actionPerformed(e);

}

}

/*

* class: clientFrame_cbItem3_actionAdapter

* description: cbItem3 action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_cbItem3_actionAdapter implements java.awt.event.ActionListener

{

clientFrame adaptee;

clientFrame_cbItem3_actionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.cbItem3_actionPerformed(e);

}

}

/*

* class: clientFrame_cbItem4_actionAdapter

* description: cbItem4 action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_cbItem4_actionAdapter

implements java.awt.event.ActionListener

{

clientFrame adaptee;

clientFrame_cbItem4_actionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.cbItem4_actionPerformed(e);

}

}

/*

* class: clientFrame_cbQty0_actionAdapter

* description: cbQty0 action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_cbQty0_actionAdapter

implements java.awt.event.ActionListener

{

clientFrame adaptee;

clientFrame_cbQty0_actionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.cbQty0_actionPerformed(e);

}

}

/*

* class: clientFrame_cbQty1_actionAdapter

* description: cbQty1 action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_cbQty1_actionAdapter

implements java.awt.event.ActionListener

{

clientFrame adaptee;

clientFrame_cbQty1_actionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.cbQty1_actionPerformed(e);

}

}

/*

* class: clientFrame_cbQty2_actionAdapter

* description: cbQty2 action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_cbQty2_actionAdapter

implements java.awt.event.ActionListener

{

clientFrame adaptee;

clientFrame_cbQty2_actionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.cbQty2_actionPerformed(e);

}

}

/*

* class: clientFrame_cbQty3_actionAdapter

* description: cbQty3 action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_cbQty3_actionAdapter

implements java.awt.event.ActionListener

{

clientFrame adaptee;

clientFrame_cbQty3_actionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.cbQty3_actionPerformed(e);

}

}

/*

* class: clientFrame_cbQty4_actionAdapter

* description: cbQty4 action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_cbQty4_actionAdapter

implements java.awt.event.ActionListener

{

clientFrame adaptee;

clientFrame_cbQty4_actionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.cbQty4_actionPerformed(e);

}

}

/*

* class: clientFrame_butSubmit_actionAdapter

* description: butSubmit action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_butSubmit_actionAdapter

implements java.awt.event.ActionListener

{

clientFrame adaptee;

clientFrame_butSubmit_actionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.butSubmit_actionPerformed(e);

}

}

/*

* class: clientFrame_butGetReport_actionAdapter

* description: butGetReport action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_butGetReport_actionAdapter

implements java.awt.event.ActionListener

{

clientFrame adaptee;

clientFrame_butGetReport_actionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.butGetReport_actionPerformed(e);

}

}

/*

* class: clientFrame_jButton1_actionAdapter

* description: jButton1 action adaptor

* inputs: none

* outputs: none

* return value: none

*/

class clientFrame_jButton1_actionAdapter

implements java.awt.event.ActionListener

{

clientFrame adaptee;

clientFrame_jButton1_actionAdapter(clientFrame adaptee)

{

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e)

{

adaptee.jButton1_actionPerformed(e);

}

}

clientFrame_AboutBox.java

package clientPkg;

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import javax.swing.border.*;

/**

* Title:

* Description:

* Copyright: Copyright (c) 2003

* Company:

* @author not attributable

* @version 1.0

*/

public class clientFrame_AboutBox extends JDialog implements ActionListener {

JPanel panel1 = new JPanel();

JPanel panel2 = new JPanel();

JPanel insetsPanel1 = new JPanel();

JPanel insetsPanel2 = new JPanel();

JPanel insetsPanel3 = new JPanel();

JButton button1 = new JButton();

JLabel imageLabel = new JLabel();

JLabel label1 = new JLabel();

JLabel label2 = new JLabel();

JLabel label3 = new JLabel();

JLabel label4 = new JLabel();

ImageIcon image1 = new ImageIcon();

BorderLayout borderLayout1 = new BorderLayout();

BorderLayout borderLayout2 = new BorderLayout();

FlowLayout flowLayout1 = new FlowLayout();

GridLayout gridLayout1 = new GridLayout();

String product = "";

String version = "1.0";

String copyright = "Copyright (c) 2003";

String comments = "";

public clientFrame_AboutBox(Frame parent) {

super(parent);

enableEvents(AWTEvent.WINDOW_EVENT_MASK);

try {

jbInit();

}

catch(Exception e) {

e.printStackTrace();

}

}

//Component initialization

private void jbInit() throws Exception {

image1 = new ImageIcon(clientPkg.clientFrame.class.getResource("about.png"));

imageLabel.setIcon(image1);

this.setTitle("About");

panel1.setLayout(borderLayout1);

panel2.setLayout(borderLayout2);

insetsPanel1.setLayout(flowLayout1);

insetsPanel2.setLayout(flowLayout1);

insetsPanel2.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

gridLayout1.setRows(4);

gridLayout1.setColumns(1);

label1.setText(product);

label2.setText(version);

label3.setText(copyright);

label4.setText(comments);

insetsPanel3.setLayout(gridLayout1);

insetsPanel3.setBorder(BorderFactory.createEmptyBorder(10, 60, 10, 10));

button1.setText("Ok");

button1.addActionListener(this);

insetsPanel2.add(imageLabel, null);

panel2.add(insetsPanel2, BorderLayout.WEST);

this.getContentPane().add(panel1, null);

insetsPanel3.add(label1, null);

insetsPanel3.add(label2, null);

insetsPanel3.add(label3, null);

insetsPanel3.add(label4, null);

panel2.add(insetsPanel3, BorderLayout.CENTER);

insetsPanel1.add(button1, null);

panel1.add(insetsPanel1, BorderLayout.SOUTH);

panel1.add(panel2, BorderLayout.NORTH);

setResizable(true);

}

//Overridden so we can exit when window is closed

protected void processWindowEvent(WindowEvent e) {

if (e.getID() == WindowEvent.WINDOW_CLOSING) {

cancel();

}

super.processWindowEvent(e);

}

//Close the dialog

void cancel() {

dispose();

}

//Close the dialog on a button event

public void actionPerformed(ActionEvent e) {

if (e.getSource() == button1) {

cancel();

}

}

}

dbSvr.java

package clientPkg;

import java.rmi.*;

import java.rmi.registry.*;

import java.rmi.server.*;

import java.io.*;

import java.util.*;

import .*;

import javax.swing.*;

import com.borland.jbcl.layout.*;

import java.awt.*;

import java.math.BigInteger;

import java.security.*;

import java.security.spec.*;

import java.security.interfaces.*;

import javax.crypto.*;

import javax.crypto.spec.*;

import javax.crypto.interfaces.*;

import com.sun.crypto.provider.SunJCE;

/*

* class: dbSvr

* description: maintains, updates, and reports sales information

* inputs: none

* outputs: none

* return value: none

*/

class dbSvr extends UnicastRemoteObject implements dbSvrInterface

{

int intMaxItemLines = 5;

static byte[] byteSecretKey;

static nameSvrInterface objNameSvr;

// the 1024 bit Diffie-Hellman modulus values used by SKIP

private static final byte skip1024ModulusBytes[] = {

(byte) 0xF4, (byte) 0x88, (byte) 0xFD, (byte) 0x58,

(byte) 0x4E, (byte) 0x49, (byte) 0xDB, (byte) 0xCD,

(byte) 0x20, (byte) 0xB4, (byte) 0x9D, (byte) 0xE4,

(byte) 0x91, (byte) 0x07, (byte) 0x36, (byte) 0x6B,

(byte) 0x33, (byte) 0x6C, (byte) 0x38, (byte) 0x0D,

(byte) 0x45, (byte) 0x1D, (byte) 0x0F, (byte) 0x7C,

(byte) 0x88, (byte) 0xB3, (byte) 0x1C, (byte) 0x7C,

(byte) 0x5B, (byte) 0x2D, (byte) 0x8E, (byte) 0xF6,

(byte) 0xF3, (byte) 0xC9, (byte) 0x23, (byte) 0xC0,

(byte) 0x43, (byte) 0xF0, (byte) 0xA5, (byte) 0x5B,

(byte) 0x18, (byte) 0x8D, (byte) 0x8E, (byte) 0xBB,

(byte) 0x55, (byte) 0x8C, (byte) 0xB8, (byte) 0x5D,

(byte) 0x38, (byte) 0xD3, (byte) 0x34, (byte) 0xFD,

(byte) 0x7C, (byte) 0x17, (byte) 0x57, (byte) 0x43,

(byte) 0xA3, (byte) 0x1D, (byte) 0x18, (byte) 0x6C,

(byte) 0xDE, (byte) 0x33, (byte) 0x21, (byte) 0x2C,

(byte) 0xB5, (byte) 0x2A, (byte) 0xFF, (byte) 0x3C,

(byte) 0xE1, (byte) 0xB1, (byte) 0x29, (byte) 0x40,

(byte) 0x18, (byte) 0x11, (byte) 0x8D, (byte) 0x7C,

(byte) 0x84, (byte) 0xA7, (byte) 0x0A, (byte) 0x72,

(byte) 0xD6, (byte) 0x86, (byte) 0xC4, (byte) 0x03,

(byte) 0x19, (byte) 0xC8, (byte) 0x07, (byte) 0x29,

(byte) 0x7A, (byte) 0xCA, (byte) 0x95, (byte) 0x0C,

(byte) 0xD9, (byte) 0x96, (byte) 0x9F, (byte) 0xAB,

(byte) 0xD0, (byte) 0x0A, (byte) 0x50, (byte) 0x9B,

(byte) 0x02, (byte) 0x46, (byte) 0xD3, (byte) 0x08,

(byte) 0x3D, (byte) 0x66, (byte) 0xA4, (byte) 0x5D,

(byte) 0x41, (byte) 0x9F, (byte) 0x9C, (byte) 0x7C,

(byte) 0xBD, (byte) 0x89, (byte) 0x4B, (byte) 0x22,

(byte) 0x19, (byte) 0x26, (byte) 0xBA, (byte) 0xAB,

(byte) 0xA2, (byte) 0x5E, (byte) 0xC3, (byte) 0x55,

(byte) 0xE9, (byte) 0x2F, (byte) 0x78, (byte) 0xC7

};

// the SKIP 1024 bit modulus

private static final BigInteger skip1024Modulus

= new BigInteger(1, skip1024ModulusBytes);

// the base used with the SKIP 1024 bit modulus

private static final BigInteger skip1024Base = BigInteger.valueOf(2);

/*

* function: dbSvr

* description: constructor

* inputs: none

* outputs: none

* return value: none

*/

public dbSvr() throws RemoteException

{

super();

try

{

jbInit();

}

catch(Exception e)

{

e.printStackTrace();

}

}

/*

* function: dbSvrStatus

* description: returns a true value to the calling program to

* indicate that the database server is alive

* inputs: none

* outputs: none

* return value: boolean, true if database server is alive,

* none otherwise

*/

public boolean dbSvrStatus() throws RemoteException

{

System.out.println("dbSvrStatus has been called...");

return (true);

}

/*

* function: prepDbData

* description: formats data for entry into the database

* inputs: String strData, data to be formatted

* outputs: none

* return value: String, formatted data

*/

String prepDbData (String strData)

{

String strTemp;

if (strData.equals(""))

strTemp = "nodata:";

else

strTemp = strData.trim() + ":";

return strTemp;

}

/*

* function: submitInvoiceToDbSvr

* description: takes blowfish encrypted data and writes out the data to

* the database in clear text. data is received in an invoice

* object. each field in the invoice object is blowfish

* encrypted. the key to the blowfish encryption is obtained

* during database server initialization. the invoice object

* is decrypted, and written out to the database.

* inputs: invoice objInvoice, invoice form data in an encrypted format

* outputs: none

* return value: none

*/

public void submitInvoiceToDbSvr(invoice objInvoice) throws RemoteException

{

String strBuffer = new String();

int i;

BlowfishECB bfecb = new BlowfishECB(byteSecretKey);

System.out.println("submitInvoiceToDbSvr has been called...");

try

{

if ((strBuffer = readFile("invoice_db.txt")) == null)

strBuffer = "";

}

catch (Exception e)

{

System.out.println("submitInvoiceToDbSvr file read error: " +

e.getMessage());

}

// decrypt objInvoice fields and output data into a string buffer

try

{

bfecb.decrypt(objInvoice.byteBillName);

strBuffer += prepDbData(new String(objInvoice.byteBillName, "UTF8"));

bfecb.decrypt(objInvoice.byteBillAddress);

strBuffer += prepDbData(new String(objInvoice.byteBillAddress, "UTF8"));

bfecb.decrypt(objInvoice.byteBillCity);

strBuffer += prepDbData(new String(objInvoice.byteBillCity, "UTF8"));

bfecb.decrypt(objInvoice.byteBillState);

strBuffer += prepDbData(new String(objInvoice.byteBillState, "UTF8"));

bfecb.decrypt(objInvoice.byteBillZip);

strBuffer += prepDbData(new String(objInvoice.byteBillZip, "UTF8"));

bfecb.decrypt(objInvoice.byteShipName);

strBuffer += prepDbData(new String(objInvoice.byteShipName, "UTF8"));

bfecb.decrypt(objInvoice.byteShipAddress);

strBuffer += prepDbData(new String(objInvoice.byteShipAddress, "UTF8"));

bfecb.decrypt(objInvoice.byteShipCity);

strBuffer += prepDbData(new String(objInvoice.byteShipCity, "UTF8"));

bfecb.decrypt(objInvoice.byteShipState);

strBuffer += prepDbData(new String(objInvoice.byteShipState, "UTF8"));

bfecb.decrypt(objInvoice.byteShipZip);

strBuffer += prepDbData(new String(objInvoice.byteShipZip, "UTF8"));

bfecb.decrypt(objInvoice.byteQty0);

strBuffer += prepDbData(new String(objInvoice.byteQty0, "UTF8"));

bfecb.decrypt(objInvoice.byteItem0);

strBuffer += prepDbData(new String(objInvoice.byteItem0, "UTF8"));

bfecb.decrypt(objInvoice.bytePrice0);

strBuffer += prepDbData(new String(objInvoice.bytePrice0, "UTF8"));

bfecb.decrypt(objInvoice.byteExtend0);

strBuffer += prepDbData(new String(objInvoice.byteExtend0, "UTF8"));

bfecb.decrypt(objInvoice.byteQty1);

strBuffer += prepDbData(new String(objInvoice.byteQty1, "UTF8"));

bfecb.decrypt(objInvoice.byteItem1);

strBuffer += prepDbData(new String(objInvoice.byteItem1, "UTF8"));

bfecb.decrypt(objInvoice.bytePrice1);

strBuffer += prepDbData(new String(objInvoice.bytePrice1, "UTF8"));

bfecb.decrypt(objInvoice.byteExtend1);

strBuffer += prepDbData(new String(objInvoice.byteExtend1, "UTF8"));

bfecb.decrypt(objInvoice.byteQty2);

strBuffer += prepDbData(new String(objInvoice.byteQty2, "UTF8"));

bfecb.decrypt(objInvoice.byteItem2);

strBuffer += prepDbData(new String(objInvoice.byteItem2, "UTF8"));

bfecb.decrypt(objInvoice.bytePrice2);

strBuffer += prepDbData(new String(objInvoice.bytePrice2, "UTF8"));

bfecb.decrypt(objInvoice.byteExtend2);

strBuffer += prepDbData(new String(objInvoice.byteExtend2, "UTF8"));

bfecb.decrypt(objInvoice.byteQty3);

strBuffer += prepDbData(new String(objInvoice.byteQty3, "UTF8"));

bfecb.decrypt(objInvoice.byteItem3);

strBuffer += prepDbData(new String(objInvoice.byteItem3, "UTF8"));

bfecb.decrypt(objInvoice.bytePrice3);

strBuffer += prepDbData(new String(objInvoice.bytePrice3, "UTF8"));

bfecb.decrypt(objInvoice.byteExtend3);

strBuffer += prepDbData(new String(objInvoice.byteExtend3, "UTF8"));

bfecb.decrypt(objInvoice.byteQty4);

strBuffer += prepDbData(new String(objInvoice.byteQty4, "UTF8"));

bfecb.decrypt(objInvoice.byteItem4);

strBuffer += prepDbData(new String(objInvoice.byteItem4, "UTF8"));

bfecb.decrypt(objInvoice.bytePrice4);

strBuffer += prepDbData(new String(objInvoice.bytePrice4, "UTF8"));

bfecb.decrypt(objInvoice.byteExtend4);

strBuffer += prepDbData(new String(objInvoice.byteExtend4, "UTF8"));

bfecb.decrypt(objInvoice.byteSubTotal);

strBuffer += prepDbData(new String(objInvoice.byteSubTotal, "UTF8"));

bfecb.decrypt(objInvoice.byteTax);

strBuffer += prepDbData(new String(objInvoice.byteTax, "UTF8"));

bfecb.decrypt(objInvoice.byteTotal);

strBuffer += prepDbData(new String(objInvoice.byteTotal, "UTF8"));

}

catch (Exception e)

{

System.out.println("submitInvoiceToDbSvr error: " + e.getMessage());

}

// write data into the database

try

{

writeFile(strBuffer, "invoice_db.txt");

}

catch (Exception e)

{

System.out.println("submitInvoiceToDbSvr file write error: " + e.getMessage());

}

}

/*

* function: updateReport

* description: combine like data from the database to create summary report

* inputs: report objReport, holder of summary data from the database

* string[] strQty, quantity of each item type

* string[] strItem, item type

* string[] strPrice, price of each item type

* string[] strExtend, extended price of each item type

* string strSubTotal, subtotal

* string strTax, tax

* string strTotal, total

* outputs: none

* return value: report, summary report

*/

public report updateReport (report objReport,

String[] strQty,

String[] strItem,

String[] strPrice,

String[] strExtend,

String strSubTotal,

String strTax,

String strTotal)

{

int i;

// update each item type

for (i = 0; i < intMaxItemLines; i++)

{

if (strItem[i].equals("CPU"))

{

objReport.intCpuQty = objReport.intCpuQty + Integer.parseInt(strQty[i]);

objReport.fltCpuPrice = objReport.fltCpuPrice +

Float.parseFloat(strPrice[i]);

objReport.fltCpuExtend = objReport.fltCpuExtend +

Float.parseFloat(strExtend[i]);

}

if (strItem[i].equals("Keyboard"))

{

objReport.intKbQty = objReport.intKbQty + Integer.parseInt(strQty[i]);

objReport.fltKbPrice =

objReport.fltKbPrice + Float.parseFloat(strPrice[i]);

objReport.fltKbExtend = objReport.fltKbExtend +

Float.parseFloat(strExtend[i]);

}

if (strItem[i].equals("Memory"))

{

objReport.intMemQty = objReport.intMemQty + Integer.parseInt(strQty[i]);

objReport.fltMemPrice = objReport.fltMemPrice +

Float.parseFloat(strPrice[i]);

objReport.fltMemExtend = objReport.fltMemExtend +

Float.parseFloat(strExtend[i]);

}

if (strItem[i].equals("Monitor"))

{

objReport.intMonitorQty = objReport.intMonitorQty +

Integer.parseInt(strQty[i]);

objReport.fltMonitorPrice = objReport.fltMonitorPrice +

Float.parseFloat(strPrice[i]);

objReport.fltMonitorExtend = objReport.fltMonitorExtend +

Float.parseFloat(strExtend[i]);

}

}

// update totals

objReport.fltSubTotal =

objReport.fltSubTotal + Float.parseFloat(strSubTotal);

objReport.fltTax = objReport.fltTax + Float.parseFloat(strTax);

objReport.fltTotal = objReport.fltTotal + Float.parseFloat(strTotal);

return (objReport);

}

/*

* function: getReport

* description: initialize database data

* inputs: String strData, database data in a string format

* outputs: none

* return value: String, initialized database data string

*/

public encReport getReport() throws RemoteException

{

report objReport = null;

encReport objEncReport = null;

String strDiscard, strData;

String strSubTotal, strTax, strTotal;

String[] strQty = new String[intMaxItemLines];

String[] strItem = new String[intMaxItemLines];

String[] strPrice = new String[intMaxItemLines];

String[] strExtend = new String[intMaxItemLines];

int i;

try

{

System.out.println("getReport has been called...");

objReport = new report();

strData = readFile("invoice_db.txt");

StringTokenizer tokenizer = new StringTokenizer(strData, ":");

while (tokenizer.hasMoreTokens())

{

strDiscard = tokenizer.nextToken(); // strBillName

strDiscard = tokenizer.nextToken(); // strBillAddress

strDiscard = tokenizer.nextToken(); // strBillCity

strDiscard = tokenizer.nextToken(); // strBillState

strDiscard = tokenizer.nextToken(); // strBillZip

strDiscard = tokenizer.nextToken(); // strShipName

strDiscard = tokenizer.nextToken(); // strShipAddress

strDiscard = tokenizer.nextToken(); // strShipCity

strDiscard = tokenizer.nextToken(); // strShipState

strDiscard = tokenizer.nextToken(); // strShipZip

for (i = 0; i < intMaxItemLines; i++)

{

strQty[i] = tokenizer.nextToken(); // strQty#

strItem[i] = tokenizer.nextToken(); // strItem#

strPrice[i] = tokenizer.nextToken(); // strPrice#

strExtend[i] = tokenizer.nextToken(); // strExtend#

}

strSubTotal = tokenizer.nextToken(); // strSubTotal

strTax = tokenizer.nextToken(); // strTax

strTotal = tokenizer.nextToken(); // strTotal

objReport = updateReport (objReport,

strQty,

strItem,

strPrice,

strExtend,

strSubTotal,

strTax,

strTotal);

}

objEncReport = encryptReport (objReport);

}

catch (Exception e)

{

System.out.println("getReport error: " + e.getMessage());

}

return (objEncReport);

}

/*

* function: create_message

* description: generate and return a blowfish encrypted message

* inputs: byte[] temp_buf, message in clear text

* int n_MessSize, size of temp_buf

* outputs: none

* return value: byte[], blowfish encrypted message

*/

public byte[] create_message (byte[] temp_buf, int n_MessSize)

{

int nRest;

// align to the next 8 byte border

byte[] messbuf;

nRest = n_MessSize & 7;

if (nRest != 0)

{

messbuf = new byte[(n_MessSize & (~7)) + 8];

System.arraycopy(temp_buf, 0, messbuf, 0, n_MessSize);

for (int nI = n_MessSize; nI < messbuf.length ; nI++)

messbuf[nI] = 0x20;

System.out.println("message with " + n_MessSize + " bytes aligned to " +

messbuf.length + " bytes");

}

else

{

messbuf = new byte[n_MessSize];

System.arraycopy(temp_buf, 0, messbuf, 0, n_MessSize);

}

return (messbuf);

}

/*

* function: encryptReport

* description: generates a blowfish encrypted encReport object from a

* non-encrypted report object

* inputs: report objReport, holder of summary data from the database

* outputs: none

* return value: encReport, encrypted summary data from the database

*/

public encReport encryptReport (report objReport)

{

String strTemp = new String();

encReport objEncReport = new encReport();

int i;

byte[] byteKey = new byte[20];

BlowfishECB bfecb = new BlowfishECB(byteSecretKey);

// encrypt summary data and return it

try

{

objEncReport.byteCpuQty =

Integer.toString(objReport.intCpuQty).getBytes();

objEncReport.byteCpuQty =

create_message (objEncReport.byteCpuQty,

Integer.toString(objReport.intCpuQty).length());

bfecb.encrypt(objEncReport.byteCpuQty);

objEncReport.byteCpuPrice =

Float.toString(objReport.fltCpuPrice).getBytes();

objEncReport.byteCpuPrice =

create_message (objEncReport.byteCpuPrice,

Float.toString(objReport.fltCpuPrice).length());

bfecb.encrypt(objEncReport.byteCpuPrice);

objEncReport.byteCpuExtend =

Float.toString(objReport.fltCpuExtend).getBytes();

objEncReport.byteCpuExtend =

create_message (objEncReport.byteCpuExtend,

Float.toString(objReport.fltCpuExtend).length());

bfecb.encrypt(objEncReport.byteCpuExtend);

objEncReport.byteKbQty = Integer.toString(objReport.intKbQty).getBytes();

objEncReport.byteKbQty =

create_message (objEncReport.byteKbQty,

Integer.toString(objReport.intKbQty).length());

bfecb.encrypt(objEncReport.byteKbQty);

objEncReport.byteKbPrice =

Float.toString(objReport.fltKbPrice).getBytes();

objEncReport.byteKbPrice =

create_message (objEncReport.byteKbPrice,

Float.toString(objReport.fltKbPrice).length());

bfecb.encrypt(objEncReport.byteKbPrice);

objEncReport.byteKbExtend =

Float.toString(objReport.fltKbExtend).getBytes();

objEncReport.byteKbExtend =

create_message (objEncReport.byteKbExtend,

Float.toString(objReport.fltKbExtend).length());

bfecb.encrypt(objEncReport.byteKbExtend);

objEncReport.byteMemQty =

Integer.toString(objReport.intMemQty).getBytes();

objEncReport.byteMemQty =

create_message(objEncReport.byteMemQty,

Integer.toString(objReport.intMemQty).length());

bfecb.encrypt(objEncReport.byteMemQty);

objEncReport.byteMemPrice =

Float.toString(objReport.fltMemPrice).getBytes();

objEncReport.byteMemPrice =

create_message(objEncReport.byteMemPrice,

Float.toString(objReport.fltMemPrice).length());

bfecb.encrypt(objEncReport.byteMemPrice);

objEncReport.byteMemExtend =

Float.toString(objReport.fltMemExtend).getBytes();

objEncReport.byteMemExtend =

create_message (objEncReport.byteMemExtend,

Float.toString(objReport.fltMemExtend).length());

bfecb.encrypt(objEncReport.byteMemExtend);

objEncReport.byteMonitorQty =

Integer.toString(objReport.intMonitorQty).getBytes();

objEncReport.byteMonitorQty =

create_message(objEncReport.byteMonitorQty,

Integer.toString(objReport.intMonitorQty).length());

bfecb.encrypt(objEncReport.byteMonitorQty);

objEncReport.byteMonitorPrice =

Float.toString(objReport.fltMonitorPrice).getBytes();

objEncReport.byteMonitorPrice =

create_message(objEncReport.byteMonitorPrice,

Float.toString(objReport.fltMonitorPrice).length());

bfecb.encrypt(objEncReport.byteMonitorPrice);

objEncReport.byteMonitorExtend =

Float.toString(objReport.fltMonitorExtend).getBytes();

objEncReport.byteMonitorExtend =

create_message (objEncReport.byteMonitorExtend,

Float.toString(objReport.fltMonitorExtend).length());

bfecb.encrypt(objEncReport.byteMonitorExtend);

objEncReport.byteSubTotal =

Float.toString(objReport.fltSubTotal).getBytes();

objEncReport.byteSubTotal =

create_message(objEncReport.byteSubTotal,

Float.toString(objReport.fltSubTotal).length());

bfecb.encrypt(objEncReport.byteSubTotal);

objEncReport.byteTax = Float.toString(objReport.fltTax).getBytes();

objEncReport.byteTax =

create_message(objEncReport.byteTax,

Float.toString(objReport.fltTax).length());

bfecb.encrypt(objEncReport.byteTax);

objEncReport.byteTotal = Float.toString(objReport.fltTotal).getBytes();

objEncReport.byteTotal =

create_message(objEncReport.byteTotal,

Float.toString(objReport.fltTotal).length());

bfecb.encrypt(objEncReport.byteTotal);

}

catch (Exception e)

{

System.out.println("encryptReport error: " + e.getMessage());

}

return objEncReport;

}

/*

* function: readFile

* description: read and returns the content of a text file in form of a

* string

* inputs: String strFileName, name of a text file

* outputs: none

* return value: string, content of a text file

*/

public String readFile(String strFileName) throws RemoteException

{

FileReader objFileReader;

BufferedReader objBufferedReader;

String strData = null;

try

{

objFileReader = new FileReader(strFileName);

objBufferedReader = new BufferedReader(objFileReader);

strData = new String();

while (objBufferedReader.ready())

strData += objBufferedReader.readLine();

objBufferedReader.close();

}

catch (Exception e)

{

System.out.println("readFile error: " + e.getMessage());

}

return (strData);

}

/*

* function: writeFile

* description: write the content of a string into a file

* inputs: String strData, data to be written out to file

* String strFileName, name of a text file

* outputs: none

* return value: none

*/

public void writeFile(String strData, String strFileName)

throws RemoteException

{

FileOutputStream objFileOutputStream;

PrintStream objPrintStream;

try

{

objFileOutputStream = new FileOutputStream(strFileName);

objPrintStream = new PrintStream(objFileOutputStream);

objPrintStream.println(strData);

objPrintStream.close();

}

catch (Exception e)

{

System.out.println("writeFile error: " + e.getMessage());

}

}

/*

* function: pubKeyClient

* description: pubKeyClient uses the Diffie-Hellman algorithm to

* communicate with the name server via public key

* encryption. pubKeyClient generates its own public key,

* sends the public key to the name server. The name server

* generates a secret key with pubKeyClient's public key,

* and encodes a message for pubKeyClient with the secret

* key. pubKeyClient will decode the encrypted message with

* the its public key. the message is the key that will be

* used by blowfish to encrypt and decrypt data.

* inputs: none

* outputs: none

* return value: none

*/

static public void pubKeyClient() throws Exception {

// use some pre-generated, default Skip DH parameters

DHParameterSpec dhSkipParamSpec =

new DHParameterSpec(skip1024Modulus, skip1024Base);

// app generates its own key pair from parameters above

KeyPairGenerator clientKpairGen = KeyPairGenerator.getInstance("DH");

clientKpairGen.initialize(dhSkipParamSpec);

KeyPair clientKpair = clientKpairGen.generateKeyPair();

// app creates and initializes own DH KeyAgreement object

KeyAgreement clientKeyAgree = KeyAgreement.getInstance("DH");

clientKeyAgree.init(clientKpair.getPrivate());

// app encodes own public key and sends it over to server

byte[] clientPubKeyEnc = clientKpair.getPublic().getEncoded();

// app generates a copy of the server's public key from the server's

// encoded public key

KeyFactory clientKeyFac = KeyFactory.getInstance("DH");

X509EncodedKeySpec x509KeySpec =

new X509EncodedKeySpec(objNameSvr.getServerPubKeyEnc(clientPubKeyEnc));

PublicKey serverPubKey = clientKeyFac.generatePublic(x509KeySpec);

clientKeyAgree.doPhase(serverPubKey, true);

// generate secret key

SecretKey clientDesKey = clientKeyAgree.generateSecret("DES");

// get server's encoded message and decode it

byte[] ciphertext = objNameSvr.getServerEncMsg();

Cipher clientCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");

clientCipher.init(Cipher.DECRYPT_MODE, clientDesKey);

byteSecretKey = clientCipher.doFinal(ciphertext);

// for information purpose only. compares received message with actual

// message to make sure correct data is received.

byte[] cleartext = new byte[20];

for (int i = 0; i < 20; i++)

cleartext[i] = (byte) ( (i + 1) & 0xff);

if (!java.util.Arrays.equals(cleartext, byteSecretKey))

System.out.println("DES in CBC mode recovered text is " +

"different from cleartext");

else {

System.out.println("DES in ECB mode recovered text is " +

"same as cleartext");

for (int i = 0; i < byteSecretKey.length; i++)

System.out.print(byteSecretKey[i] + " ");

System.out.println();

for (int i = 0; i < cleartext.length; i++)

System.out.print(cleartext[i] + " ");

System.out.println();

}

}

/*

* function: main

* description: main registers the database server with the local registry

* and the name server. if the default port number is not

* available, main finds the first available port number and

* binds to it. main then registers with the name server.

* if the name server database queue is full, and error is

* output to the standard output.

* inputs: none

* outputs: none

* return value: none

*/

public static void main(String arguments[]) throws RemoteException {

Registry regDbSvr;

boolean blContinue = true;

int intPortNum = 6989;

String strDbSvrLoc;

dbSvrInterface objDbSvr;

String strNameSvrLoc = "rmi://127.0.0.1:6969/nameSvr";

InetAddress localHost;

System.out.println("*** database_server starting ***");

while (blContinue)

{

try

{

regDbSvr = LocateRegistry.createRegistry(intPortNum);

blContinue = false;

}

catch (Exception e)

{

intPortNum++;

}

}

try

{

localHost = InetAddress.getLocalHost();

strDbSvrLoc =

"rmi://127.0.0.1:" + String.valueOf(intPortNum) + "/dbSvr";

objDbSvr = new dbSvr();

Naming.rebind(strDbSvrLoc, objDbSvr);

System.out.println("database server registered successfully at port# " +

intPortNum);

objNameSvr = (nameSvrInterface) Naming.lookup(strNameSvrLoc);

if (!objNameSvr.regDbSvr(strDbSvrLoc))

{

System.out.println("Name Server DB queue is full");

System.exit(1);

}

pubKeyClient();

}

catch (Exception e)

{

System.out.println("dbSvr main error: " + e.getMessage());

}

}

/*

* function: jbInit

* description: none

* inputs: none

* outputs: none

* return value: none

*/

private void jbInit() throws Exception

{

}

}

dbSvrInterface.java

package clientPkg;

import java.rmi.*;

/*

* interface: dbSvrInterface

* description: database server remote methods

* note: all remote methods must throw RemoteException

*/

public interface dbSvrInterface extends Remote

{

/*

* function: dbSvrStatus

* description: returns a true value to the calling program to

* indicate that the database server is alive

* inputs: none

* outputs: none

* return value: boolean, true if database server is alive,

* none otherwise

*/

boolean dbSvrStatus() throws RemoteException;

/*

* function: submitInvoiceToDbSvr

* description: takes blowfish encrypted data and writes out the data to

* the database in clear text. data is received in an invoice

* object. each field in the invoice object is blowfish

* encrypted. the key to the blowfish encryption is obtained

* during database server initialization. the invoice object

* is decrypted, and written out to the database.

* inputs: invoice objInvoice, invoice form data in an encrypted format

* outputs: none

* return value: none

*/

void submitInvoiceToDbSvr(invoice objInvoice) throws RemoteException;

/*

* function: getReport

* description: initialize database data

* inputs: String strData, database data in a string format

* outputs: none

* return value: String, initialized database data string

*/

encReport getReport() throws RemoteException;

}

encReport.java

package clientPkg;

import java.io.*;

/*

* class: encReport

* description: blowfish encrypted invoice form data

*/

public class encReport implements Serializable

{

byte[] byteCpuQty;

byte[] byteCpuPrice;

byte[] byteCpuExtend;

byte[] byteKbQty;

byte[] byteKbPrice;

byte[] byteKbExtend;

byte[] byteMemQty;

byte[] byteMemPrice;

byte[] byteMemExtend;

byte[] byteMonitorQty;

byte[] byteMonitorPrice;

byte[] byteMonitorExtend;

byte[] byteSubTotal;

byte[] byteTax;

byte[] byteTotal;

}

frontEndSvr.java

package clientPkg;

import java.rmi.*;

import java.rmi.registry.*;

import java.rmi.server.*;

import java.io.*;

import java.util.*;

import .*;

import javax.swing.*;

import com.borland.jbcl.layout.*;

import java.awt.*;

/*

* class: frontEndSvr

* description: frontEndSvr serves as a broker between the client user

* interface (ui) and the database servers. the client ui

* makes all requests through the frontEndSvr, which in turn

* forwards the requests to the next available database server.

* this relieves the client ui from having to keep track of

* available database servers.

* inputs: none

* outputs: none

* return value: none

*/

public class frontEndSvr

extends UnicastRemoteObject

implements frontEndSvrInterface

{

/*

* function: frontEndSvr

* description: constructor

* inputs: none

* outputs: none

* return value: none

*/

public frontEndSvr() throws RemoteException

{

super();

}

/*

* function: frontEndSvrStatus

* description: frontEndSvrStatus returns a true value to the calling

* program to indicate that the Front End Server is alive

* inputs: none

* outputs: none

* return value: boolean, true if Front End Server is alive,

* none otherwise

*/

public boolean frontEndSvrStatus() throws RemoteException

{

System.out.println("frontEndSvrStatus function has been called...");

return (true);

}

/*

* function: submitInvoiceToFrontEndSvr

* description: submitInvoiceToFrontEndSvr forwards the invoice object it

* receives to a database server. submitInvoiceToFrontEndSvr

* calls the Name Server to get the location of the next

* available database server. if a database server is

* located, the invoice object is fowarded; otherwise, an

* exception is thrown and an error message is printed to

* standard output.

* inputs: invoice objInvoice

* outputs: none

* return value: none

*/

public void submitInvoiceToFrontEndSvr(invoice objInvoice)

throws RemoteException

{

nameSvrInterface objNameSvr;

String strNameSvrLoc = "rmi://127.0.0.1:6969/nameSvr";

dbSvrInterface objDBSvr;

String strDBSvrLoc;

// call Name Server to get next available database server object to submit

// invoice object

try

{

System.out.println("submitInvoiceToFrontEndSvr has been called...");

objNameSvr = (nameSvrInterface) Naming.lookup(strNameSvrLoc);

strDBSvrLoc = objNameSvr.getDbSvr();

objDBSvr = (dbSvrInterface) Naming.lookup(strDBSvrLoc);

objDBSvr.submitInvoiceToDbSvr(objInvoice);

}

catch (Exception except)

{

System.out.println ("submitInvoiceToFrontEndSvr error: " +

except.getMessage());

}

}

/*

* function: getReport

* description: getReport extracts an encReport object from the Database

* Server and returning it to the calling program. getReport

* calls the Name Serve to get the location of the next

* available database server. If the database server is

* located, an encReport object is extracted from the Database

* server and returned to the calling program; otherwise, an

* exception is thrown and an error message is printed to the

* standard output.

* inputs: none

* outputs: none

* return value: encReport, Blowfish encrypted data

*/

public encReport getReport() throws RemoteException

{

nameSvrInterface objNameSvr;

String strNameSvrLoc = "rmi://127.0.0.1:6969/nameSvr";

dbSvrInterface objDBSvr;

String strDBSvrLoc;

report objReport;

encReport objEncReport = null;

// call Name Server to get the next available database server object to

// extract the encReport object and return the encReport object to the

// calling program

try

{

System.out.println ("getReport has been called...");

objNameSvr = (nameSvrInterface) Naming.lookup(strNameSvrLoc);

strDBSvrLoc = objNameSvr.getDbSvr();

objDBSvr = (dbSvrInterface) Naming.lookup(strDBSvrLoc);

objEncReport = objDBSvr.getReport();

}

catch (Exception except)

{

System.out.println("gerReport error: " + except.getMessage());

}

return (objEncReport);

}

/*

* function: main

* description: main registers the frontEndSvr with the local registry

* inputs: none

* outputs: none

* return value: none

*/

public static void main(String[] args)

{

Registry regFrontEndSvr;

String strFrontEndSvrLoc;

frontEndSvrInterface objFrontEndSvr;

nameSvrInterface objNameSvr;

InetAddress localHost;

System.out.println("*** front end server starting ***");

// register with the local registry

try

{

localHost = InetAddress.getLocalHost();

strFrontEndSvrLoc = "rmi://" + localHost.getHostAddress() + ":6979/frontEndSvr";

regFrontEndSvr = LocateRegistry.createRegistry(6979);

objFrontEndSvr = new frontEndSvr();

Naming.rebind(strFrontEndSvrLoc, objFrontEndSvr);

System.out.println("frontEndSvr registered successfully at port# 6979");

}

catch (Exception e)

{

System.out.println("frontEndSvr main error: " + e.getMessage());

}

}

}

frontEndSvr2.java

package clientPkg;

import java.rmi.*;

import java.rmi.registry.*;

import java.rmi.server.*;

import java.io.*;

import java.util.*;

import .*;

import javax.swing.*;

import com.borland.jbcl.layout.*;

import java.awt.*;

/*

* class: frontEndSvr

* description: frontEndSvr serves as a broker between the client user

* interface (ui) and the database servers. the client ui

* makes all requests through the frontEndSvr, which in turn

* forwards the requests to the next available database server.

* this relieves the client ui from having to keep track of

* available database servers.

* inputs: none

* outputs: none

* return value: none

*/

public class frontEndSvr2

extends UnicastRemoteObject

implements frontEndSvrInterface2

{

/*

* function: frontEndSvr

* description: constructor

* inputs: none

* outputs: none

* return value: none

*/

public frontEndSvr2() throws RemoteException

{

super();

}

/*

* function: frontEndSvrStatus

* description: frontEndSvrStatus returns a true value to the calling

* program to indicate that the Front End Server is alive

* inputs: none

* outputs: none

* return value: boolean, true if Front End Server is alive,

* none otherwise

*/

public boolean frontEndSvrStatus() throws RemoteException

{

System.out.println("frontEndSvrStatus function called...");

return (true);

}

/*

* function: submitInvoiceToFrontEndSvr

* description: submitInvoiceToFrontEndSvr forwards the invoice object it

* receives to a database server. submitInvoiceToFrontEndSvr

* calls the Name Server to get the location of the next

* available database server. if a database server is

* located, the invoice object is fowarded; otherwise, an

* exception is thrown and an error message is printed to

* standard output.

* inputs: invoice objInvoice

* outputs: none

* return value: none

*/

public void submitInvoiceToFrontEndSvr(invoice objInvoice)

throws RemoteException

{

nameSvrInterface objNameSvr;

String strNameSvrLoc = "rmi://127.0.0.1:6969/nameSvr";

dbSvrInterface objDBSvr;

String strDBSvrLoc;

report objReport;

encReport objEncReport;

// call Name Server to get next available database server object to submit

// invoice object

try

{

System.out.println("submitInvoiceToFrontEndSvr has been called...");

objNameSvr = (nameSvrInterface) Naming.lookup(strNameSvrLoc);

strDBSvrLoc = objNameSvr.getDbSvr();

objDBSvr = (dbSvrInterface) Naming.lookup(strDBSvrLoc);

objDBSvr.submitInvoiceToDbSvr(objInvoice);

}

catch (Exception except)

{

System.out.println("submitInvoiceToFrontEndSvr error: " +

except.getMessage());

}

}

/*

* function: getReport

* description: getReport extracts an encReport object from the Database

* Server and returning it to the calling program. getReport

* calls the Name Serve to get the location of the next

* available database server. If the database server is

* located, an encReport object is extracted from the Database

* server and returned to the calling program; otherwise, an

* exception is thrown and an error message is printed to the

* standard output.

* inputs: none

* outputs: none

* return value: encReport, Blowfish encrypted data

*/

public encReport getReport() throws RemoteException

{

nameSvrInterface objNameSvr;

String strNameSvrLoc = "rmi://127.0.0.1:6969/nameSvr";

dbSvrInterface objDBSvr;

String strDBSvrLoc;

report objReport;

encReport objEncReport = null;

// call Name Server to get the next available database server object to

// extract the encReport object and return the encReport object to the

// calling program

try

{

System.out.println("getReport has been called...");

objNameSvr = (nameSvrInterface) Naming.lookup(strNameSvrLoc);

strDBSvrLoc = objNameSvr.getDbSvr();

objDBSvr = (dbSvrInterface) Naming.lookup(strDBSvrLoc);

objEncReport = objDBSvr.getReport();

}

catch (Exception except)

{

System.out.println("getReport error: " + except.getMessage());

}

return (objEncReport);

}

/*

* function: main

* description: main registers the frontEndSvr with the local registry

* inputs: none

* outputs: none

* return value: none

*/

public static void main(String[] args)

{

Registry regFrontEndSvr;

String strFrontEndSvrLoc;

frontEndSvrInterface objFrontEndSvr;

nameSvrInterface objNameSvr;

String strNameSvrLoc = "rmi://127.0.0.1:6969/nameSvr";

InetAddress localHost;

System.out.println("*** front end server starting ***");

// register with the local registry

try

{

localHost = InetAddress.getLocalHost();

strFrontEndSvrLoc = "rmi://" + localHost.getHostAddress() + ":6980/frontEndSvr";

regFrontEndSvr = LocateRegistry.createRegistry(6980);

objFrontEndSvr = new frontEndSvr();

Naming.rebind(strFrontEndSvrLoc, objFrontEndSvr);

System.out.println("frontEndSvr2 registered successfully at port# 6980");

}

catch (Exception e)

{

System.out.println("frontEndSvr main error: " + e.getMessage());

}

}

}

frontEndSvrInterface.java

package clientPkg;

import java.rmi.*;

/*

* interface: frontEndSvrInterface

* description: front end server remote methods

* note: all remote methods must throw RemoteException

*/

public interface frontEndSvrInterface extends Remote

{

/*

* function: frontEndSvrStatus

* description: frontEndSvrStatus returns a true value to the calling

* program to indicate that the Front End Server is alive

* inputs: none

* outputs: none

* return value: boolean, true if Front End Server is alive,

* none otherwise

*/

boolean frontEndSvrStatus() throws RemoteException;

/*

* function: submitInvoiceToFrontEndSvr

* description: submitInvoiceToFrontEndSvr forwards the invoice object it

* receives to a database server. submitInvoiceToFrontEndSvr

* calls the Name Server to get the location of the next

* available database server. if a database server is

* located, the invoice object is fowarded; otherwise, an

* exception is thrown and an error message is printed to

* standard output.

* inputs: invoice objInvoice

* outputs: none

* return value: none

*/

void submitInvoiceToFrontEndSvr(invoice objInvoice) throws RemoteException;

/*

* function: getReport

* description: getReport extracts an encReport object from the Database

* Server and returning it to the calling program. getReport

* calls the Name Serve to get the location of the next

* available database server. If the database server is

* located, an encReport object is extracted from the Database

* server and returned to the calling program; otherwise, an

* exception is thrown and an error message is printed to the

* standard output.

* inputs: none

* outputs: none

* return value: encReport, Blowfish encrypted data

*/

encReport getReport() throws RemoteException;

}

frontEndSvrInterface2.java

package clientPkg;

import java.rmi.*;

/*

* interface: frontEndSvrInterface2

* description: front end server remote methods

* note: all remote methods must throw RemoteException

*/

public interface frontEndSvrInterface2 extends Remote

{

/*

* function: frontEndSvrStatus

* description: frontEndSvrStatus returns a true value to the calling

* program to indicate that the Front End Server is alive

* inputs: none

* outputs: none

* return value: boolean, true if Front End Server is alive,

* none otherwise

*/

boolean frontEndSvrStatus() throws RemoteException;

/*

* function: submitInvoiceToFrontEndSvr

* description: submitInvoiceToFrontEndSvr forwards the invoice object it

* receives to a database server. submitInvoiceToFrontEndSvr

* calls the Name Server to get the location of the next

* available database server. if a database server is

* located, the invoice object is fowarded; otherwise, an

* exception is thrown and an error message is printed to

* standard output.

* inputs: invoice objInvoice

* outputs: none

* return value: none

*/

void submitInvoiceToFrontEndSvr(invoice objInvoice) throws RemoteException;

/*

* function: getReport

* description: getReport extracts an encReport object from the Database

* Server and returning it to the calling program. getReport

* calls the Name Serve to get the location of the next

* available database server. If the database server is

* located, an encReport object is extracted from the Database

* server and returned to the calling program; otherwise, an

* exception is thrown and an error message is printed to the

* standard output.

* inputs: none

* outputs: none

* return value: encReport, Blowfish encrypted data

*/

encReport getReport() throws RemoteException;

}

invoice.java

package clientPkg;

import java.io.*;

/*

* invoice:

* description: invoice form data

*/

public class invoice implements Serializable

{

byte[] byteBillName;

byte[] byteBillAddress;

byte[] byteBillCity;

byte[] byteBillState;

byte[] byteBillZip;

byte[] byteShipName;

byte[] byteShipAddress;

byte[] byteShipCity;

byte[] byteShipState;

byte[] byteShipZip;

byte[] byteQty0;

byte[] byteItem0;

byte[] bytePrice0;

byte[] byteExtend0;

byte[] byteQty1;

byte[] byteItem1;

byte[] bytePrice1;

byte[] byteExtend1;

byte[] byteQty2;

byte[] byteItem2;

byte[] bytePrice2;

byte[] byteExtend2;

byte[] byteQty3;

byte[] byteItem3;

byte[] bytePrice3;

byte[] byteExtend3;

byte[] byteQty4;

byte[] byteItem4;

byte[] bytePrice4;

byte[] byteExtend4;

byte[] byteSubTotal;

byte[] byteTax;

byte[] byteTotal;

}

nameSvr.java

package clientPkg;

import java.rmi.*;

import java.rmi.registry.*;

import java.rmi.server.*;

import java.io.*;

import java.math.BigInteger;

import java.security.*;

import java.security.spec.*;

import java.security.interfaces.*;

import javax.crypto.*;

import javax.crypto.spec.*;

import javax.crypto.interfaces.*;

import com.sun.crypto.provider.SunJCE;

/*

* class: nameSvr

* description:

* inputs: none

* outputs: none

* return value: none

*/

public class nameSvr extends UnicastRemoteObject implements nameSvrInterface

{

static int intGetDbIndex = 0;

static int intAddDbIndex = 0;

int intSizeOfQueue = 100;

String[] strDbQueue = new String[intSizeOfQueue];

dbSvrInterface objDBSvr;

/*

* function: nameSvr

* description: constructor

* inputs: none

* outputs: none

* return value: none

*/

public nameSvr() throws RemoteException

{

super();

}

/*

* function: getDbSvr

* description: return the next available database server to the calling

* program. the name server keeps track of all

* available database servers. in an effort to load balance,

* the name server distributes the workload to all database

* servers in a round robin fashion. the name server will

* make sure a database server is alive before returning it

* to the calling program. if no database server is

* available, an empty string is returned.

* inputs: none

* outputs: none

* return value: string, the location of a database server if one is

* available, an empty string otherwise

*/

public String getDbSvr()

{

int intTmpIndex = intGetDbIndex;

String strSvrFound = "";

do

{

if (strDbQueue[intTmpIndex] != null &&

!strDbQueue[intTmpIndex].equals(""))

{

try

{

// attach to strDbQueue[intTmpIndex];

System.out.println("getDbSvr has been called...");

objDBSvr = (dbSvrInterface) Naming.lookup(strDbQueue[

intTmpIndex]);

if (objDBSvr.dbSvrStatus())

{

System.out.println("dbSvr " + intTmpIndex + " is active");

strSvrFound = strDbQueue[intTmpIndex];

intTmpIndex = (intTmpIndex + 1) % intSizeOfQueue;

intGetDbIndex = intTmpIndex;

}

}

catch (Exception e) {

strDbQueue[intTmpIndex] = "";

System.out.println ("dbSvr " + intTmpIndex + " is now offline");

intTmpIndex = (intTmpIndex + 1) % intSizeOfQueue;

}

}

else

{

intTmpIndex = (intTmpIndex + 1) % intSizeOfQueue;

}

}

while (intTmpIndex != intGetDbIndex);

return (strSvrFound);

}

/*

* function: regDbSvr

* description: registers a database server, to be retrieved later by

* getDbSvr

* inputs: String strServer, location and name of the database

* server to be registered

* outputs: none

* return value: boolean, true if database server registration is

* successful, false otherwise

*/

public boolean regDbSvr(String strServer)

{

int intTmpIndex = intAddDbIndex;

boolean blSvrAdded = false;

do

{

System.out.println("regDbSvr has been called...");

if (strDbQueue[intTmpIndex] == null ||

strDbQueue[intTmpIndex].equals("")) {

strDbQueue[intTmpIndex] = strServer;

blSvrAdded = true;

System.out.println("DB Server " + intTmpIndex + " added.");

intAddDbIndex = intTmpIndex;

}

else {

intTmpIndex = (intTmpIndex + 1) % intSizeOfQueue;

}

}

while (intTmpIndex != intAddDbIndex);

return (blSvrAdded);

}

/*

* function: nameSvrStatus

* description: nameSvrStatus returns a true value to the calling

* program to indicate that the Front End Server is alive

* inputs: none

* outputs: none

* return value: boolean, true if Front End Server is alive,

* none otherwise

*/

public boolean nameSvrStatus() throws RemoteException

{

System.out.println("nameSvrStatus has been called");

return (true);

}

static KeyAgreement serverKeyAgree;

static PublicKey clientPubKey;

/*

* function: getServerPubKeyEnc

* description: given a encrypted public key from the calling application,

* getServerPubKeyEnc returns the name server's public key,

* encrypted using the diffie hellman algorithm. the client

* public key is decrypted using dh, and a server public

* key is generated based on the client public key. the

* server public key is encrypted using dh, and returned to

* the calling program.

*

* inputs: byte[] clientPubKeyEnc, dh encrypted client public key

* outputs: none

* return value: byte[], dh encrypted server public key

*/

public byte[] getServerPubKeyEnc (byte[] clientPubKeyEnc)

throws RemoteException

{

byte[] serverPubKeyEnc = null;

try

{

// server decodes app's public key from app's encoded public key

KeyFactory serverKeyFac = KeyFactory.getInstance("DH");

X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec

(clientPubKeyEnc);

clientPubKey = serverKeyFac.generatePublic(x509KeySpec);

// server generates its own public key

DHParameterSpec dhParamSpec = ((DHPublicKey) clientPubKey).getParams();

KeyPairGenerator serverKpairGen = KeyPairGenerator.getInstance("DH");

serverKpairGen.initialize(dhParamSpec);

KeyPair serverKpair = serverKpairGen.generateKeyPair();

serverKeyAgree = KeyAgreement.getInstance("DH");

serverKeyAgree.init(serverKpair.getPrivate());

serverKeyAgree.doPhase(clientPubKey, true);

// server encodes its public key

serverPubKeyEnc = serverKpair.getPublic().getEncoded();

}

catch (Exception e)

{

System.out.println ("getServerPubKeyEnc error: " + e.getMessage());

}

return (serverPubKeyEnc);

}

/*

* function: getServerEncMsg

* description: a diffie hellman encrytped message is generated using

* the calling program's secret key. the message is a

* key to be used by blowfish to encrypted and decrypt

* data messages

* inputs: none

* outputs: none

* return value: byte[], dh encrypted message that contains a secret key

* to be used by blowfish

*/

public byte[] getServerEncMsg() throws RemoteException

{

byte[] ciphertext = null;

try

{

// generate server-app secret key

serverKeyAgree.doPhase(clientPubKey, true);

SecretKey serverDesKey = serverKeyAgree.generateSecret("DES");

// create encrypted message in ECB mode based on secret key

Cipher serverCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");

serverCipher.init(Cipher.ENCRYPT_MODE, serverDesKey);

byte[] cleartext = new byte[20];

for (int i = 0; i < 20; i++)

cleartext[i] = (byte) ( (i + 1) & 0xff);

ciphertext = serverCipher.doFinal(cleartext);

}

catch (Exception e)

{

System.out.println ("getServerEncMsg error: " + e.getMessage());

}

return (ciphertext);

}

/*

* function: main

* description: main registers the name server with the local registry

* inputs: none

* outputs: none

* return value: none

*/

public static void main(String arguments[]) throws RemoteException

{

System.out.println("*** nameSvr starting ***");

Registry regNameSvr;

String strNameSvrLoc = "rmi://localhost:6969/nameSvr";

try

{

regNameSvr = LocateRegistry.createRegistry(6969);

nameSvrInterface objNameSvr = new nameSvr();

Naming.rebind(strNameSvrLoc, objNameSvr);

System.out.println("nameSvr registered successfully...");

}

catch (Exception e)

{

System.out.println("nameSvr error: " + e.getMessage());

}

}

}

nameSvrInterface.java

package clientPkg;

import java.rmi.*;

/*

* interface: nameSvrInterface

* description: name server remote methods

* note: all remote methods must throw RemoteException

*/

public interface nameSvrInterface extends Remote

{

/*

* function: getDbSvr

* description: return the next available database server to the calling

* program. the name server keeps track of all

* available database servers. in an effort to load balance,

* the name server distributes the workload to all database

* servers in a round robin fashion. the name server will

* make sure a database server is alive before returning it

* to the calling program. if no database server is

* available, an empty string is returned.

* inputs: none

* outputs: none

* return value: string, the location of a database server if one is

* available, an empty string otherwise

*/

String getDbSvr () throws RemoteException;

/*

* function: regDbSvr

* description: registers a database server, to be retrieved later by

* getDbSvr

* inputs: String strServer, location and name of the database

* server to be registered

* outputs: none

* return value: boolean, true if database server registration is

* successful, false otherwise

*/

boolean regDbSvr(String strServer) throws RemoteException;

/*

* function: nameSvrStatus

* description: nameSvrStatus returns a true value to the calling

* program to indicate that the Front End Server is alive

* inputs: none

* outputs: none

* return value: boolean, true if Front End Server is alive,

* none otherwise

*/

boolean nameSvrStatus () throws RemoteException;

/*

* function: getServerPubKeyEnc

* description: given a encrypted public key from the calling application,

* getServerPubKeyEnc returns the name server's public key,

* encrypted using the diffie hellman algorithm. the client

* public key is decrypted using dh, and a server public

* key is generated based on the client public key. the

* server public key is encrypted using dh, and returned to

* the calling program.

*

* inputs: byte[] clientPubKeyEnc, dh encrypted client public key

* outputs: none

* return value: byte[], dh encrypted server public key

*/

byte[] getServerPubKeyEnc (byte[] clientPubKeyEnc) throws RemoteException;

/*

* function: getServerEncMsg

* description: a diffie hellman encrytped message is generated using

* the calling program's secret key. the message is a

* key to be used by blowfish to encrypted and decrypt

* data messages

* inputs: none

* outputs: none

* return value: byte[], dh encrypted message that contains a secret key

* to be used by blowfish

*/

byte[] getServerEncMsg() throws RemoteException;

}

report.java

package clientPkg;

import java.io.*;

public class report implements Serializable{

int intCpuQty;

float fltCpuPrice;

float fltCpuExtend;

int intKbQty;

float fltKbPrice;

float fltKbExtend;

int intMemQty;

float fltMemPrice;

float fltMemExtend;

int intMonitorQty;

float fltMonitorPrice;

float fltMonitorExtend;

float fltSubTotal;

float fltTax;

float fltTotal;

}

rmi.policy

grant

{

// Allow everything to contact servers

permission .SocketPermission "*:1024-65535", "accept, connect, listen";

};

BIBLIOGRAPHY

[1] What is Diffie-Hellman,

[2] The Blowfish Encryption Algorithm,

[3] Java Technology,

[4] Java Remote Method Invocation (Java RMI),

[5] Java Foundation Classes (JFC/Swing),

................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download