2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / java / security / MessageDigest.java
blob47b082a19f401a03e28dab2a408678412729ecb4
1 /* MessageDigest.java --- The message digest interface.
2 Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package java.security;
40 import gnu.java.security.Engine;
42 /**
43 * <p>This <code>MessageDigest</code> class provides applications the
44 * functionality of a message digest algorithm, such as <i>MD5</i> or <i>SHA</i>.
45 * Message digests are secure one-way hash functions that take arbitrary-sized
46 * data and output a fixed-length hash value.</p>
48 * <p>A <code>MessageDigest</code> object starts out initialized. The data is
49 * processed through it using the <code>update()</code> methods. At any point
50 * <code>reset()</code> can be called to reset the digest. Once all the data to
51 * be updated has been updated, one of the <code>digest()</code> methods should
52 * be called to complete the hash computation.</p>
54 * <p>The <code>digest()</code> method can be called <b>once</b> for a given
55 * number of updates. After <code>digest()</code> has been called, the
56 * <code>MessageDigest</code> object is <b>reset</b> to its initialized state.
57 * </p>
59 * <p>Implementations are free to implement the {@link Cloneable} interface.
60 * Client applications can test cloneability by attempting cloning and catching
61 * the {@link CloneNotSupportedException}:
63 * <pre>
64 * MessageDigest md = MessageDigest.getInstance("SHA");
65 * try
66 * {
67 * md.update(toChapter1);
68 * MessageDigest tc1 = md.clone();
69 * byte[] toChapter1Digest = tc1.digest();
70 * md.update(toChapter2);
71 * // ...
72 * }
73 * catch (CloneNotSupportedException x)
74 * {
75 * throw new DigestException("couldn't make digest of partial content");
76 * }
77 * </pre>
79 * <p>Note that if a given implementation is not cloneable, it is still possible
80 * to compute intermediate digests by instantiating several instances, if the
81 * number of digests is known in advance.</p>
83 * <p>Note that this class is abstract and extends from {@link MessageDigestSpi}
84 * for historical reasons. Application developers should only take notice of the
85 * methods defined in this <code>MessageDigest</code> class; all the methods in
86 * the superclass are intended for cryptographic service providers who wish to
87 * supply their own implementations of message digest algorithms.</p>
89 * @see MessageDigestSpi
90 * @see Provider
91 * @since JDK 1.1
93 public abstract class MessageDigest extends MessageDigestSpi
95 /** The service name for message digests. */
96 private static final String MESSAGE_DIGEST = "MessageDigest";
98 private String algorithm;
99 Provider provider;
100 private byte[] lastDigest;
103 * Creates a message digest with the specified algorithm name.
105 * @param algorithm the standard name of the digest algorithm.
106 * See Appendix A in the Java Cryptography Architecture API
107 * Specification &amp; Reference for information about standard
108 * algorithm names.
110 protected MessageDigest(String algorithm)
112 this.algorithm = algorithm;
113 provider = null;
117 * Generates a <code>MessageDigest</code> object that implements the specified
118 * digest algorithm. If the default provider package provides an
119 * implementation of the requested digest algorithm, an instance of
120 * <code>MessageDigest</code> containing that implementation is returned. If
121 * the algorithm is not available in the default package, other packages are
122 * searched.
124 * @param algorithm the name of the algorithm requested. See Appendix A in the
125 * Java Cryptography Architecture API Specification &amp; Reference for
126 * information about standard algorithm names.
127 * @return a Message Digest object implementing the specified algorithm.
128 * @throws NoSuchAlgorithmException if the algorithm is not available in the
129 * caller's environment.
131 public static MessageDigest getInstance(String algorithm)
132 throws NoSuchAlgorithmException
134 Provider[] p = Security.getProviders();
135 for (int i = 0; i < p.length; i++)
139 return getInstance(algorithm, p[i]);
141 catch (NoSuchAlgorithmException ignored) {}
144 throw new NoSuchAlgorithmException(algorithm);
148 * Generates a <code>MessageDigest</code> object implementing the specified
149 * algorithm, as supplied from the specified provider, if such an algorithm is
150 * available from the provider.
152 * @param algorithm the name of the algorithm requested. See Appendix A in the
153 * Java Cryptography Architecture API Specification &amp; Reference for
154 * information about standard algorithm names.
155 * @param provider the name of the provider.
156 * @return a Message Digest object implementing the specified algorithm.
157 * @throws NoSuchAlgorithmException if the algorithm is not available in the
158 * package supplied by the requested provider.
159 * @throws NoSuchProviderException if the provider is not available in the
160 * environment.
161 * @throws IllegalArgumentException if the provider name is null or empty.
162 * @see Provider
164 public static MessageDigest getInstance(String algorithm, String provider)
165 throws NoSuchAlgorithmException, NoSuchProviderException
167 if (provider == null || provider.length() == 0)
168 throw new IllegalArgumentException("Illegal provider");
170 Provider p = Security.getProvider(provider);
171 if (p == null)
172 throw new NoSuchProviderException(provider);
174 return getInstance(algorithm, p);
178 * Generates a <code>MessageDigest</code> object implementing the specified
179 * algorithm, as supplied from the specified provider, if such an algorithm
180 * is available from the provider. Note: the provider doesn't have to be
181 * registered.
183 * @param algorithm the name of the algorithm requested. See Appendix A in
184 * the Java Cryptography Architecture API Specification &amp; Reference for
185 * information about standard algorithm names.
186 * @param provider the provider.
187 * @return a Message Digest object implementing the specified algorithm.
188 * @throws NoSuchAlgorithmException if the <code>algorithm</code> is not
189 * available in the package supplied by the requested <code>provider</code>.
190 * @throws IllegalArgumentException if the <code>provider</code> is
191 * <code>null</code>.
192 * @since 1.4
193 * @see Provider
195 public static MessageDigest getInstance(String algorithm, Provider provider)
196 throws NoSuchAlgorithmException
198 if (provider == null)
199 throw new IllegalArgumentException("Illegal provider");
201 MessageDigest result = null;
202 Object o = null;
205 o = Engine.getInstance(MESSAGE_DIGEST, algorithm, provider);
207 catch (java.lang.reflect.InvocationTargetException ite)
209 throw new NoSuchAlgorithmException(algorithm);
212 if (o instanceof MessageDigestSpi)
214 result = new DummyMessageDigest((MessageDigestSpi) o, algorithm);
216 else if (o instanceof MessageDigest)
218 result = (MessageDigest) o;
219 result.algorithm = algorithm;
221 else
223 throw new NoSuchAlgorithmException(algorithm);
225 result.provider = provider;
226 return result;
230 * Returns the provider of this message digest object.
232 * @return the provider of this message digest object.
234 public final Provider getProvider()
236 return provider;
240 * Updates the digest using the specified byte.
242 * @param input the byte with which to update the digest.
244 public void update(byte input)
246 engineUpdate(input);
250 * Updates the digest using the specified array of bytes, starting at the
251 * specified offset.
253 * @param input the array of bytes.
254 * @param offset the offset to start from in the array of bytes.
255 * @param len the number of bytes to use, starting at offset.
257 public void update(byte[] input, int offset, int len)
259 engineUpdate(input, offset, len);
263 * Updates the digest using the specified array of bytes.
265 * @param input the array of bytes.
267 public void update(byte[] input)
269 engineUpdate(input, 0, input.length);
273 * Completes the hash computation by performing final operations such as
274 * padding. The digest is reset after this call is made.
276 * @return the array of bytes for the resulting hash value.
278 public byte[] digest()
280 return lastDigest = engineDigest();
284 * Completes the hash computation by performing final operations such as
285 * padding. The digest is reset after this call is made.
287 * @param buf An output buffer for the computed digest.
288 * @param offset The offset into the output buffer to begin storing the digest.
289 * @param len The number of bytes within buf allotted for the digest.
290 * @return The number of bytes placed into buf.
291 * @throws DigestException if an error occurs.
293 public int digest(byte[] buf, int offset, int len) throws DigestException
295 return engineDigest(buf, offset, len);
299 * Performs a final update on the digest using the specified array of bytes,
300 * then completes the digest computation. That is, this method first calls
301 * <code>update(input)</code>, passing the input array to the <code>update()
302 * </code> method, then calls <code>digest()</code>.
304 * @param input the input to be updated before the digest is completed.
305 * @return the array of bytes for the resulting hash value.
307 public byte[] digest(byte[] input)
309 update(input);
310 return digest();
314 * Returns a string representation of this message digest object.
316 * @return a string representation of the object.
318 public String toString()
320 return (getClass()).getName() + " Message Digest <" + digestToString() + ">";
324 * Compares two digests for equality. Does a simple byte compare.
326 * @param digesta one of the digests to compare.
327 * @param digestb the other digest to compare.
328 * @return <code>true</code> if the digests are equal, <code>false</code>
329 * otherwise.
331 public static boolean isEqual(byte[] digesta, byte[] digestb)
333 if (digesta.length != digestb.length)
334 return false;
336 for (int i = digesta.length - 1; i >= 0; --i)
337 if (digesta[i] != digestb[i])
338 return false;
340 return true;
343 /** Resets the digest for further use. */
344 public void reset()
346 engineReset();
350 * Returns a string that identifies the algorithm, independent of
351 * implementation details. The name should be a standard Java Security name
352 * (such as <code>"SHA"</code>, <code>"MD5"</code>, and so on). See Appendix
353 * A in the Java Cryptography Architecture API Specification &amp; Reference
354 * for information about standard algorithm names.
356 * @return the name of the algorithm.
358 public final String getAlgorithm()
360 return algorithm;
364 * Returns the length of the digest in bytes, or <code>0</code> if this
365 * operation is not supported by the provider and the implementation is not
366 * cloneable.
368 * @return the digest length in bytes, or <code>0</code> if this operation is
369 * not supported by the provider and the implementation is not cloneable.
370 * @since 1.2
372 public final int getDigestLength()
374 return engineGetDigestLength();
378 * Returns a clone if the implementation is cloneable.
380 * @return a clone if the implementation is cloneable.
381 * @throws CloneNotSupportedException if this is called on an implementation
382 * that does not support {@link Cloneable}.
384 public Object clone() throws CloneNotSupportedException
386 if (this instanceof Cloneable)
387 return super.clone();
388 else
389 throw new CloneNotSupportedException();
392 private String digestToString()
394 byte[] digest = lastDigest;
396 if (digest == null)
397 return "incomplete";
399 StringBuffer buf = new StringBuffer();
400 int len = digest.length;
401 for (int i = 0; i < len; ++i)
403 byte b = digest[i];
404 byte high = (byte) ((b & 0xff) >>> 4);
405 byte low = (byte) (b & 0xf);
407 buf.append(high > 9 ? ('a' - 10) + high : '0' + high);
408 buf.append(low > 9 ? ('a' - 10) + low : '0' + low);
411 return buf.toString();