1. /*
  2. * @(#)MessageDigest.java 1.74 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.security;
  8. import java.util.*;
  9. import java.lang.*;
  10. import java.io.IOException;
  11. import java.io.ByteArrayOutputStream;
  12. import java.io.PrintStream;
  13. import java.io.InputStream;
  14. import java.io.ByteArrayInputStream;
  15. /**
  16. * This MessageDigest class provides applications the functionality of a
  17. * message digest algorithm, such as MD5 or SHA.
  18. * Message digests are secure one-way hash functions that take arbitrary-sized
  19. * data and output a fixed-length hash value.
  20. *
  21. * <p>A MessageDigest object starts out initialized. The data is
  22. * processed through it using the {@link #update(byte) update}
  23. * methods. At any point {@link #reset() reset} can be called
  24. * to reset the digest. Once all the data to be updated has been
  25. * updated, one of the {@link #digest() digest} methods should
  26. * be called to complete the hash computation.
  27. *
  28. * <p>The <code>digest</code> method can be called once for a given number
  29. * of updates. After <code>digest</code> has been called, the MessageDigest
  30. * object is reset to its initialized state.
  31. *
  32. * <p>Implementations are free to implement the Cloneable interface.
  33. * Client applications can test cloneability by attempting cloning
  34. * and catching the CloneNotSupportedException: <p>
  35. *
  36. * <pre>
  37. * MessageDigest md = MessageDigest.getInstance("SHA");
  38. *
  39. * try {
  40. * md.update(toChapter1);
  41. * MessageDigest tc1 = md.clone();
  42. * byte[] toChapter1Digest = tc1.digest();
  43. * md.update(toChapter2);
  44. * ...etc.
  45. * } catch (CloneNotSupportedException cnse) {
  46. * throw new DigestException("couldn't make digest of partial content");
  47. * }
  48. * </pre>
  49. *
  50. * <p>Note that if a given implementation is not cloneable, it is
  51. * still possible to compute intermediate digests by instantiating
  52. * several instances, if the number of digests is known in advance.
  53. *
  54. * <p>Note that this class is abstract and extends from
  55. * <code>MessageDigestSpi</code> for historical reasons.
  56. * Application developers should only take notice of the methods defined in
  57. * this <code>MessageDigest</code> class; all the methods in
  58. * the superclass are intended for cryptographic service providers who wish to
  59. * supply their own implementations of message digest algorithms.
  60. *
  61. * @author Benjamin Renaud
  62. *
  63. * @version 1.74, 01/23/03
  64. *
  65. * @see DigestInputStream
  66. * @see DigestOutputStream
  67. */
  68. public abstract class MessageDigest extends MessageDigestSpi {
  69. private String algorithm;
  70. // The state of this digest
  71. private static final int INITIAL = 0;
  72. private static final int IN_PROGRESS = 1;
  73. private int state = INITIAL;
  74. // The provider
  75. private Provider provider;
  76. /**
  77. * Creates a message digest with the specified algorithm name.
  78. *
  79. * @param algorithm the standard name of the digest algorithm.
  80. * See Appendix A in the <a href=
  81. * "../../../guide/security/CryptoSpec.html#AppA">
  82. * Java Cryptography Architecture API Specification & Reference </a>
  83. * for information about standard algorithm names.
  84. */
  85. protected MessageDigest(String algorithm) {
  86. this.algorithm = algorithm;
  87. }
  88. /**
  89. * Generates a MessageDigest object that implements the specified digest
  90. * algorithm. If the default provider package
  91. * provides an implementation of the requested digest algorithm,
  92. * an instance of MessageDigest containing that implementation is returned.
  93. * If the algorithm is not available in the default
  94. * package, other packages are searched.
  95. *
  96. * @param algorithm the name of the algorithm requested.
  97. * See Appendix A in the <a href=
  98. * "../../../guide/security/CryptoSpec.html#AppA">
  99. * Java Cryptography Architecture API Specification & Reference </a>
  100. * for information about standard algorithm names.
  101. *
  102. * @return a Message Digest object implementing the specified
  103. * algorithm.
  104. *
  105. * @exception NoSuchAlgorithmException if the algorithm is
  106. * not available in the caller's environment.
  107. */
  108. public static MessageDigest getInstance(String algorithm)
  109. throws NoSuchAlgorithmException {
  110. try {
  111. Object[] objs = Security.getImpl(algorithm, "MessageDigest",
  112. (String)null);
  113. if (objs[0] instanceof MessageDigest) {
  114. MessageDigest md = (MessageDigest)objs[0];
  115. md.provider = (Provider)objs[1];
  116. return md;
  117. } else {
  118. MessageDigest delegate =
  119. new Delegate((MessageDigestSpi)objs[0], algorithm);
  120. delegate.provider = (Provider)objs[1];
  121. return delegate;
  122. }
  123. } catch(NoSuchProviderException e) {
  124. throw new NoSuchAlgorithmException(algorithm + " not found");
  125. }
  126. }
  127. /**
  128. * Generates a MessageDigest object implementing the specified
  129. * algorithm, as supplied from the specified provider, if such an
  130. * algorithm is available from the provider.
  131. *
  132. * @param algorithm the name of the algorithm requested.
  133. * See Appendix A in the <a href=
  134. * "../../../guide/security/CryptoSpec.html#AppA">
  135. * Java Cryptography Architecture API Specification & Reference </a>
  136. * for information about standard algorithm names.
  137. *
  138. * @param provider the name of the provider.
  139. *
  140. * @return a Message Digest object implementing the specified
  141. * algorithm.
  142. *
  143. * @exception NoSuchAlgorithmException if the algorithm is
  144. * not available in the package supplied by the requested
  145. * provider.
  146. *
  147. * @exception NoSuchProviderException if the provider is not
  148. * available in the environment.
  149. *
  150. * @exception IllegalArgumentException if the provider name is null
  151. * or empty.
  152. *
  153. * @see Provider
  154. */
  155. public static MessageDigest getInstance(String algorithm, String provider)
  156. throws NoSuchAlgorithmException, NoSuchProviderException
  157. {
  158. if (provider == null || provider.length() == 0)
  159. throw new IllegalArgumentException("missing provider");
  160. Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider);
  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. }
  172. /**
  173. * Generates a MessageDigest object implementing the specified
  174. * algorithm, as supplied from the specified provider, if such an
  175. * algorithm is available from the provider. Note: the
  176. * <code>provider</code> doesn't have to be registered.
  177. *
  178. * @param algorithm the name of the algorithm requested.
  179. * See Appendix A in the <a href=
  180. * "../../../guide/security/CryptoSpec.html#AppA">
  181. * Java Cryptography Architecture API Specification & Reference </a>
  182. * for information about standard algorithm names.
  183. *
  184. * @param provider the provider.
  185. *
  186. * @return a Message Digest object implementing the specified
  187. * algorithm.
  188. *
  189. * @exception NoSuchAlgorithmException if the algorithm is
  190. * not available in the package supplied by the requested
  191. * provider.
  192. *
  193. * @exception IllegalArgumentException if the <code>provider</code> is
  194. * null.
  195. *
  196. * @see Provider
  197. *
  198. * @since 1.4
  199. */
  200. public static MessageDigest getInstance(String algorithm,
  201. Provider provider)
  202. throws NoSuchAlgorithmException
  203. {
  204. if (provider == null)
  205. throw new IllegalArgumentException("missing provider");
  206. Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider);
  207. if (objs[0] instanceof MessageDigest) {
  208. MessageDigest md = (MessageDigest)objs[0];
  209. md.provider = (Provider)objs[1];
  210. return md;
  211. } else {
  212. MessageDigest delegate =
  213. new Delegate((MessageDigestSpi)objs[0], algorithm);
  214. delegate.provider = (Provider)objs[1];
  215. return delegate;
  216. }
  217. }
  218. /**
  219. * Returns the provider of this message digest object.
  220. *
  221. * @return the provider of this message digest object
  222. */
  223. public final Provider getProvider() {
  224. return this.provider;
  225. }
  226. /**
  227. * Updates the digest using the specified byte.
  228. *
  229. * @param input the byte with which to update the digest.
  230. */
  231. public void update(byte input) {
  232. engineUpdate(input);
  233. state = IN_PROGRESS;
  234. }
  235. /**
  236. * Updates the digest using the specified array of bytes, starting
  237. * at the specified offset.
  238. *
  239. * @param input the array of bytes.
  240. *
  241. * @param offset the offset to start from in the array of bytes.
  242. *
  243. * @param len the number of bytes to use, starting at
  244. * <code>offset</code>.
  245. */
  246. public void update(byte[] input, int offset, int len) {
  247. if (input == null) {
  248. throw new IllegalArgumentException("No input buffer given");
  249. }
  250. if (input.length - offset < len) {
  251. throw new IllegalArgumentException("Input buffer too short");
  252. }
  253. engineUpdate(input, offset, len);
  254. state = IN_PROGRESS;
  255. }
  256. /**
  257. * Updates the digest using the specified array of bytes.
  258. *
  259. * @param input the array of bytes.
  260. */
  261. public void update(byte[] input) {
  262. engineUpdate(input, 0, input.length);
  263. state = IN_PROGRESS;
  264. }
  265. /**
  266. * Completes the hash computation by performing final operations
  267. * such as padding. The digest is reset after this call is made.
  268. *
  269. * @return the array of bytes for the resulting hash value.
  270. */
  271. public byte[] digest() {
  272. /* Resetting is the responsibility of implementors. */
  273. byte[] result = engineDigest();
  274. state = INITIAL;
  275. return result;
  276. }
  277. /**
  278. * Completes the hash computation by performing final operations
  279. * such as padding. The digest is reset after this call is made.
  280. *
  281. * @param buf output buffer for the computed digest
  282. *
  283. * @param offset offset into the output buffer to begin storing the digest
  284. *
  285. * @param len number of bytes within buf allotted for the digest
  286. *
  287. * @return the number of bytes placed into <code>buf</code>
  288. *
  289. * @exception DigestException if an error occurs.
  290. */
  291. public int digest(byte[] buf, int offset, int len) throws DigestException {
  292. if (buf == null) {
  293. throw new IllegalArgumentException("No output buffer given");
  294. }
  295. if (buf.length - offset < len) {
  296. throw new IllegalArgumentException
  297. ("Output buffer too small for specified offset and length");
  298. }
  299. int numBytes = engineDigest(buf, offset, len);
  300. state = INITIAL;
  301. return numBytes;
  302. }
  303. /**
  304. * Performs a final update on the digest using the specified array
  305. * of bytes, then completes the digest computation. That is, this
  306. * method first calls {@link #update(byte[]) update(input)},
  307. * passing the <i>input</i> array to the <code>update</code> method,
  308. * then calls {@link #digest() digest()}.
  309. *
  310. * @param input the input to be updated before the digest is
  311. * completed.
  312. *
  313. * @return the array of bytes for the resulting hash value.
  314. */
  315. public byte[] digest(byte[] input) {
  316. update(input);
  317. return digest();
  318. }
  319. /**
  320. * Returns a string representation of this message digest object.
  321. */
  322. public String toString() {
  323. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  324. PrintStream p = new PrintStream(baos);
  325. p.print(algorithm+" Message Digest from "+provider.getName()+", ");
  326. switch (state) {
  327. case INITIAL:
  328. p.print("<initialized>");
  329. break;
  330. case IN_PROGRESS:
  331. p.print("<in progress>");
  332. break;
  333. }
  334. p.println();
  335. return (baos.toString());
  336. }
  337. /**
  338. * Compares two digests for equality. Does a simple byte compare.
  339. *
  340. * @param digesta one of the digests to compare.
  341. *
  342. * @param digestb the other digest to compare.
  343. *
  344. * @return true if the digests are equal, false otherwise.
  345. */
  346. public static boolean isEqual(byte digesta[], byte digestb[]) {
  347. if (digesta.length != digestb.length)
  348. return false;
  349. for (int i = 0; i < digesta.length; i++) {
  350. if (digesta[i] != digestb[i]) {
  351. return false;
  352. }
  353. }
  354. return true;
  355. }
  356. /**
  357. * Resets the digest for further use.
  358. */
  359. public void reset() {
  360. engineReset();
  361. state = INITIAL;
  362. }
  363. /**
  364. * Returns a string that identifies the algorithm, independent of
  365. * implementation details. The name should be a standard
  366. * Java Security name (such as "SHA", "MD5", and so on).
  367. * See Appendix A in the <a href=
  368. * "../../../guide/security/CryptoSpec.html#AppA">
  369. * Java Cryptography Architecture API Specification & Reference </a>
  370. * for information about standard algorithm names.
  371. *
  372. * @return the name of the algorithm
  373. */
  374. public final String getAlgorithm() {
  375. return this.algorithm;
  376. }
  377. /**
  378. * Returns the length of the digest in bytes, or 0 if this operation is
  379. * not supported by the provider and the implementation is not cloneable.
  380. *
  381. * @return the digest length in bytes, or 0 if this operation is not
  382. * supported by the provider and the implementation is not cloneable.
  383. *
  384. * @since 1.2
  385. */
  386. public final int getDigestLength() {
  387. int digestLen = engineGetDigestLength();
  388. if (digestLen == 0) {
  389. try {
  390. MessageDigest md = (MessageDigest)clone();
  391. byte[] digest = md.digest();
  392. return digest.length;
  393. } catch (CloneNotSupportedException e) {
  394. return digestLen;
  395. }
  396. }
  397. return digestLen;
  398. }
  399. /**
  400. * Returns a clone if the implementation is cloneable.
  401. *
  402. * @return a clone if the implementation is cloneable.
  403. *
  404. * @exception CloneNotSupportedException if this is called on an
  405. * implementation that does not support <code>Cloneable</code>.
  406. */
  407. public Object clone() throws CloneNotSupportedException {
  408. if (this instanceof Cloneable) {
  409. return super.clone();
  410. } else {
  411. throw new CloneNotSupportedException();
  412. }
  413. }
  414. /*
  415. * The following class allows providers to extend from MessageDigestSpi
  416. * rather than from MessageDigest. It represents a MessageDigest with an
  417. * encapsulated, provider-supplied SPI object (of type MessageDigestSpi).
  418. * If the provider implementation is an instance of MessageDigestSpi,
  419. * the getInstance() methods above return an instance of this class, with
  420. * the SPI object encapsulated.
  421. *
  422. * Note: All SPI methods from the original MessageDigest class have been
  423. * moved up the hierarchy into a new class (MessageDigestSpi), which has
  424. * been interposed in the hierarchy between the API (MessageDigest)
  425. * and its original parent (Object).
  426. */
  427. static class Delegate extends MessageDigest {
  428. // The provider implementation (delegate)
  429. private MessageDigestSpi digestSpi;
  430. // constructor
  431. public Delegate(MessageDigestSpi digestSpi, String algorithm) {
  432. super(algorithm);
  433. this.digestSpi = digestSpi;
  434. }
  435. /*
  436. * Returns a clone if the delegate is cloneable.
  437. *
  438. * @return a clone if the delegate is cloneable.
  439. *
  440. * @exception CloneNotSupportedException if this is called on a
  441. * delegate that does not support <code>Cloneable</code>.
  442. */
  443. public Object clone() throws CloneNotSupportedException {
  444. if (digestSpi instanceof Cloneable) {
  445. MessageDigestSpi digestSpiClone =
  446. (MessageDigestSpi)digestSpi.clone();
  447. // Because 'algorithm', 'provider', and 'state' are private
  448. // members of our supertype, we must perform a cast to
  449. // access them.
  450. MessageDigest that =
  451. new Delegate(digestSpiClone,
  452. ((MessageDigest)this).algorithm);
  453. that.provider = ((MessageDigest)this).provider;
  454. that.state = ((MessageDigest)this).state;
  455. return that;
  456. } else {
  457. throw new CloneNotSupportedException();
  458. }
  459. }
  460. protected int engineGetDigestLength() {
  461. return digestSpi.engineGetDigestLength();
  462. }
  463. protected void engineUpdate(byte input) {
  464. digestSpi.engineUpdate(input);
  465. }
  466. protected void engineUpdate(byte[] input, int offset, int len) {
  467. digestSpi.engineUpdate(input, offset, len);
  468. }
  469. protected byte[] engineDigest() {
  470. return digestSpi.engineDigest();
  471. }
  472. protected int engineDigest(byte[] buf, int offset, int len)
  473. throws DigestException {
  474. return digestSpi.engineDigest(buf, offset, len);
  475. }
  476. protected void engineReset() {
  477. digestSpi.engineReset();
  478. }
  479. }
  480. }