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

    1   /*
    2    * Copyright (c) 1996, 2011, Oracle and/or its affiliates. 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.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * 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 SHA-1 or SHA-256.
   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    * <p> Every implementation of the Java platform is required to support
   85    * the following standard <code>MessageDigest</code> algorithms:
   86    * <ul>
   87    * <li><tt>MD5</tt></li>
   88    * <li><tt>SHA-1</tt></li>
   89    * <li><tt>SHA-256</tt></li>
   90    * </ul>
   91    * These algorithms are described in the <a href=
   92    * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest">
   93    * MessageDigest section</a> of the
   94    * Java Cryptography Architecture Standard Algorithm Name Documentation.
   95    * Consult the release documentation for your implementation to see if any
   96    * other algorithms are supported.
   97    *
   98    * @author Benjamin Renaud
   99    *
  100    * @see DigestInputStream
  101    * @see DigestOutputStream
  102    */
  103   
  104   public abstract class MessageDigest extends MessageDigestSpi {
  105   
  106       private String algorithm;
  107   
  108       // The state of this digest
  109       private static final int INITIAL = 0;
  110       private static final int IN_PROGRESS = 1;
  111       private int state = INITIAL;
  112   
  113       // The provider
  114       private Provider provider;
  115   
  116       /**
  117        * Creates a message digest with the specified algorithm name.
  118        *
  119        * @param algorithm the standard name of the digest algorithm.
  120        * See the MessageDigest section in the <a href=
  121        * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest">
  122        * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
  123        * for information about standard algorithm names.
  124        */
  125       protected MessageDigest(String algorithm) {
  126           this.algorithm = algorithm;
  127       }
  128   
  129       /**
  130        * Returns a MessageDigest object that implements the specified digest
  131        * algorithm.
  132        *
  133        * <p> This method traverses the list of registered security Providers,
  134        * starting with the most preferred Provider.
  135        * A new MessageDigest object encapsulating the
  136        * MessageDigestSpi implementation from the first
  137        * Provider that supports the specified algorithm is returned.
  138        *
  139        * <p> Note that the list of registered providers may be retrieved via
  140        * the {@link Security#getProviders() Security.getProviders()} method.
  141        *
  142        * @param algorithm the name of the algorithm requested.
  143        * See the MessageDigest section in the <a href=
  144        * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest">
  145        * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
  146        * for information about standard algorithm names.
  147        *
  148        * @return a Message Digest object that implements the specified algorithm.
  149        *
  150        * @exception NoSuchAlgorithmException if no Provider supports a
  151        *          MessageDigestSpi implementation for the
  152        *          specified algorithm.
  153        *
  154        * @see Provider
  155        */
  156       public static MessageDigest getInstance(String algorithm)
  157       throws NoSuchAlgorithmException {
  158           try {
  159               Object[] objs = Security.getImpl(algorithm, "MessageDigest",
  160                                                (String)null);
  161               if (objs[0] instanceof MessageDigest) {
  162                   MessageDigest md = (MessageDigest)objs[0];
  163                   md.provider = (Provider)objs[1];
  164                   return md;
  165               } else {
  166                   MessageDigest delegate =
  167                       new Delegate((MessageDigestSpi)objs[0], algorithm);
  168                   delegate.provider = (Provider)objs[1];
  169                   return delegate;
  170               }
  171           } catch(NoSuchProviderException e) {
  172               throw new NoSuchAlgorithmException(algorithm + " not found");
  173           }
  174       }
  175   
  176       /**
  177        * Returns a MessageDigest object that implements the specified digest
  178        * algorithm.
  179        *
  180        * <p> A new MessageDigest object encapsulating the
  181        * MessageDigestSpi implementation from the specified provider
  182        * is returned.  The specified provider must be registered
  183        * in the security provider list.
  184        *
  185        * <p> Note that the list of registered providers may be retrieved via
  186        * the {@link Security#getProviders() Security.getProviders()} method.
  187        *
  188        * @param algorithm the name of the algorithm requested.
  189        * See the MessageDigest section in the <a href=
  190        * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest">
  191        * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
  192        * for information about standard algorithm names.
  193        *
  194        * @param provider the name of the provider.
  195        *
  196        * @return a MessageDigest object that implements the specified algorithm.
  197        *
  198        * @exception NoSuchAlgorithmException if a MessageDigestSpi
  199        *          implementation for the specified algorithm is not
  200        *          available from the specified provider.
  201        *
  202        * @exception NoSuchProviderException if the specified provider is not
  203        *          registered in the security provider list.
  204        *
  205        * @exception IllegalArgumentException if the provider name is null
  206        *          or empty.
  207        *
  208        * @see Provider
  209        */
  210       public static MessageDigest getInstance(String algorithm, String provider)
  211           throws NoSuchAlgorithmException, NoSuchProviderException
  212       {
  213           if (provider == null || provider.length() == 0)
  214               throw new IllegalArgumentException("missing provider");
  215           Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider);
  216           if (objs[0] instanceof MessageDigest) {
  217               MessageDigest md = (MessageDigest)objs[0];
  218               md.provider = (Provider)objs[1];
  219               return md;
  220           } else {
  221               MessageDigest delegate =
  222                   new Delegate((MessageDigestSpi)objs[0], algorithm);
  223               delegate.provider = (Provider)objs[1];
  224               return delegate;
  225           }
  226       }
  227   
  228       /**
  229        * Returns a MessageDigest object that implements the specified digest
  230        * algorithm.
  231        *
  232        * <p> A new MessageDigest object encapsulating the
  233        * MessageDigestSpi implementation from the specified Provider
  234        * object is returned.  Note that the specified Provider object
  235        * does not have to be registered in the provider list.
  236        *
  237        * @param algorithm the name of the algorithm requested.
  238        * See the MessageDigest section in the <a href=
  239        * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest">
  240        * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
  241        * for information about standard algorithm names.
  242        *
  243        * @param provider the provider.
  244        *
  245        * @return a MessageDigest object that implements the specified algorithm.
  246        *
  247        * @exception NoSuchAlgorithmException if a MessageDigestSpi
  248        *          implementation for the specified algorithm is not available
  249        *          from the specified Provider object.
  250        *
  251        * @exception IllegalArgumentException if the specified provider is null.
  252        *
  253        * @see Provider
  254        *
  255        * @since 1.4
  256        */
  257       public static MessageDigest getInstance(String algorithm,
  258                                               Provider provider)
  259           throws NoSuchAlgorithmException
  260       {
  261           if (provider == null)
  262               throw new IllegalArgumentException("missing provider");
  263           Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider);
  264           if (objs[0] instanceof MessageDigest) {
  265               MessageDigest md = (MessageDigest)objs[0];
  266               md.provider = (Provider)objs[1];
  267               return md;
  268           } else {
  269               MessageDigest delegate =
  270                   new Delegate((MessageDigestSpi)objs[0], algorithm);
  271               delegate.provider = (Provider)objs[1];
  272               return delegate;
  273           }
  274       }
  275   
  276       /**
  277        * Returns the provider of this message digest object.
  278        *
  279        * @return the provider of this message digest object
  280        */
  281       public final Provider getProvider() {
  282           return this.provider;
  283       }
  284   
  285       /**
  286        * Updates the digest using the specified byte.
  287        *
  288        * @param input the byte with which to update the digest.
  289        */
  290       public void update(byte input) {
  291           engineUpdate(input);
  292           state = IN_PROGRESS;
  293       }
  294   
  295       /**
  296        * Updates the digest using the specified array of bytes, starting
  297        * at the specified offset.
  298        *
  299        * @param input the array of bytes.
  300        *
  301        * @param offset the offset to start from in the array of bytes.
  302        *
  303        * @param len the number of bytes to use, starting at
  304        * <code>offset</code>.
  305        */
  306       public void update(byte[] input, int offset, int len) {
  307           if (input == null) {
  308               throw new IllegalArgumentException("No input buffer given");
  309           }
  310           if (input.length - offset < len) {
  311               throw new IllegalArgumentException("Input buffer too short");
  312           }
  313           engineUpdate(input, offset, len);
  314           state = IN_PROGRESS;
  315       }
  316   
  317       /**
  318        * Updates the digest using the specified array of bytes.
  319        *
  320        * @param input the array of bytes.
  321        */
  322       public void update(byte[] input) {
  323           engineUpdate(input, 0, input.length);
  324           state = IN_PROGRESS;
  325       }
  326   
  327       /**
  328        * Update the digest using the specified ByteBuffer. The digest is
  329        * updated using the <code>input.remaining()</code> bytes starting
  330        * at <code>input.position()</code>.
  331        * Upon return, the buffer's position will be equal to its limit;
  332        * its limit will not have changed.
  333        *
  334        * @param input the ByteBuffer
  335        * @since 1.5
  336        */
  337       public final void update(ByteBuffer input) {
  338           if (input == null) {
  339               throw new NullPointerException();
  340           }
  341           engineUpdate(input);
  342           state = IN_PROGRESS;
  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        * @return the array of bytes for the resulting hash value.
  350        */
  351       public byte[] digest() {
  352           /* Resetting is the responsibility of implementors. */
  353           byte[] result = engineDigest();
  354           state = INITIAL;
  355           return result;
  356       }
  357   
  358       /**
  359        * Completes the hash computation by performing final operations
  360        * such as padding. The digest is reset after this call is made.
  361        *
  362        * @param buf output buffer for the computed digest
  363        *
  364        * @param offset offset into the output buffer to begin storing the digest
  365        *
  366        * @param len number of bytes within buf allotted for the digest
  367        *
  368        * @return the number of bytes placed into <code>buf</code>
  369        *
  370        * @exception DigestException if an error occurs.
  371        */
  372       public int digest(byte[] buf, int offset, int len) throws DigestException {
  373           if (buf == null) {
  374               throw new IllegalArgumentException("No output buffer given");
  375           }
  376           if (buf.length - offset < len) {
  377               throw new IllegalArgumentException
  378                   ("Output buffer too small for specified offset and length");
  379           }
  380           int numBytes = engineDigest(buf, offset, len);
  381           state = INITIAL;
  382           return numBytes;
  383       }
  384   
  385       /**
  386        * Performs a final update on the digest using the specified array
  387        * of bytes, then completes the digest computation. That is, this
  388        * method first calls {@link #update(byte[]) update(input)},
  389        * passing the <i>input</i> array to the <code>update</code> method,
  390        * then calls {@link #digest() digest()}.
  391        *
  392        * @param input the input to be updated before the digest is
  393        * completed.
  394        *
  395        * @return the array of bytes for the resulting hash value.
  396        */
  397       public byte[] digest(byte[] input) {
  398           update(input);
  399           return digest();
  400       }
  401   
  402       /**
  403        * Returns a string representation of this message digest object.
  404        */
  405       public String toString() {
  406           ByteArrayOutputStream baos = new ByteArrayOutputStream();
  407           PrintStream p = new PrintStream(baos);
  408           p.print(algorithm+" Message Digest from "+provider.getName()+", ");
  409           switch (state) {
  410           case INITIAL:
  411               p.print("<initialized>");
  412               break;
  413           case IN_PROGRESS:
  414               p.print("<in progress>");
  415               break;
  416           }
  417           p.println();
  418           return (baos.toString());
  419       }
  420   
  421       /**
  422        * Compares two digests for equality. Does a simple byte compare.
  423        *
  424        * @param digesta one of the digests to compare.
  425        *
  426        * @param digestb the other digest to compare.
  427        *
  428        * @return true if the digests are equal, false otherwise.
  429        */
  430       public static boolean isEqual(byte[] digesta, byte[] digestb) {
  431           if (digesta.length != digestb.length) {
  432               return false;
  433           }
  434   
  435           int result = 0;
  436           // time-constant comparison
  437           for (int i = 0; i < digesta.length; i++) {
  438               result |= digesta[i] ^ digestb[i];
  439           }
  440           return result == 0;
  441       }
  442   
  443       /**
  444        * Resets the digest for further use.
  445        */
  446       public void reset() {
  447           engineReset();
  448           state = INITIAL;
  449       }
  450   
  451       /**
  452        * Returns a string that identifies the algorithm, independent of
  453        * implementation details. The name should be a standard
  454        * Java Security name (such as "SHA", "MD5", and so on).
  455        * See the MessageDigest section in the <a href=
  456        * "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest">
  457        * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
  458        * for information about standard algorithm names.
  459        *
  460        * @return the name of the algorithm
  461        */
  462       public final String getAlgorithm() {
  463           return this.algorithm;
  464       }
  465   
  466       /**
  467        * Returns the length of the digest in bytes, or 0 if this operation is
  468        * not supported by the provider and the implementation is not cloneable.
  469        *
  470        * @return the digest length in bytes, or 0 if this operation is not
  471        * supported by the provider and the implementation is not cloneable.
  472        *
  473        * @since 1.2
  474        */
  475       public final int getDigestLength() {
  476           int digestLen = engineGetDigestLength();
  477           if (digestLen == 0) {
  478               try {
  479                   MessageDigest md = (MessageDigest)clone();
  480                   byte[] digest = md.digest();
  481                   return digest.length;
  482               } catch (CloneNotSupportedException e) {
  483                   return digestLen;
  484               }
  485           }
  486           return digestLen;
  487       }
  488   
  489       /**
  490        * Returns a clone if the implementation is cloneable.
  491        *
  492        * @return a clone if the implementation is cloneable.
  493        *
  494        * @exception CloneNotSupportedException if this is called on an
  495        * implementation that does not support <code>Cloneable</code>.
  496        */
  497       public Object clone() throws CloneNotSupportedException {
  498           if (this instanceof Cloneable) {
  499               return super.clone();
  500           } else {
  501               throw new CloneNotSupportedException();
  502           }
  503       }
  504   
  505   
  506   
  507   
  508       /*
  509        * The following class allows providers to extend from MessageDigestSpi
  510        * rather than from MessageDigest. It represents a MessageDigest with an
  511        * encapsulated, provider-supplied SPI object (of type MessageDigestSpi).
  512        * If the provider implementation is an instance of MessageDigestSpi,
  513        * the getInstance() methods above return an instance of this class, with
  514        * the SPI object encapsulated.
  515        *
  516        * Note: All SPI methods from the original MessageDigest class have been
  517        * moved up the hierarchy into a new class (MessageDigestSpi), which has
  518        * been interposed in the hierarchy between the API (MessageDigest)
  519        * and its original parent (Object).
  520        */
  521   
  522       static class Delegate extends MessageDigest {
  523   
  524           // The provider implementation (delegate)
  525           private MessageDigestSpi digestSpi;
  526   
  527           // constructor
  528           public Delegate(MessageDigestSpi digestSpi, String algorithm) {
  529               super(algorithm);
  530               this.digestSpi = digestSpi;
  531           }
  532   
  533           /**
  534            * Returns a clone if the delegate is cloneable.
  535            *
  536            * @return a clone if the delegate is cloneable.
  537            *
  538            * @exception CloneNotSupportedException if this is called on a
  539            * delegate that does not support <code>Cloneable</code>.
  540            */
  541           public Object clone() throws CloneNotSupportedException {
  542               if (digestSpi instanceof Cloneable) {
  543                   MessageDigestSpi digestSpiClone =
  544                       (MessageDigestSpi)digestSpi.clone();
  545                   // Because 'algorithm', 'provider', and 'state' are private
  546                   // members of our supertype, we must perform a cast to
  547                   // access them.
  548                   MessageDigest that =
  549                       new Delegate(digestSpiClone,
  550                                    ((MessageDigest)this).algorithm);
  551                   that.provider = ((MessageDigest)this).provider;
  552                   that.state = ((MessageDigest)this).state;
  553                   return that;
  554               } else {
  555                   throw new CloneNotSupportedException();
  556               }
  557           }
  558   
  559           protected int engineGetDigestLength() {
  560               return digestSpi.engineGetDigestLength();
  561           }
  562   
  563           protected void engineUpdate(byte input) {
  564               digestSpi.engineUpdate(input);
  565           }
  566   
  567           protected void engineUpdate(byte[] input, int offset, int len) {
  568               digestSpi.engineUpdate(input, offset, len);
  569           }
  570   
  571           protected void engineUpdate(ByteBuffer input) {
  572               digestSpi.engineUpdate(input);
  573           }
  574   
  575           protected byte[] engineDigest() {
  576               return digestSpi.engineDigest();
  577           }
  578   
  579           protected int engineDigest(byte[] buf, int offset, int len)
  580               throws DigestException {
  581                   return digestSpi.engineDigest(buf, offset, len);
  582           }
  583   
  584           protected void engineReset() {
  585               digestSpi.engineReset();
  586           }
  587       }
  588   }

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