home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / security / MessageDigest.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  14.8 KB  |  491 lines

  1. /*
  2.  * @(#)MessageDigest.java    1.51 98/03/18
  3.  *
  4.  * Copyright 1996-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.security;
  16.  
  17. import java.util.*;
  18. import java.lang.*;
  19. import java.io.IOException;
  20. import java.io.ByteArrayOutputStream;
  21. import java.io.PrintStream;
  22. import java.io.InputStream;
  23. import java.io.ByteArrayInputStream;
  24.  
  25. /**
  26.  * This MessageDigest class provides applications the functionality of a
  27.  * message digest algorithm, such as MD5 or SHA.
  28.  * Message digests are secure one-way hash functions that take arbitrary-sized
  29.  * data and output a fixed-length hash value.
  30.  *
  31.  * <p>A MessageDigest object starts out initialized. The data is 
  32.  * processed through it using the <a href="#update(byte)">update</a>
  33.  * methods. At any point <a href="#reset()">reset</a> can be called
  34.  * to reset the digest. Once all the data to be updated has been
  35.  * updated, one of the <a href="#digest()">digest</a> methods should 
  36.  * be called to complete the hash computation.
  37.  *
  38.  * <p>The <code>digest</code> method can be called once for a given number 
  39.  * of updates. After <code>digest</code> has been called, the MessageDigest
  40.  * object is reset to its initialized state.
  41.  *
  42.  * <p>Implementations are free to implement the Cloneable interface.
  43.  * Client applications can test cloneability
  44.  * using <code>instanceof Cloneable</code> before attempting cloning: <p>    
  45.  *
  46.  * <pre>
  47.  * MessageDigest md = MessageDigest.getInstance("SHA");
  48.  *
  49.  * if (md instanceof Cloneable) {
  50.  *     md.update(toChapter1);
  51.  *     MessageDigest tc1 = md.clone();
  52.  *     byte[] toChapter1Digest = tc1.digest;
  53.  *     md.update(toChapter2);
  54.  *     ...etc.
  55.  * } else {
  56.  *     throw new DigestException("couldn't make digest of partial content");
  57.  * }
  58.  * </pre>
  59.  *
  60.  * <p>Note that if a given implementation is not cloneable, it is
  61.  * still possible to compute intermediate digests by instantiating
  62.  * several instances, if the number of digests is known in advance.
  63.  *
  64.  * <p>Note that this class is abstract and extends from
  65.  * <code>MessageDigestSpi</code> for historical reasons.
  66.  * Application developers should only take notice of the methods defined in
  67.  * this <code>MessageDigest</code> class, and ignore all the methods in
  68.  * the superclass.
  69.  *
  70.  * @author Benjamin Renaud 
  71.  *
  72.  * @version 1.51 98/03/18
  73.  *
  74.  * @see DigestInputStream
  75.  * @see DigestOutputStream
  76.  */
  77.  
  78. public abstract class MessageDigest extends MessageDigestSpi {
  79.  
  80.     /* Are we in debugging mode? */
  81.     private static boolean debug = false;
  82.  
  83.     /* The digest bits, if any. */
  84.     private byte[] digestBits;
  85.  
  86.     private String algorithm;
  87.  
  88.     // The provider
  89.     private Provider provider;
  90.  
  91.     /**
  92.      * Creates a message digest with the specified algorithm name.
  93.      * 
  94.      * @param algorithm the standard name of the digest algorithm. 
  95.      * See Appendix A in the <a href=
  96.      * "../guide/security/CryptoSpec.html#AppA">
  97.      * Java Cryptography Architecture API Specification & Reference </a> 
  98.      * for information about standard algorithm names.
  99.      */
  100.     protected MessageDigest(String algorithm) {
  101.     this.algorithm = algorithm;
  102.     }
  103.  
  104.     /**
  105.      * Generates a MessageDigest object that implements the specified digest
  106.      * algorithm. If the default provider package
  107.      * provides an implementation of the requested digest algorithm,
  108.      * an instance of MessageDigest containing that implementation is returned.
  109.      * If the algorithm is not available in the default 
  110.      * package, other packages are searched.
  111.      *
  112.      * @param algorithm the name of the algorithm requested. 
  113.      * See Appendix A in the <a href=
  114.      * "../guide/security/CryptoSpec.html#AppA">
  115.      * Java Cryptography Architecture API Specification & Reference </a> 
  116.      * for information about standard algorithm names.
  117.      *
  118.      * @return a Message Digest object implementing the specified
  119.      * algorithm.
  120.      *
  121.      * @exception NoSuchAlgorithmException if the algorithm is
  122.      * not available in the caller's environment.  
  123.      */
  124.     public static MessageDigest getInstance(String algorithm) 
  125.     throws NoSuchAlgorithmException { 
  126.     try {
  127.         Object[] objs = Security.getImpl(algorithm, "MessageDigest", null);
  128.         if (objs[0] instanceof MessageDigest) {
  129.         MessageDigest md = (MessageDigest)objs[0];
  130.         md.provider = (Provider)objs[1];
  131.         return md;
  132.         } else {
  133.         Delegate delegate = new Delegate((MessageDigestSpi)objs[0],
  134.                          algorithm);
  135.         delegate.provider = (Provider)objs[1];
  136.         return delegate;
  137.         }
  138.     } catch(NoSuchProviderException e) {
  139.         throw new NoSuchAlgorithmException(algorithm + " not found");
  140.     }
  141.     }
  142.  
  143.     /**
  144.      * Generates a MessageDigest object implementing the specified
  145.      * algorithm, as supplied from the specified provider, if such an 
  146.      * algorithm is available from the provider.
  147.      *
  148.      * @param algorithm the name of the algorithm requested. 
  149.      * See Appendix A in the <a href=
  150.      * "../guide/security/CryptoSpec.html#AppA">
  151.      * Java Cryptography Architecture API Specification & Reference </a> 
  152.      * for information about standard algorithm names.
  153.      *
  154.      * @param provider the name of the provider.
  155.      *
  156.      * @return a Message Digest object implementing the specified
  157.      * algorithm.
  158.      *
  159.      * @exception NoSuchAlgorithmException if the algorithm is
  160.      * not available in the package supplied by the requested
  161.      * provider.
  162.      *
  163.      * @exception NoSuchProviderException if the provider is not
  164.      * available in the environment. 
  165.      * 
  166.      * @see Provider 
  167.      */
  168.     public static MessageDigest getInstance(String algorithm, String provider)
  169.     throws NoSuchAlgorithmException, NoSuchProviderException {
  170.     Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider);
  171.     if (objs[0] instanceof MessageDigest) {
  172.         MessageDigest md = (MessageDigest)objs[0];
  173.         md.provider = (Provider)objs[1];
  174.         return md;
  175.     } else {
  176.         Delegate delegate = new Delegate((MessageDigestSpi)objs[0],
  177.                          algorithm);
  178.         delegate.provider = (Provider)objs[1];
  179.         return delegate;
  180.     }
  181.     }
  182.  
  183.     /** 
  184.      * Returns the provider of this message digest object.
  185.      * 
  186.      * @return the provider of this message digest object
  187.      */
  188.     public final Provider getProvider() {
  189.     return this.provider;
  190.     }
  191.  
  192.     /**
  193.      * Updates the digest using the specified byte.    
  194.      * 
  195.      * @param input the byte with which to update the digest.
  196.      */
  197.     public void update(byte input) {
  198.     digestBits = null;
  199.     engineUpdate(input);
  200.     }
  201.  
  202.     /**
  203.      * Updates the digest using the specified array of bytes, starting
  204.      * at the specified offset.
  205.      * 
  206.      * @param input the array of bytes.
  207.      *
  208.      * @param offset the offset to start from in the array of bytes.
  209.      *
  210.      * @param len the number of bytes to use, starting at 
  211.      * <code>offset</code>.  
  212.      */
  213.     public void update(byte[] input, int offset, int len) {
  214.     if (input == null) {
  215.         throw new IllegalArgumentException("No input buffer given");
  216.     }
  217.     if (input.length - offset < len) {
  218.         throw new IllegalArgumentException("Input buffer too short");
  219.     }
  220.     digestBits = null;
  221.     engineUpdate(input, offset, len);
  222.     }
  223.  
  224.     /**
  225.      * Updates the digest using the specified array of bytes.
  226.      * 
  227.      * @param input the array of bytes.
  228.      */
  229.     public void update(byte[] input) {
  230.     digestBits = null;
  231.     engineUpdate(input, 0, input.length);
  232.     }
  233.  
  234.     /**
  235.      * Completes the hash computation by performing final operations
  236.      * such as padding. The digest is reset after this call is made.
  237.      *
  238.      * @return the array of bytes for the resulting hash value.  
  239.      */
  240.     public byte[] digest() {
  241.     /* Resetting is the responsibility of implementors. */
  242.     digestBits = engineDigest();
  243.     return digestBits;
  244.     }
  245.  
  246.     /**
  247.      * Completes the hash computation by performing final operations
  248.      * such as padding. The digest is reset after this call is made.
  249.      *
  250.      * @param buf output buffer for the computed digest
  251.      *
  252.      * @param offset offset into the output buffer to begin storing the digest
  253.      *
  254.      * @param len number of bytes within buf allotted for the digest
  255.      *
  256.      * @return the length of the digest
  257.      * 
  258.      * @exception DigestException if an error occurs.
  259.      */
  260.     public int digest(byte[] buf, int offset, int len) throws DigestException {
  261.     if (buf == null) {
  262.         throw new IllegalArgumentException("No input buffer given");
  263.     }
  264.     if (buf.length - offset < len) {
  265.         throw new IllegalArgumentException("Input buffer too short");
  266.     }
  267.     int diglen = engineDigest(buf, offset, len);
  268.     digestBits = new byte[diglen];
  269.     System.arraycopy(buf, offset, digestBits, 0, diglen);
  270.     return diglen;
  271.     }
  272.  
  273.     /**
  274.      * Performs a final update on the digest using the specified array 
  275.      * of bytes, then completes the digest computation. That is, this
  276.      * method first calls <a href = "#update(byte[])">update</a> on the
  277.      * array, then calls <a href = "#digest()">digest()</a>.
  278.      *
  279.      * @param input the input to be updated before the digest is
  280.      * completed.
  281.      *
  282.      * @return the array of bytes for the resulting hash value.  
  283.      */
  284.     public byte[] digest(byte[] input) {
  285.     update(input);
  286.     return digest();
  287.     }
  288.  
  289.     /**
  290.      * Helper function that prints unsigned two character hex digits.
  291.      */
  292.     private static void hexDigit(PrintStream p, byte x) {
  293.     char c = (char) ((x >> 4) & 0xf);
  294.     if (c > 9) {
  295.         c = (char) ((c - 10) + 'a');
  296.     } else {
  297.         c = (char) (c + '0');
  298.     }
  299.     p.write(c);
  300.  
  301.     c = (char) (x & 0xf);
  302.     if (c > 9) {
  303.         c = (char)((c - 10) + 'a');
  304.     } else {
  305.         c = (char)(c + '0');
  306.     }
  307.     p.write(c);
  308.     }
  309.  
  310.     /**
  311.      * Returns a string representation of this message digest object.  
  312.      */
  313.     public String toString() {
  314.     ByteArrayOutputStream baos = new ByteArrayOutputStream();
  315.     PrintStream p = new PrintStream(baos);
  316.     p.print(this.getClass().getName()+" Message Digest ");
  317.     if (digestBits != null) {
  318.         p.print("<");
  319.         for (int i = 0; i < digestBits.length; i++)
  320.              hexDigit(p, digestBits[i]);
  321.         p.print(">");
  322.     } else {
  323.         p.print("<incomplete>");
  324.     }
  325.     p.println();
  326.     return (baos.toString());
  327.     }
  328.  
  329.     /**
  330.      * Compares two digests for equality. Does a simple byte compare.
  331.      * 
  332.      * @param digesta one of the digests to compare.
  333.      * 
  334.      * @param digestb the other digest to compare.    
  335.      *
  336.      * @return true if the digests are equal, false otherwise.
  337.      */
  338.     public static boolean isEqual(byte digesta[], byte digestb[]) {
  339.     if (digesta.length != digestb.length)
  340.         return false;
  341.  
  342.     for (int i = 0; i < digesta.length; i++) {
  343.         if (digesta[i] != digestb[i]) {
  344.         return false;
  345.         }
  346.     }
  347.     return true;
  348.     }
  349.  
  350.     /**
  351.      * Resets the digest for further use.
  352.      */
  353.     public void reset() {
  354.     engineReset();
  355.     digestBits = null;
  356.     }
  357.  
  358.     /** 
  359.      * Returns a string that identifies the algorithm, independent of
  360.      * implementation details. The name should be a standard
  361.      * Java Security name (such as "SHA", "MD5", and so on). 
  362.      * See Appendix A in the <a href=
  363.      * "../guide/security/CryptoSpec.html#AppA">
  364.      * Java Cryptography Architecture API Specification & Reference </a> 
  365.      * for information about standard algorithm names.
  366.      */
  367.     public final String getAlgorithm() {
  368.     return this.algorithm;
  369.     }
  370.  
  371.     /** 
  372.      * Returns the length of the digest in bytes, or 0 if this operation is
  373.      * not supported by the provider and the implementation is not cloneable.
  374.      *
  375.      * @return the digest length in bytes, or 0 if this operation is not
  376.      * supported by the provider and the implementation is not cloneable.
  377.      * 
  378.      * @since JDK1.2
  379.      */
  380.     public final int getDigestLength() {
  381.     int digestLen = engineGetDigestLength();
  382.     if (digestLen == 0) {
  383.         try {
  384.         MessageDigest md = (MessageDigest)clone();
  385.         byte[] digest = md.digest();
  386.         return digest.length;
  387.         } catch (CloneNotSupportedException e) {
  388.         return digestLen;
  389.         }
  390.     }
  391.     return digestLen;
  392.     }
  393.  
  394.     /**    
  395.      * Returns a clone if the implementation is cloneable.    
  396.      * 
  397.      * @return a clone if the implementation is cloneable.
  398.      *
  399.      * @exception CloneNotSupportedException if this is called on an
  400.      * implementation that does not support <code>Cloneable</code>.
  401.      */
  402.     public Object clone() throws CloneNotSupportedException {
  403.     if (this instanceof Cloneable) {
  404.         return super.clone();
  405.     } else {
  406.         throw new CloneNotSupportedException();
  407.     }
  408.     }
  409.   
  410.     private void debug(String statement) {
  411.     if (debug) {
  412.         System.err.println(statement);
  413.     }
  414.     }
  415.  
  416.  
  417.  
  418.  
  419.     /*
  420.      * The following class allows providers to extend from MessageDigestSpi
  421.      * rather than from MessageDigest. It represents a MessageDigest with an
  422.      * encapsulated, provider-supplied SPI object (of type MessageDigestSpi).
  423.      * If the provider implementation is an instance of MessageDigestSpi,
  424.      * the getInstance() methods above return an instance of this class, with
  425.      * the SPI object encapsulated.
  426.      *
  427.      * Note: All SPI methods from the original MessageDigest class have been
  428.      * moved up the hierarchy into a new class (MessageDigestSpi), which has
  429.      * been interposed in the hierarchy between the API (MessageDigest)
  430.      * and its original parent (Object).
  431.      */
  432.  
  433.     static class Delegate extends MessageDigest {
  434.  
  435.     // The provider implementation (delegate)
  436.     private MessageDigestSpi digestSpi;
  437.  
  438.     // constructor
  439.     public Delegate(MessageDigestSpi digestSpi, String algorithm) {
  440.         super(algorithm);
  441.         this.digestSpi = digestSpi;
  442.     }
  443.  
  444.     /*
  445.      * Returns a clone if the delegate is cloneable.    
  446.      * 
  447.      * @return a clone if the delegate is cloneable.
  448.      *
  449.      * @exception CloneNotSupportedException if this is called on a
  450.      * delegate that does not support <code>Cloneable</code>.
  451.      */
  452.     public Object clone() throws CloneNotSupportedException {
  453.         if (digestSpi instanceof Cloneable) {
  454.         MessageDigestSpi digestSpiClone =
  455.             (MessageDigestSpi)digestSpi.clone();
  456.         Delegate that = new Delegate(digestSpiClone, algorithm);
  457.         that.provider = provider;
  458.         that.digestBits = digestBits;
  459.         return that;
  460.         } else {
  461.         throw new CloneNotSupportedException();
  462.         }
  463.     }
  464.  
  465.     protected int engineGetDigestLength() {
  466.         return digestSpi.engineGetDigestLength();
  467.     }
  468.  
  469.     protected void engineUpdate(byte input) {
  470.         digestSpi.engineUpdate(input);
  471.     }
  472.  
  473.     protected void engineUpdate(byte[] input, int offset, int len) {
  474.         digestSpi.engineUpdate(input, offset, len);
  475.     }
  476.  
  477.     protected byte[] engineDigest() {
  478.         return digestSpi.engineDigest();
  479.     }
  480.  
  481.     protected int engineDigest(byte[] buf, int offset, int len)
  482.         throws DigestException {
  483.         return digestSpi.engineDigest(buf, offset, len);
  484.     }
  485.  
  486.     protected void engineReset() {
  487.         digestSpi.engineReset();
  488.     }
  489.     }
  490. }
  491.