Friday, May 21, 2010

Digital Signature in java

The basic idea in the use of digital signatures is as follows.

  1. You "sign" the document or code using one of your private keys, which you can generate by using keytool or security API methods. That is, you generate a digital signature for the document or code, using the jarsigner tool or Security API methods.
  2. You send your signed document to your recipient.
  3. You also supply your recipient with your public key. This public key corresponds to the private key you originally used to generate the signature.
  4. Your recipient uses your public key to verify that your document came from you and was not modified before it reached him/her.
A recipient needs to ensure that your public key itself is authentic before he/she can use it to verify that your signature is authentic. Therefore, you will usually supply a certificate that contains your public key together with the key of a Certificate Authority who can vouch for your key's authenticity. See the next section for details.

Generating and Verifying Signatures
This lesson walks you through the steps necessary to use the JDK Security API to generate a digital signature for data and to verify that a signature is authentic. This lesson is meant for developers who wish to incorporate security functionality into their programs, including cryptography services.
This lesson demonstrates the use of the JDK Security API with respect to signing documents. The lesson shows what one program, executed by the person who has the original document, would do to generate keys, generate a digital signature for the document using the private key, and export the public key and the signature to files.
Then it shows an example of another program, executed by the receiver of the document, signature, and public key. It shows how the program could import the public key and verify the authenticity of the signature. The lesson also discusses and demonstrates possible alternative approaches and methods of supplying and importing keys, including in certificates.
For further information about the concepts and terminology (digital signatures, certificates, keystores), see the API and Tools Use for Secure Code and File Exchanges lesson.
In this lesson you create two basic applications, one for the digital signature generation and the other for the verification. This is followed by a discussion and demonstration of potential enhancements. The lesson contains three sections.
  • Generating a Digital Signature shows using the API to generate keys and a digital signature for data using the private key and to export the public key and the signature to files. The application gets the data file name from the command line.
  • Verifying a Digital Signature shows using the API to import a public key and a signature that is alleged to be the signature of a specified data file and to verify the authenticity of the signature. The data, public key, and signature file names are specified on the command line.
  • Weaknesses and Alternatives discusses potential weaknesses of the approach used by the basic programs. It then presents and demonstrates possible alternative approaches and methods of supplying and importing keys, including the use of files containing encoded key bytes and the use of certificates containing public keys.
 Generating a Digital Signature
  • The GenSig program you are about to create will use the JDK Security API to generate keys and a digital signature for data using the private key and to export the public key and the signature to files. The application gets the data file name from the command line.
    The following steps create the GenSig sample program.
    1. Prepare Initial Program Structure Create a text file named GenSig.java. Type in the initial program structure (import statements, class name, main method, and so on).
    2. Generate Public and Private Keys Generate a key pair (public key and private key). The private key is needed for signing the data. The public key will be used by the VerSig program for verifying the signature.
    3. Sign the Data Get a Signature object and initialize it for signing. Supply it with the data to be signed, and generate the signature.
    4. Save the Signature and the Public Key in Files Save the signature bytes in one file and the public key bytes in another.
    5. Compile and Run the Program
Prepare Initial Program Structure
Here's the basic structure of the GenSig program. Place it in a file called GenSig.java.
import java.io.*;
import java.security.*;

class GenSig {

    public static void main(String[] args) {

        /* Generate a DSA signature */

        if (args.length != 1) {
            System.out.println("Usage: GenSig nameOfFileToSign");
            }
        else try {

        // the rest of the code goes here

        } catch (Exception e) {
            System.err.println("Caught exception " + e.toString());
        }
    }

}

Notes:
  • The methods for signing data are in the java.security package, so the program imports everything from that package. The program also imports the java.io package, which contains the methods needed to input the file data to be signed.
  • A single argument is expected, specifying the data file to be signed.
  • The code written in subsequent steps will go between the try and the catch blocks.

