home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / main.bin / MessageDigest.java < prev    next >
Text File  |  1997-10-01  |  13KB  |  397 lines

  1. /*
  2.  * @(#)MessageDigest.java    1.31 97/01/30
  3.  * 
  4.  * Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  * CopyrightVersion 1.1_beta
  20.  * 
  21.  */
  22.  
  23. package java.security;
  24.  
  25. import java.util.*;
  26. import java.lang.*;
  27. import java.io.IOException;
  28. import java.io.ByteArrayOutputStream;
  29. import java.io.PrintStream;
  30. import java.io.InputStream;
  31. import java.io.ByteArrayInputStream;
  32.  
  33. /**
  34.  * This MessageDigest class provides the functionality of a message digest
  35.  * algorithm, such as MD5 or SHA. Message digests are secure one-way
  36.  * hash functions that take arbitrary-sized data and output a
  37.  * fixed-length hash value.
  38.  *
  39.  * <p>Like other algorithm-based classes in Java Security, 
  40.  * MessageDigest has two major components:
  41.  *
  42.  * <dl>
  43.  *
  44.  * <dt><b>Message Digest API</b> (Application Program Interface)
  45.  *
  46.  * <dd>This is the interface of methods called by applications needing 
  47.  * message digest services. The API consists of all public methods.
  48.  *
  49.  * <dt><b>Message Digest SPI</b> (Service Provider Interface)
  50.  *
  51.  * <dd>This is the interface implemented by providers that supply
  52.  * specific algorithms. It consists of all methods whose names
  53.  * are prefixed by <em>engine</em>. Each such method is called by    
  54.  * a correspondingly-named public API method. For example,
  55.  * the <code>engineReset</code> method is    
  56.  * called by the <code>reset</code> method.    
  57.  * The SPI methods are abstract; providers must supply a    
  58.  * concrete implementation.
  59.  *
  60.  * </dl>
  61.  *
  62.  * <p>A MessageDigest object starts out initialized. The data is 
  63.  * processed through it using the <a href="#update(byte)">update</a>
  64.  * methods. At any point <a href="#reset">reset</a> can be called
  65.  * to reset the digest. Once all the data to be updated has been
  66.  * updated, one of the <a href="#digest()">digest</a> methods should 
  67.  * be called to complete the hash computation.
  68.  *
  69.  * <p>The <code>digest</code> method can be called once for a given number 
  70.  * of updates. After <code>digest</code> has been called, the MessageDigest
  71.  * object is reset to its initialized state.
  72.  *
  73.  * <p>Implementations are free to implement the Cloneable interface,
  74.  * and doing so will let client applications test cloneability
  75.  * using <code>instanceof Cloneable</code> before cloning: <p>    
  76.  *
  77.  * <pre>
  78.  * MessageDigest md = MessageDigest.getInstance("SHA");
  79.  *
  80.  * if (md instanceof Cloneable) {
  81.  *     md.update(toChapter1);
  82.  *     MessageDigest tc1 = md.clone();
  83.  *     byte[] toChapter1Digest = tc1.digest;
  84.  *     md.update(toChapter2);
  85.  *     ...etc.
  86.  * } else {
  87.  *     throw new DigestException("couldn't make digest of partial content");
  88.  * }
  89.  * </pre>
  90.  *
  91.  * <p>Note that if a given implementation is not cloneable, it is
  92.  * still possible to compute intermediate digests by instantiating
  93.  * several instances, if the number of digests is known in advance.
  94.  *
  95.  * @see DigestInputStream
  96.  * @see DigestOutputStream
  97.  *
  98.  * @version 1.31 97/02/03
  99.  * @author Benjamin Renaud 
  100.  */
  101. public abstract class MessageDigest {
  102.  
  103.     /* Are we in debugging mode? */
  104.     private static boolean debug = false;
  105.  
  106.     /* The digest bits, if any. */
  107.     private byte[] digestBits;
  108.  
  109.     private String algorithm;
  110.  
  111.     /**
  112.      * Creates a message digest with the specified algorithm name.
  113.      * 
  114.      * @param algorithm the standard name of the digest algorithm. 
  115.      * See Appendix A in the <a href=
  116.      * "../guide/security/CryptoSpec.html#AppA">
  117.      * Java Cryptography Architecture API Specification & Reference </a> 
  118.      * for information about standard algorithm names.
  119.      */
  120.     protected MessageDigest(String algorithm) {
  121.     this.algorithm = algorithm;
  122.     }
  123.  
  124.     /**
  125.      * Generates a MessageDigest object that implements the specified digest
  126.      * algorithm. If the default provider package contains a MessageDigest
  127.      * subclass implementing the algorithm, an instance of that subclass
  128.      * is returned. If the algorithm is not available in the default 
  129.      * package, other packages are searched.
  130.      *
  131.      * @param algorithm the name of the algorithm requested. 
  132.      * See Appendix A in the <a href=
  133.      * "../guide/security/CryptoSpec.html#AppA">
  134.      * Java Cryptography Architecture API Specification & Reference </a> 
  135.      * for information about standard algorithm names.
  136.      *
  137.      * @return a Message Digest object implementing the specified
  138.      * algorithm.
  139.      *
  140.      * @exception NoSuchAlgorithmException if the algorithm is
  141.      * not available in the caller's environment.  
  142.      */
  143.     public static MessageDigest getInstance(String algorithm) 
  144.     throws NoSuchAlgorithmException { 
  145.     try {
  146.         return (MessageDigest)Security.getImpl(algorithm, 
  147.                            "MessageDigest", null);
  148.     } catch(NoSuchProviderException e) {
  149.         throw new InternalError("please send a bug report via " +
  150.                     System.getProperty("java.vendor.url.bug"));
  151.     }
  152.     }
  153.  
  154.     /**
  155.      * Generates a MessageDigest object implementing the specified
  156.      * algorithm, as supplied from the specified provider, if such an 
  157.      * algorithm is available from the provider.
  158.      *
  159.      * @param algorithm the name of the algorithm requested. 
  160.      * See Appendix A in the <a href=
  161.      * "../guide/security/CryptoSpec.html#AppA">
  162.      * Java Cryptography Architecture API Specification & Reference </a> 
  163.      * for information about standard algorithm names.
  164.      *
  165.      * @param provider the name of the provider.
  166.      *
  167.      * @return a Message Digest object implementing the specified
  168.      * algorithm.
  169.      *
  170.      * @exception NoSuchAlgorithmException if the algorithm is
  171.      * not available in the package supplied by the requested
  172.      * provider.
  173.      *
  174.      * @exception NoSuchProviderException if the provider is not
  175.      * available in the environment. 
  176.      * 
  177.      * @see Provider 
  178.      */
  179.     public static MessageDigest getInstance(String algorithm, String provider)
  180.     throws NoSuchAlgorithmException, NoSuchProviderException {
  181.     return (MessageDigest)Security.getImpl(algorithm, 
  182.                            "MessageDigest", provider);
  183.     }
  184.  
  185.     /**
  186.      * Updates the digest using the specified byte.    
  187.      * 
  188.      * @param input the byte with which to update the digest.
  189.      */
  190.     public void update(byte input) {
  191.     engineUpdate(input);
  192.     }
  193.  
  194.  
  195.     /**
  196.      * Updates the digest using the specified array of bytes, starting
  197.      * at the specified offset.
  198.      * 
  199.      * @param input the array of bytes.
  200.      *
  201.      * @param offset the offset to start from in the array of bytes.
  202.      *
  203.      * @param len the number of bytes to use, starting at 
  204.      * <code>offset</code>.  
  205.      */
  206.     public void update(byte[] input, int offset, int len) {
  207.     engineUpdate(input, offset, len);
  208.     }
  209.  
  210.     /**
  211.      * Updates the digest using the specified array of bytes.
  212.      * 
  213.      * @param input the array of bytes.
  214.      */
  215.     public void update(byte[] input) {
  216.     engineUpdate(input, 0, input.length);
  217.     }
  218.  
  219.     /**
  220.      * Completes the hash computation by performing final operations
  221.      * such as padding. The digest is reset after this call is made.
  222.      *
  223.      * @return the array of bytes for the resulting hash value.  
  224.      */
  225.     public byte[] digest() {
  226.     /* Resetting is the responsibility of implementors. */
  227.     digestBits = engineDigest();
  228.     return digestBits;
  229.     }
  230.  
  231.     /**
  232.      * Performs a final update on the digest using the specified array 
  233.      * of bytes, then completes the digest computation. That is, this
  234.      * method first calls <a href = "#update(byte[])">update</a> on the
  235.      * array, then calls <a href = "#digest()">digest()</a>.
  236.      *
  237.      * @param input the input to be updated before the digest is
  238.      * completed.
  239.      *
  240.      * @return the array of bytes for the resulting hash value.  
  241.      */
  242.     public byte[] digest(byte[] input) {
  243.     update(input);
  244.     return digest();
  245.     }
  246.  
  247.     /**
  248.      * Helper function that prints unsigned two character hex digits.
  249.      */
  250.     private static void hexDigit(PrintStream p, byte x) {
  251.     char c;
  252.     
  253.     c = (char) ((x >> 4) & 0xf);
  254.     if (c > 9) {
  255.         c = (char) ((c - 10) + 'a');
  256.     } else {
  257.         c = (char) (c + '0');
  258.     }
  259.     p.write(c);
  260.  
  261.     c = (char) (x & 0xf);
  262.     if (c > 9) {
  263.         c = (char)((c - 10) + 'a');
  264.     } else {
  265.         c = (char)(c + '0');
  266.     }
  267.     p.write(c);
  268.     }
  269.  
  270.     /**
  271.      * Returns a string representation of this message digest object.  
  272.      */
  273.     public String toString() {
  274.     ByteArrayOutputStream ou = new ByteArrayOutputStream();
  275.     PrintStream p = new PrintStream(ou);
  276.         
  277.     p.print(this.getClass().getName()+" Message Digest ");
  278.     if (digestBits != null) {
  279.         p.print("<");
  280.         for(int i = 0; i < digestBits.length; i++)
  281.              hexDigit(p, digestBits[i]);
  282.         p.print(">");
  283.     } else {
  284.         p.print("<incomplete>");
  285.     }
  286.     p.println();
  287.     return (ou.toString());
  288.     }
  289.  
  290.     /**
  291.      * Compares two digests for equality. Does a simple byte compare.
  292.      * 
  293.      * @param digesta one of the digests to compare.
  294.      * 
  295.      * @param digestb the other digest to compare.    
  296.      *
  297.      * @return true if the digests are equal, false otherwise.
  298.      */
  299.     public static boolean isEqual(byte digesta[], byte digestb[]) {
  300.     int    i;
  301.         
  302.     if (digesta.length != digestb.length)
  303.         return false;
  304.  
  305.     for (i = 0; i < digesta.length; i++) {
  306.         if (digesta[i] != digestb[i]) {
  307.         return false;
  308.         }
  309.     }
  310.     return true;
  311.     }
  312.  
  313.     /**
  314.      * Resets the digest for further use.
  315.      */
  316.     public void reset() {
  317.     engineReset();
  318.     digestBits = null;
  319.     }
  320.  
  321.     /** 
  322.      * Returns a string that identifies the algorithm, independent of
  323.      * implementation details. The name should be a standard
  324.      * Java Security name (such as "SHA", "MD5", and so on). 
  325.      * See Appendix A in the <a href=
  326.      * "../guide/security/CryptoSpec.html#AppA">
  327.      * Java Cryptography Architecture API Specification & Reference </a> 
  328.      * for information about standard algorithm names.
  329.      */
  330.     public final String getAlgorithm() {
  331.     return algorithm;
  332.     }
  333.  
  334.     /**
  335.      * <b>SPI</b>: Updates the digest using the specified byte.
  336.      *
  337.      * @param input the byte to use for the update.
  338.      */
  339.     protected abstract void engineUpdate(byte input);
  340.  
  341.     /**
  342.      * <b>SPI</b>: Updates the digest using the specified array of bytes,    
  343.      * starting at the specified offset. This should be a no-op if
  344.      * the digest has been finalized.
  345.      *
  346.      * @param input the array of bytes to use for the update.
  347.      *
  348.      * @param offset the offset to start from in the array of bytes.
  349.      *
  350.      * @param len the number of bytes to use, starting at 
  351.      * <code>offset</code>.
  352.      */
  353.     protected abstract void engineUpdate(byte[] input, int offset, int len);
  354.  
  355.     /**
  356.      * <b>SPI</b>: Completes the hash computation by performing final
  357.      * operations such as padding. Once <code>engineDigest</code> has 
  358.      * been called, the engine should be reset (see <a href =
  359.      * "#reset">reset</a>).  Resetting is the responsibility of the
  360.      * engine implementor.
  361.      *
  362.      * @return the array of bytes for the resulting hash value.  
  363.      */
  364.     protected abstract byte[] engineDigest();
  365.  
  366.     /**
  367.      * <b>SPI</b>: Resets the digest for further use.
  368.      */
  369.     protected abstract void engineReset();    
  370.  
  371.  
  372.     /**    
  373.      * Returns a clone if the implementation is cloneable.    
  374.      * 
  375.      * @return a clone if the implementation is cloneable.
  376.      *
  377.      * @exception CloneNotSupportedException if this is called on an
  378.      * implementation that does not support <code>Cloneable</code>.
  379.      */
  380.     public Object clone() throws CloneNotSupportedException {
  381.     if (this instanceof Cloneable) {
  382.         return super.clone();
  383.     } else {
  384.         throw new CloneNotSupportedException();
  385.     }
  386.     }
  387.   
  388.  
  389.     private void debug(String statement) {
  390.     if (debug) {
  391.         System.err.println(statement);
  392.     }
  393.     }
  394.  
  395.  
  396. }
  397.