JDK Tutorials - Herong's Tutorial Notes
Dr. Herong Yang, Version 4.32, 2006

JCA - Digital Signature

Part:   1  2  3  4  5  

JDK Tutorials - Herong's Tutorial Notes © Dr. Herong Yang

Internationalization

Character Set and Encoding

Socket Communication

Document Object Model (DOM)

XSD Validation in Java

XSL - Transformer in Java

JCA - Private and Public Key Pairs

JCE - Secret Key

SSL (Secure Socket Layer)

SSL - Client Authentication

... Table of Contents

(Continued from previous part...)

Signature Verification Program - JcaVerify.java

The following program is a standalone program that reads in an input file, a signature file and a public key file, and verifies that if the signature file matches the input file based on the specified digital signature algorithm.

/**
 * JcaVerify.java
 * Copyright (c) 2002 by Dr. Herong Yang
 */
import java.io.*;
import java.security.*;
import java.security.spec.*;
class JcaVerify {
   public static void main(String[] a) {
      if (a.length<5) {
         System.out.println("Usage:");
         System.out.println("java JcaVerify input signFile"
            +" signAlgo keyFile keyAlgo");
         return;
      }
      String input = a[0];
      String signFile = a[1];
      String signAlgo = a[2];  // SHA1withDSA, SHA1withRSA,
      String keyFile = a[3];
      String keyAlgo = a[4]; // DSA, RSA
      try {
         PublicKey pubKey = readPublicKey(keyFile,keyAlgo);
         byte[] sign = readSignature(signFile);
         verify(input,signAlgo,sign,pubKey);
      } catch (Exception e) {
         System.out.println("Exception: "+e);
         return;
      }
   }
   private static PublicKey readPublicKey(String input,
         String algorithm) throws Exception {
      FileInputStream pubKeyStream = new FileInputStream(input);
      int pubKeyLength = pubKeyStream.available();
      byte[] pubKeyBytes = new byte[pubKeyLength];
      pubKeyStream.read(pubKeyBytes);
      pubKeyStream.close();
      X509EncodedKeySpec pubKeySpec 
         = new X509EncodedKeySpec(pubKeyBytes);
      KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
      PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
      System.out.println();
      System.out.println("Public Key Info: ");
      System.out.println("Algorithm = "+pubKey.getAlgorithm());
      System.out.println("Saved File = "+input);
      System.out.println("Length = "+pubKeyBytes.length);
      System.out.println("toString = "+pubKey.toString());
      return pubKey;
   }
   private static byte[] readSignature(String input) 
         throws Exception {
      FileInputStream signStream = new FileInputStream(input);
      int signLength = signStream.available();
      byte[] signBytes = new byte[signLength];
      signStream.read(signBytes);
      signStream.close();
      return  signBytes;
   }
   private static boolean verify(String input, String algorithm, 
         byte[] sign, PublicKey pubKey) throws Exception {
      Signature sg = Signature.getInstance(algorithm);
      sg.initVerify(pubKey);
      System.out.println();
      System.out.println("Signature Object Info: ");
      System.out.println("Algorithm = "+sg.getAlgorithm());
      System.out.println("Provider = "+sg.getProvider());
      FileInputStream in = new FileInputStream(input);
      int bufSize = 1024;
      byte[] buffer = new byte[bufSize];
      int n = in.read(buffer,0,bufSize);
      int count = 0;
      while (n!=-1) {
         count += n;
         sg.update(buffer,0,n);
         n = in.read(buffer,0,bufSize);
      }
      in.close();
      boolean ok = sg.verify(sign);
      System.out.println("Verify Processing Info: ");
      System.out.println("Number of input bytes = "+count);
      System.out.println("Verification result = "+ok);
      return ok;
   }
}

Here is result of my first test to verify a signature generated with the DSA algorithm and the SHA1withDSA algorithm. See the previous section for more information.

java -cp . JcaVerify JcaSign.class JcaSign.sgn SHA1withDSA dsa.pub DSA

Public Key Info:
Algorithm = DSA
Saved File = dsa.pub
Length = 243
toString = Sun DSA Public Key
Parameters:DSA
p:    
fca682ce 8e12caba 26efccf7 110e526d b078b05e decbcd1e b4a208f3 ae1617ae
01f35b91 a47e6df6 3413c5e1 2ed0899b cd132acd 50d99151 bdc43ee7 37592e17
q:     
962eddcc 369cba8e bb260ee6 b6a126d9 346e38c5
g:     
678471b2 7a9cf44e e91a49c5 147db1a9 aaf244f0 5a434d64 86931d2d 14271b9e
35030b71 fd73da17 9069b32e 2935630e 1c206235 4d0da20a 6c416e50 be794ca4

y:
2cf7c9ba a2dd3ce5 0e2d6384 122951fa a956ebd9 573a5168 ce9c0a83 b8c63348
ce5c5d65 b35c8c81 beb9206b 8cf36587 0b24e605 a0150dbe a40dd57d 64b42b8a

Signature Object Info:
Algorithm = SHA/DSA
Provider = SUN version 1.2
Verify Processing Info:
Number of input bytes = 2940
Verification result = true

Yes. The program is working correctly. Here is another on the signature generated with RSA and MD2withRSA algorithms.

java -cp . JcaVerify JcaSign.class JcaSign_rsa.sgn MD2withRSA rsa.pub RSA

Public Key Info:
Algorithm = RSA
Saved File = rsa.pub
Length = 94
toString = com.sun.rsajca.JSA_RSAPublicKey@12e78c

Signature Object Info:
Algorithm = MD2withRSA
Provider = SunRsaSign version 1.0
Verify Processing Info:
Number of input bytes = 2940
Verification result = true

Conclusions:

  • Generating and verification digital signatures are done by encrypting and decrypting the message digest of the input data with private keys and public keys.
  • The Signature class requires the help of the KeyPairGenerator class and the KeyFactory class.
  • Sun provides several digital signature algorithms: SHA1withDSA, SHA1withRSA, MD2withDSA, and MD2withRSA.
  • Of course, you must choose a digital signature algorithm that is compatible with the keys.
  • Keys are stored in files in encoded formats. The default encoding for private key is PKCS#8, and the default encoding for public key is X.509.

Part:   1  2  3  4  5  

Dr. Herong Yang, updated in 2006
JDK Tutorials - Herong's Tutorial Notes - JCA - Digital Signature