Generate Public and Private Keys
In order to be able to create a digital signature, you need a private key. (Its corresponding public key will be needed in order to verify the authenticity of the signature.)
In some cases the key pair (private key and corresponding public key) are already available in files. In that case the program can import and use the private key for signing, as shown in Weaknesses and Alternatives.
In other cases the program needs to generate the key pair. A key pair is generated by using the KeyPairGenerator class.
In this example you will generate a public/private key pair for the Digital Signature Algorithm (DSA). You will generate keys with a 1024-bit length.
Generating a key pair requires several steps:
Create a Key Pair Generator
The first step is to get a key-pair generator object for generating keys for the DSA signature algorithm.
As with all engine classes, the way to get a KeyPairGenerator object for a particular type of algorithm is to call the getInstance static factory method on the KeyPairGenerator class. This method has two forms, both of which hava a String algorithm first argument; one form also has a String provider second argument.
A caller may thus optionally specify the name of a provider, which will guarantee that the implementation of the algorithm requested is from the named provider. The sample code of this lesson always specifies the default SUN provider built into the JDK.
Put the following statement after the
else try {
line in the file created in the previous step, Prepare Initial Program Structure:
KeyPairGenerator keyGen =
    KeyPairGenerator.getInstance("DSA", "SUN");
Initialize the Key-Pair Generator
The next step is to initialize the key-pair generator. All key-pair generators share the concepts of a keysize and a source of randomness. The KeyPairGenerator class has an initialize method that takes these two types of arguments.
The keysize for a DSA key generator is the key length (in bits), which you will set to 1024.
The source of randomness must be an instance of the SecureRandom class. This example requests one that uses the SHA1PRNG pseudo-random-number generation algorithm, as provided by the built-in SUN provider. The example then passes this SecureRandom instance to the key-pair generator initialization method.
SecureRandom random =
    SecureRandom.getInstance("SHA1PRNG", "SUN");
keyGen.initialize(1024, random);
Note: The SecureRandom implementation attempts to completely randomize the internal state of the generator itself unless the caller follows the call to the getInstance method with a call to the setSeed method. So if you had a specific seed value that you wanted used, you would call the following prior to the initialize call:
random.setSeed(seed);
Generate the Pair of Keys
 
The final step is to generate the key pair and to store the keys in PrivateKey and PublicKey objects.
KeyPair pair = keyGen.generateKeyPair();
PrivateKey priv = pair.getPrivate();
PublicKey pub = pair.getPublic();
In order to be able to create a digital signature, you need a private key. (Its corresponding public key will be needed in order to verify the authenticity of the signature.)
In some cases the key pair (private key and corresponding public key) are already available in files. In that case the program can import and use the private key for signing, as shown in Weaknesses and Alternatives.
In other cases the program needs to generate the key pair. A key pair is generated by using the KeyPairGenerator class.
In this example you will generate a public/private key pair for the Digital Signature Algorithm (DSA). You will generate keys with a 1024-bit length.
Generating a key pair requires several steps: 

Create a Key Pair Generator
The first step is to get a key-pair generator object for generating keys for the DSA signature algorithm.
As with all engine classes, the way to get a KeyPairGenerator object for a particular type of algorithm is to call the getInstance static factory method on the KeyPairGenerator class. This method has two forms, both of which hava a String algorithm first argument; one form also has a String provider second argument.
A caller may thus optionally specify the name of a provider, which will guarantee that the implementation of the algorithm requested is from the named provider. The sample code of this lesson always specifies the default SUN provider built into the JDK.
Put the following statement after the
else try {
line in the file created in the previous step, Prepare Initial Program Structure:
KeyPairGenerator keyGen =
    KeyPairGenerator.getInstance("DSA", "SUN");
Initialize the Key-Pair Generator
The next step is to initialize the key-pair generator. All key-pair generators share the concepts of a keysize and a source of randomness. The KeyPairGenerator class has an initialize method that takes these two types of arguments.
The keysize for a DSA key generator is the key length (in bits), which you will set to 1024.
The source of randomness must be an instance of the SecureRandom class. This example requests one that uses the SHA1PRNG pseudo-random-number generation algorithm, as provided by the built-in SUN provider. The example then passes this SecureRandom instance to the key-pair generator initialization method.
SecureRandom random =
    SecureRandom.getInstance("SHA1PRNG", "SUN");
keyGen.initialize(1024, random);
Note: The SecureRandom implementation attempts to completely randomize the internal state of the generator itself unless the caller follows the call to the getInstance method with a call to the setSeed method. So if you had a specific seed value that you wanted used, you would call the following prior to the initialize call:
random.setSeed(seed);
Generate the Pair of Keys
The final step is to generate the key pair and to store the keys in PrivateKey and PublicKey objects.
KeyPair pair = keyGen.generateKeyPair();
PrivateKey priv = pair.getPrivate();
PublicKey pub = pair.getPublic();

Sign the Data
Now that you have created a public key and a private key, you are ready to sign the data. In this example you will sign the data contained in a file. GenSig gets the file name from the command line. A digital signature is created (or verified) using an instance of the Signature class.
Signing data, generating a digital signature for that data, is done with the following steps.
Get a Signature Object:
The following gets a Signature object for generating or verifying signatures using the DSA algorithm, the same algorithm for which the program generated keys in the previous step, Generate Public and Private Keys.
Signature dsa = Signature.getInstance("SHA1withDSA", "SUN"); 
Note: When specifying the signature algorithm name, you should also include the name of the message digest algorithm used by the signature algorithm. SHA1withDSA is a way of specifying the DSA signature algorithm, using the SHA-1 message digest algorithm.
Initialize the Signature Object
Before a Signature object can be used for signing or verifying, it must be initialized. The initialization method for signing requires a private key. Use the private key placed into the PrivateKey object named priv in the previous step.
dsa.initSign(priv);
Supply the Signature Object the Data to Be Signed
This program will use the data from the file whose name is specified as the first (and only) command line argument. The program will read in the data a buffer at a time and will supply it to the Signature object by calling the update method.
FileInputStream fis = new FileInputStream(args[0]);
BufferedInputStream bufin = new BufferedInputStream(fis);
byte[] buffer = new byte[1024];
int len;
while ((len = bufin.read(buffer)) >= 0) {
    dsa.update(buffer, 0, len);
};
bufin.close();
Generate the Signature
Once all of the data has been supplied to the Signature object, you can generate the digital signature of that data.
byte[] realSig = dsa.sign();
Save the Signature and the Public Key in Files
Now that you have generated a signature for some data, you need to save the signature bytes in one file and the public key bytes in another so you can send (via modem, floppy, mail, and so on) someone else
  • the data for which the signature was generated,
  • the signature, and
  • the public key
The receiver can verify that the data came from you and was not modified in transit by running the VerSig program you will generate in the upcoming Verifying a Digital Signature steps. That program uses the public key to verify that the signature received is the true signature for the data received. Recall that the signature was placed in a byte array named realSig. You can save the signature bytes in a file named sig via the following.
/* save the signature in a file */
        FileOutputStream sigfos = new FileOutputStream("sig");
        sigfos.write(realSig);
        sigfos.close();
Recall from the Generate Public and Private Keys step that the public key was placed in a PublicKey object named pub. You can get the encoded key bytes by calling the getEncoded method and then store the encoded bytes in a file. You can name the file whatever you want. If, for example, your name is Susan, you might name it something like suepk (for "Sue's public key"), as in the following:
/* save the public key in a file */
        byte[] key = pub.getEncoded();
        FileOutputStream keyfos = new FileOutputStream("suepk");
        keyfos.write(key);
        keyfos.close();
Compile and Run the Program
Here is the complete source code for the GenSig.java program, with some comments added. Compile and run it. Remember, you need to specify the name of a file to be signed, as in
java GenSig data
You can download and use this sample file named data or any other file you like. The file will not be modified. It will be read so that a signature can be generated for it.
After executing the program, you should see the saved suepk (public key) and sig (signature) files.

Verifying a Digital Signature
If you have data for which a digital signature was generated, you can verify the authenticity of the signature. To do so, you need
  • the data
  • the signature
  • the public key corresponding to the private key used to sign the data
In this example you write a VerSig program to verify the signature generated by the GenSig program. This demonstrates the steps required to verify the authenticity of an alleged signature.
VerSig imports a public key and a signature that is alleged to be the signature of a specified data file and then verifies the authenticity of the signature. The public key, signature, and data file names are specified on the command line.
The steps to create the VerSig sample program to import the files and to verify the signature are the following.
  1. Prepare Initial Program Structure Create a text file named VerSig.java. Type in the initial program structure (import statements, class name, main method, and so on).
  2. Input and Convert the Encoded Public Key Bytes Import the encoded public key bytes from the file specified as the first command line argument and convert them to a PublicKey.
  3. Input the Signature Bytes Input the signature bytes from the file specified as the second command line argument.
  4. Verify the Signature Get a Signature object and initialize it with the public key for verifying the signature. Supply it with the data whose signature is to be verified (from the file specified as the third command line argument), and verify the signature.
  5. Compile and Run the Program


No comments: