Inside Java

Java Security API - Example


 

Introduction

The Java Security API is a new Java core API. The first release of Java Security in JDK 1.1 contains a subset of cryptography functionality, including APIs for digital signatures and message digests. In addition, there are abstract interfaces for key management and certificate management.

An example

This advanced example supposes that you are familiar with Object Serialization and Streams (including sockets). It is based on a client-server architecture.

The client reads a file, generates a pair of key, signs the content of a file and send an object through the network to a server. This object contains the public key generated by the client, the signature, and the content of the file.
The server then receives this object, and verifies that the signature is correct.

This example may be a good starting point to understand for example how a SSL browser works, and how the Java Security API may be used in client-server applications.

Source files:

There are 4 files: Main.java, Client.java, Server.java, signedData.java.
You can download them:

Main.java

import java.net.*;
import java.io.*;


class Main {
   
    public static void main(String [] argv)
    {
        try {
            Server s=new Server();
            s.startServer();
        } catch (IOException e) {};
    }
   
}

The main class simply starts the Server that listens on a port (4096).

Client.java

import java.net.*;
import java.io.*;
import java.security.*;

class Client {
   
   
    public static void main(String [] argv)
    {
       
        try {
           
            Socket s=new Socket("localhost",4096);
           
            System.out.println("Generating keys...");           
            ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
           
            //Generates keys
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
            keyGen.initialize(256);
            KeyPair pair = keyGen.generateKeyPair();
            System.out.println("Keys generated.");
           
            //Generates signature object
            Signature dsa = Signature.getInstance("SHA/DSA");
            PublicKey pub=pair.getPublic();
            PrivateKey priv=pair.getPrivate();
            dsa.initSign(priv);
            System.out.println("Signature object generated.");
           
            //Read the input file and computes a signature
            FileInputStream fis = new FileInputStream(argv[0]);
            byte[] b=new byte[fis.available()];
            fis.read(b);
            dsa.update(b);
           
            //Build the signedData and send it           
            signedData Data=new signedData(b,dsa.sign(),pub);
            Data.printKey();
            oos.writeObject(Data);
           
            //Close streams
            fis.close();
            oos.close();
            s.close();
           
        } catch (Exception e) {System.out.println(e);};
    }
   
}

You have to launch the Client using java Client file, where file is the filename you want to send to the server.

The client class creates a pair of key (256 bytes) and a signature object. This Signature class is used to provide the functionality of a digital signature algorithm, such as RSA with MD5 or DSA. Here we use the DSA algorithm.
Then, it reads the file supplied on the command line and computes a digital signature. A signedData object is created with the content of the file, the client's public key and the digital signature. It's then sent to the server using serialization through an ObjectOutputStream.

Server.java

import java.net.*;
import java.io.*;
import java.security.*;

class Server implements Runnable
{
   
    ServerSocket server=null;
    Socket data=null;
    Thread t=null;
    KeyPairGenerator keyGen;
    KeyPair pair;
   
    public synchronized void startServer() throws IOException {
        if (t==null)
        {
            server=new ServerSocket(4096);
            t=new Thread(this);
            t.start();
        }
    }
   
    public synchronized void stopServer() throws IOException {
        if (t!=null)
        {
            t=null;
            server.close();
        }
       
    }
   
    public void run()
    {
        Thread thisThread=Thread.currentThread();
        System.out.println("Ready to accept connections.");
        while (t==thisThread) {
            try {
                Socket data=server.accept();
                process(data);
            } catch( Exception e) {}
        }
    }
   
    private void process(Socket data) throws IOException
    {
       
        System.out.println("Accepting connexion...");
        try {
           
            ObjectInputStream ois=new ObjectInputStream(data.getInputStream());
           
            //Read the object from the network
            signedData Data=(signedData)ois.readObject();
           
            //Generate the signature object
            Signature dsa = Signature.getInstance("SHA/DSA");
            dsa.initVerify(Data.pub);
            dsa.update(Data.b);
           
            //Verify the signature
            Data.printKey();
            boolean verifies = dsa.verify(Data.sig);
            System.out.println(verifies?"Signature is correct!":"Signature not valid!");
                       
            ois.close();
            data.close();
           
} catch (Exception e) {System.out.println(e);}
    }
   
}

You have to launch the Server using java Server.

The Server class waits for an incoming connection using a ServerSocket. When a connection is made, it reads a signedData object from the stream, and computes a digital signature using the client's public key to verify that the file transmitted from the client is valid.

signedData.java

import java.io.*;
import java.security.*;

public class signedData implements Serializable
{
    byte[] b;
    byte[] sig;
    PublicKey pub;
   
    signedData(byte b[],byte [] sig ,PublicKey pub)      {
        this.b=b;
        this.sig=sig;
        this.pub=pub;
    }
   
   
    void printKey() {
        System.out.println("Key dump:");
        System.out.println(pub);
    }
   
}


This class is sent through the network from the client to the server. It contains an array of byte, a digital signature, and a public key.

Here is the output from the client:

>java Client test.txt
Generating keys...
Keys generated.
Signature object generated.
Key dump:
Sun DSA Public Key
parameters:
p: 8785376389fcfa2159500dc13478a8e59edf2aab2a5aee306e67cce131057901
q: eeebb693f22a2a87c2ddd97de1ae15cc2aebb847
g: 625fcdb4c32d298519ca9512a9fc741c58d489627ce8c3ef489e7d532e63b9a1

y: 1ee472813899e17acbeb396d5b78bee0e433f9091b838c92a05d36a3f60192ac

Here is the output from the server:

>java Main
Ready to accept connections.
Accepting connexion...
Key dump:
Sun DSA Public Key
parameters:
p: 8785376389fcfa2159500dc13478a8e59edf2aab2a5aee306e67cce131057901
q: eeebb693f22a2a87c2ddd97de1ae15cc2aebb847
g: 625fcdb4c32d298519ca9512a9fc741c58d489627ce8c3ef489e7d532e63b9a1

y: 1ee472813899e17acbeb396d5b78bee0e433f9091b838c92a05d36a3f60192ac

Signature is correct!

Conclusion

Java 1.1 provides a number of important new features. The new Java security API offers good security functionalities. This example shows that the security API is very easy to use (verifying a signature is straightforward). Therefore, don't hesitate to use it in your applications.

 

This page was last updated 06 March 1998