Save This Page
Home » openjdk-7 » java » security » [javadoc | source]
    1   /*
    2    * Copyright 1996-2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package java.security;
   27   
   28   import java.util;
   29   import java.lang;
   30   import java.io.IOException;
   31   import java.io.ByteArrayOutputStream;
   32   import java.io.PrintStream;
   33   import java.io.InputStream;
   34   import java.io.ByteArrayInputStream;
   35   
   36   import java.nio.ByteBuffer;
   37   
   38   /**
   39    * This MessageDigest class provides applications the functionality of a
   40    * message digest algorithm, such as MD5 or SHA.
   41    * Message digests are secure one-way hash functions that take arbitrary-sized
   42    * data and output a fixed-length hash value.
   43    *
   44    * <p>A MessageDigest object starts out initialized. The data is
   45    * processed through it using the {@link #update(byte) update}
   46    * methods. At any point {@link #reset() reset} can be called
   47    * to reset the digest. Once all the data to be updated has been
   48    * updated, one of the {@link #digest() digest} methods should
   49    * be called to complete the hash computation.
   50    *
   51    * <p>The <code>digest</code> method can be called once for a given number
   52    * of updates. After <code>digest</code> has been called, the MessageDigest
   53    * object is reset to its initialized state.
   54    *
   55    * <p>Implementations are free to implement the Cloneable interface.
   56    * Client applications can test cloneability by attempting cloning
   57    * and catching the CloneNotSupportedException: <p>
   58    *
   59   * <pre>
   60   * MessageDigest md = MessageDigest.getInstance("SHA");
   61   *
   62   * try {
   63   *     md.update(toChapter1);
   64   *     MessageDigest tc1 = md.clone();
   65   *     byte[] toChapter1Digest = tc1.digest();
   66   *     md.update(toChapter2);
   67   *     ...etc.
   68   * } catch (CloneNotSupportedException cnse) {
   69   *     throw new DigestException("couldn't make digest of partial content");
   70   * }
   71   * </pre>
   72    *
   73    * <p>Note that if a given implementation is not cloneable, it is
   74    * still possible to compute intermediate digests by instantiating
   75    * several instances, if the number of digests is known in advance.
   76    *
   77    * <p>Note that this class is abstract and extends from
   78    * <code>MessageDigestSpi</code> for historical reasons.
   79    * Application developers should only take notice of the methods defined in
   80    * this <code>MessageDigest</code> class; all the methods in
   81    * the superclass are intended for cryptographic service providers who wish to
   82    * supply their own implementations of message digest algorithms.
   83    *
   84    * @author Benjamin Renaud
   85    *
   86    *
   87    * @see DigestInputStream
   88    * @see DigestOutputStream
   89    */
   90   
   91   public abstract class MessageDigest extends MessageDigestSpi {
   92   
   93       private String algorithm;
   94   
   95       // The state of this digest
   96       private static final int INITIAL = 0;
   97       private static final int IN_PROGRESS = 1;
   98       private int state = INITIAL;
   99   
  100       // The provider
  101       private Provider provider;
  102   
  103       /**
  104        * Creates a message digest with the specified algorithm name.
  105        *
  106        * @param algorithm the standard name of the digest algorithm.
  107        * See Appendix A in the <a href=
  108        * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
  109        * Java Cryptography Architecture API Specification &amp; Reference </a>
  110        * for information about standard algorithm names.
  111        */
  112       protected MessageDigest(String algorithm) {
  113           this.algorithm = algorithm;
  114       }
  115   
  116       /**
  117        * Returns a MessageDigest object that implements the specified digest
  118        * algorithm.
  119        *
  120        * <p> This method traverses the list of registered security Providers,
  121        * starting with the most preferred Provider.
  122        * A new MessageDigest object encapsulating the
  123        * MessageDigestSpi implementation from the first
  124        * Provider that supports the specified algorithm is returned.
  125        *
  126        * <p> Note that the list of registered providers may be retrieved via
  127        * the {@link Security#getProviders() Security.getProviders()} method.
  128        *
  129        * @param algorithm the name of the algorithm requested.
  130        * See Appendix A in the <a href=
  131        * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
  132        * Java Cryptography Architecture API Specification &amp; Reference </a>
  133        * for information about standard algorithm names.
  134        *
  135        * @return a Message Digest object that implements the specified algorithm.
  136        *
  137        * @exception NoSuchAlgorithmException if no Provider supports a
  138        *          MessageDigestSpi implementation for the
  139        *          specified algorithm.
  140        *
  141        * @see Provider
  142        */
  143       public static MessageDigest getInstance(String algorithm)
  144       throws NoSuchAlgorithmException {
  145           try {
  146               Object[] objs = Security.getImpl(algorithm, "MessageDigest",
  147                                                (String)null);
  148               if (objs[0] instanceof MessageDigest) {
  149                   MessageDigest md = (MessageDigest)objs[0];
  150                   md.provider = (Provider)objs[1];
  151                   return md;
  152               } else {
  153                   MessageDigest delegate =
  154                       new Delegate((MessageDigestSpi)objs[0], algorithm);
  155                   delegate.provider = (Provider)objs[1];
  156                   return delegate;
  157               }
  158           } catch(NoSuchProviderException e) {
  159               throw new NoSuchAlgorithmException(algorithm + " not found");
  160           }
  161       }
  162   
  163       /**
  164        * Returns a MessageDigest object that implements the specified digest
  165        * algorithm.
  166        *
  167        * <p> A new MessageDigest object encapsulating the
  168        * MessageDigestSpi implementation from the specified provider
  169        * is returned.  The specified provider must be registered
  170        * in the security provider list.
  171        *
  172        * <p> Note that the list of registered providers may be retrieved via
  173        * the {@link Security#getProviders() Security.getProviders()} method.
  174        *
  175        * @param algorithm the name of the algorithm requested.
  176        * See Appendix A in the <a href=
  177        * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
  178        * Java Cryptography Architecture API Specification &amp; Reference </a>
  179        * for information about standard algorithm names.
  180        *
  181        * @param provider the name of the provider.
  182        *
  183        * @return a MessageDigest object that implements the specified algorithm.
  184        *
  185        * @exception NoSuchAlgorithmException if a MessageDigestSpi
  186        *          implementation for the specified algorithm is not
  187        *          available from the specified provider.
  188        *
  189        * @exception NoSuchProviderException if the specified provider is not
  190        *          registered in the security provider list.
  191        *
  192        * @exception IllegalArgumentException if the provider name is null
  193        *          or empty.
  194        *
  195        * @see Provider
  196        */
  197       public static MessageDigest getInstance(String algorithm, String provider)
  198           throws NoSuchAlgorithmException, NoSuchProviderException
  199       {
  200           if (provider == null || provider.length() == 0)
  201               throw new IllegalArgumentException("missing provider");
  202           Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider);
  203           if (objs[0] instanceof MessageDigest) {
  204               MessageDigest md = (MessageDigest)objs[0];
  205               md.provider = (Provider)objs[1];
  206               return md;
  207           } else {
  208               MessageDigest delegate =
  209                   new Delegate((MessageDigestSpi)objs[0], algorithm);
  210               delegate.provider = (Provider)objs[1];
  211               return delegate;
  212           }
  213       }
  214   
  215       /**
  216        * Returns a MessageDigest object that implements the specified digest
  217        * algorithm.
  218        *
  219        * <p> A new MessageDigest object encapsulating the
  220        * MessageDigestSpi implementation from the specified Provider
  221        * object is returned.  Note that the specified Provider object
  222        * does not have to be registered in the provider list.
  223        *
  224        * @param algorithm the name of the algorithm requested.
  225        * See Appendix A in the <a href=
  226        * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
  227        * Java Cryptography Architecture API Specification &amp; Reference </a>
  228        * for information about standard algorithm names.
  229        *
  230        * @param provider the provider.
  231        *
  232        * @return a MessageDigest object that implements the specified algorithm.
  233        *
  234        * @exception NoSuchAlgorithmException if a MessageDigestSpi
  235        *          implementation for the specified algorithm is not available
  236        *          from the specified Provider object.
  237        *
  238        * @exception IllegalArgumentException if the specified provider is null.
  239        *
  240        * @see Provider
  241        *
  242        * @since 1.4
  243        */
  244       public static MessageDigest getInstance(String algorithm,
  245                                               Provider provider)
  246           throws NoSuchAlgorithmException
  247       {
  248           if (provider == null)
  249               throw new IllegalArgumentException("missing provider");
  250           Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider);
  251           if (objs[0] instanceof MessageDigest) {
  252               MessageDigest md = (MessageDigest)objs[0];
  253               md.provider = (Provider)objs[1];
  254               return md;
  255           } else {
  256               MessageDigest delegate =
  257                   new Delegate((MessageDigestSpi)objs[0], algorithm);
  258               delegate.provider = (Provider)objs[1];
  259               return delegate;
  260           }
  261       }
  262   
  263       /**
  264        * Returns the provider of this message digest object.
  265        *
  266        * @return the provider of this message digest object
  267        */
  268       public final Provider getProvider() {
  269           return this.provider;
  270       }
  271   
  272       /**
  273        * Updates the digest using the specified byte.
  274        *
  275        * @param input the byte with which to update the digest.
  276        */
  277       public void update(byte input) {
  278           engineUpdate(input);
  279           state = IN_PROGRESS;
  280       }
  281   
  282       /**
  283        * Updates the digest using the specified array of bytes, starting
  284        * at the specified offset.
  285        *
  286        * @param input the array of bytes.
  287        *
  288        * @param offset the offset to start from in the array of bytes.
  289        *
  290        * @param len the number of bytes to use, starting at
  291        * <code>offset</code>.
  292        */
  293       public void update(byte[] input, int offset, int len) {
  294           if (input == null) {
  295               throw new IllegalArgumentException("No input buffer given");
  296           }
  297           if (input.length - offset < len) {
  298               throw new IllegalArgumentException("Input buffer too short");
  299           }
  300           engineUpdate(input, offset, len);
  301           state = IN_PROGRESS;
  302       }
  303   
  304       /**
  305        * Updates the digest using the specified array of bytes.
  306        *
  307        * @param input the array of bytes.
  308        */
  309       public void update(byte[] input) {
  310           engineUpdate(input, 0, input.length);
  311           state = IN_PROGRESS;
  312       }
  313   
  314       /**
  315        * Update the digest using the specified ByteBuffer. The digest is
  316        * updated using the <code>input.remaining()</code> bytes starting
  317        * at <code>input.position()</code>.
  318        * Upon return, the buffer's position will be equal to its limit;
  319        * its limit will not have changed.
  320        *
  321        * @param input the ByteBuffer
  322        * @since 1.5
  323        */
  324       public final void update(ByteBuffer input) {
  325           if (input == null) {
  326               throw new NullPointerException();
  327           }
  328           engineUpdate(input);
  329           state = IN_PROGRESS;
  330       }
  331   
  332       /**
  333        * Completes the hash computation by performing final operations
  334        * such as padding. The digest is reset after this call is made.
  335        *
  336        * @return the array of bytes for the resulting hash value.
  337        */
  338       public byte[] digest() {
  339           /* Resetting is the responsibility of implementors. */
  340           byte[] result = engineDigest();
  341           state = INITIAL;
  342           return result;
  343       }
  344   
  345       /**
  346        * Completes the hash computation by performing final operations
  347        * such as padding. The digest is reset after this call is made.
  348        *
  349        * @param buf output buffer for the computed digest
  350        *
  351        * @param offset offset into the output buffer to begin storing the digest
  352        *
  353        * @param len number of bytes within buf allotted for the digest
  354        *
  355        * @return the number of bytes placed into <code>buf</code>
  356        *
  357        * @exception DigestException if an error occurs.
  358        */
  359       public int digest(byte[] buf, int offset, int len) throws DigestException {
  360           if (buf == null) {
  361               throw new IllegalArgumentException("No output buffer given");
  362           }
  363           if (buf.length - offset < len) {
  364               throw new IllegalArgumentException
  365                   ("Output buffer too small for specified offset and length");
  366           }
  367           int numBytes = engineDigest(buf, offset, len);
  368           state = INITIAL;
  369           return numBytes;
  370       }
  371   
  372       /**
  373        * Performs a final update on the digest using the specified array
  374        * of bytes, then completes the digest computation. That is, this
  375        * method first calls {@link #update(byte[]) update(input)},
  376        * passing the <i>input</i> array to the <code>update</code> method,
  377        * then calls {@link #digest() digest()}.
  378        *
  379        * @param input the input to be updated before the digest is
  380        * completed.
  381        *
  382        * @return the array of bytes for the resulting hash value.
  383        */
  384       public byte[] digest(byte[] input) {
  385           update(input);
  386           return digest();
  387       }
  388   
  389       /**
  390        * Returns a string representation of this message digest object.
  391        */
  392       public String toString() {
  393           ByteArrayOutputStream baos = new ByteArrayOutputStream();
  394           PrintStream p = new PrintStream(baos);
  395           p.print(algorithm+" Message Digest from "+provider.getName()+", ");
  396           switch (state) {
  397           case INITIAL:
  398               p.print("<initialized>");
  399               break;
  400           case IN_PROGRESS:
  401               p.print("<in progress>");
  402               break;
  403           }
  404           p.println();
  405           return (baos.toString());
  406       }
  407   
  408       /**
  409        * Compares two digests for equality. Does a simple byte compare.
  410        *
  411        * @param digesta one of the digests to compare.
  412        *
  413        * @param digestb the other digest to compare.
  414        *
  415        * @return true if the digests are equal, false otherwise.
  416        */
  417       public static boolean isEqual(byte digesta[], byte digestb[]) {
  418           if (digesta.length != digestb.length)
  419               return false;
  420   
  421           for (int i = 0; i < digesta.length; i++) {
  422               if (digesta[i] != digestb[i]) {
  423                   return false;
  424               }
  425           }
  426           return true;
  427       }
  428   
  429       /**
  430        * Resets the digest for further use.
  431        */
  432       public void reset() {
  433           engineReset();
  434           state = INITIAL;
  435       }
  436   
  437       /**
  438        * Returns a string that identifies the algorithm, independent of
  439        * implementation details. The name should be a standard
  440        * Java Security name (such as "SHA", "MD5", and so on).
  441        * See Appendix A in the <a href=
  442        * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
  443        * Java Cryptography Architecture API Specification &amp; Reference </a>
  444        * for information about standard algorithm names.
  445        *
  446        * @return the name of the algorithm
  447        */
  448       public final String getAlgorithm() {
  449           return this.algorithm;
  450       }
  451   
  452       /**
  453        * Returns the length of the digest in bytes, or 0 if this operation is
  454        * not supported by the provider and the implementation is not cloneable.
  455        *
  456        * @return the digest length in bytes, or 0 if this operation is not
  457        * supported by the provider and the implementation is not cloneable.
  458        *
  459        * @since 1.2
  460        */
  461       public final int getDigestLength() {
  462           int digestLen = engineGetDigestLength();
  463           if (digestLen == 0) {
  464               try {
  465                   MessageDigest md = (MessageDigest)clone();
  466                   byte[] digest = md.digest();
  467                   return digest.length;
  468               } catch (CloneNotSupportedException e) {
  469                   return digestLen;
  470               }
  471           }
  472           return digestLen;
  473       }
  474   
  475       /**
  476        * Returns a clone if the implementation is cloneable.
  477        *
  478        * @return a clone if the implementation is cloneable.
  479        *
  480        * @exception CloneNotSupportedException if this is called on an
  481        * implementation that does not support <code>Cloneable</code>.
  482        */
  483       public Object clone() throws CloneNotSupportedException {
  484           if (this instanceof Cloneable) {
  485               return super.clone();
  486           } else {
  487               throw new CloneNotSupportedException();
  488           }
  489       }
  490   
  491   
  492   
  493   
  494       /*
  495        * The following class allows providers to extend from MessageDigestSpi
  496        * rather than from MessageDigest. It represents a MessageDigest with an
  497        * encapsulated, provider-supplied SPI object (of type MessageDigestSpi).
  498        * If the provider implementation is an instance of MessageDigestSpi,
  499        * the getInstance() methods above return an instance of this class, with
  500        * the SPI object encapsulated.
  501        *
  502        * Note: All SPI methods from the original MessageDigest class have been
  503        * moved up the hierarchy into a new class (MessageDigestSpi), which has
  504        * been interposed in the hierarchy between the API (MessageDigest)
  505        * and its original parent (Object).
  506        */
  507   
  508       static class Delegate extends MessageDigest {
  509   
  510           // The provider implementation (delegate)
  511           private MessageDigestSpi digestSpi;
  512   
  513           // constructor
  514           public Delegate(MessageDigestSpi digestSpi, String algorithm) {
  515               super(algorithm);
  516               this.digestSpi = digestSpi;
  517           }
  518   
  519           /**
  520            * Returns a clone if the delegate is cloneable.
  521            *
  522            * @return a clone if the delegate is cloneable.
  523            *
  524            * @exception CloneNotSupportedException if this is called on a
  525            * delegate that does not support <code>Cloneable</code>.
  526            */
  527           public Object clone() throws CloneNotSupportedException {
  528               if (digestSpi instanceof Cloneable) {
  529                   MessageDigestSpi digestSpiClone =
  530                       (MessageDigestSpi)digestSpi.clone();
  531                   // Because 'algorithm', 'provider', and 'state' are private
  532                   // members of our supertype, we must perform a cast to
  533                   // access them.
  534                   MessageDigest that =
  535                       new Delegate(digestSpiClone,
  536                                    ((MessageDigest)this).algorithm);
  537                   that.provider = ((MessageDigest)this).provider;
  538                   that.state = ((MessageDigest)this).state;
  539                   return that;
  540               } else {
  541                   throw new CloneNotSupportedException();
  542               }
  543           }
  544   
  545           protected int engineGetDigestLength() {
  546               return digestSpi.engineGetDigestLength();
  547           }
  548   
  549           protected void engineUpdate(byte input) {
  550               digestSpi.engineUpdate(input);
  551           }
  552   
  553           protected void engineUpdate(byte[] input, int offset, int len) {
  554               digestSpi.engineUpdate(input, offset, len);
  555           }
  556   
  557           protected void engineUpdate(ByteBuffer input) {
  558               digestSpi.engineUpdate(input);
  559           }
  560   
  561           protected byte[] engineDigest() {
  562               return digestSpi.engineDigest();
  563           }
  564   
  565           protected int engineDigest(byte[] buf, int offset, int len)
  566               throws DigestException {
  567                   return digestSpi.engineDigest(buf, offset, len);
  568           }
  569   
  570           protected void engineReset() {
  571               digestSpi.engineReset();
  572           }
  573       }
  574   }

Save This Page
Home » openjdk-7 » java » security » [javadoc | source]