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)
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
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
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
;
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.
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}:
64 * MessageDigest md = MessageDigest.getInstance("SHA");
67 * md.update(toChapter1);
68 * MessageDigest tc1 = md.clone();
69 * byte[] toChapter1Digest = tc1.digest();
70 * md.update(toChapter2);
73 * catch (CloneNotSupportedException x)
75 * throw new DigestException("couldn't make digest of partial content");
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
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
;
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 & Reference for information about standard
110 protected MessageDigest(String algorithm
)
112 this.algorithm
= algorithm
;
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
124 * @param algorithm the name of the algorithm requested. See Appendix A in the
125 * Java Cryptography Architecture API Specification & 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 & 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
161 * @throws IllegalArgumentException if the provider name is null or empty.
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
);
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
183 * @param algorithm the name of the algorithm requested. See Appendix A in
184 * the Java Cryptography Architecture API Specification & 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
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;
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
;
223 throw new NoSuchAlgorithmException(algorithm
);
225 result
.provider
= provider
;
230 * Returns the provider of this message digest object.
232 * @return the provider of this message digest object.
234 public final Provider
getProvider()
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
)
250 * Updates the digest using the specified array of bytes, starting at the
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
)
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>
331 public static boolean isEqual(byte[] digesta
, byte[] digestb
)
333 if (digesta
.length
!= digestb
.length
)
336 for (int i
= digesta
.length
- 1; i
>= 0; --i
)
337 if (digesta
[i
] != digestb
[i
])
343 /** Resets the digest for further use. */
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 & Reference
354 * for information about standard algorithm names.
356 * @return the name of the algorithm.
358 public final String
getAlgorithm()
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
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.
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();
389 throw new CloneNotSupportedException();
392 private String
digestToString()
394 byte[] digest
= lastDigest
;
399 StringBuffer buf
= new StringBuffer();
400 int len
= digest
.length
;
401 for (int i
= 0; i
< len
; ++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();