1 /*
2 * Copyright (c) 2014, Red Hat, Inc.
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 /**
29 * This class provides static factory methods for commonly used
30 * message digest algorithms, using the default JCE provider.
31 *
32 * <p>Depending on the cryptography provider, additional message
33 * digest algorithms are available through
34 * {@link MessageDigest#getInstance(String)} and related methods.
35 *
36 * @since 1.9
37 */
38 public final class StandardMessageDigests {
39 private StandardMessageDigests() { } // No instances.
40
41 private static volatile MessageDigest sha1;
42 private static volatile MessageDigest sha256;
43 private static volatile MessageDigest sha384;
44 private static volatile MessageDigest sha512;
45
46 /**
47 * Create a new object implementing the SHA-1 message digest.
48 * @return a new message digest
49 * @throws NoSuchAlgorithmException
50 * the default provider does not support the SHA-1 algorithm
51 */
52 public static MessageDigest newSHA1() throws NoSuchAlgorithmException {
53 MessageDigest md = sha1;
54 if (md == null) {
55 md = createPrototype("SHA-1");
56 sha1 = md;
57 }
58 try {
59 return (MessageDigest) md.clone();
60 } catch (CloneNotSupportedException e) {
61 throw new AssertionError(e);
62 }
63 }
64
65 /**
66 * Create a new object implementing the SHA-256 message digest.
67 * @return a new message digest
68 * @throws NoSuchAlgorithmException
69 * the default provider does not support the SHA-256 algorithm
70 */
71 public static MessageDigest newSHA256() throws NoSuchAlgorithmException {
72 MessageDigest md = sha256;
73 if (md == null) {
74 md = createPrototype("SHA-256");
75 sha256 = md;
76 }
77 try {
78 return (MessageDigest) md.clone();
79 } catch (CloneNotSupportedException e) {
80 throw new AssertionError(e);
81 }
82 }
83
84 /**
85 * Create a new object implementing the SHA-384 message digest.
86 * @return a new message digest
87 * @throws NoSuchAlgorithmException
88 * the default provider does not support the SHA-384 algorithm
89 */
90 public static MessageDigest newSHA384() throws NoSuchAlgorithmException {
91 MessageDigest md = sha384;
92 if (md == null) {
93 md = createPrototype("SHA-384");
94 sha384 = md;
95 }
96 try {
97 return (MessageDigest) md.clone();
98 } catch (CloneNotSupportedException e) {
99 throw new AssertionError(e);
100 }
101 }
102
103 /**
104 * Create a new object implementing the SHA-512 message digest.
105 * @return a new message digest
106 * @throws NoSuchAlgorithmException
107 * the default provider does not support the SHA-512 algorithm
108 */
109 public static MessageDigest newSHA512() throws NoSuchAlgorithmException {
110 MessageDigest md = sha512;
111 if (md == null) {
112 md = createPrototype("SHA-512");
113 sha512 = md;
114 }
115 try {
116 return (MessageDigest) md.clone();
117 } catch (CloneNotSupportedException e) {
118 throw new AssertionError(e);
119 }
120 }
121
122 /**
123 * Internal class which allows non-cloneable message digests to
124 * act as prototype objects. Only cloning the initial state is
125 * actually implemented. Instances of this class are never
126 * returned, the {@link #clone()} method is invoked to create the
127 * actual message digest object.
128 */
129 static class MessageDigestPrototype extends MessageDigest {
130 MessageDigestPrototype(String algorithm) {
131 super(algorithm);
132 }
133
134 @Override
135 public Object clone() {
136 try {
137 return MessageDigest.getInstance(getAlgorithm());
138 } catch (NoSuchAlgorithmException e) {
139 throw new AssertionError(e);
140 }
141 }
142
143 @Override
144 protected void engineUpdate(byte input) {
145 throw new AssertionError();
146 }
147
148 @Override
149 protected void engineUpdate(byte[] input, int offset, int len) {
150 throw new AssertionError();
151 }
152
153 @Override
154 protected byte[] engineDigest() {
155 throw new AssertionError();
156 }
157
158 @Override
159 protected int engineDigest(byte[] buf, int offset, int len) {
160 throw new AssertionError();
161 }
162
163 @Override
164 protected void engineReset() {
165 throw new AssertionError();
166 }
167 }
168
169 /**
170 * Creates a new cloneable {@code MessageDigest} object.
171 */
172 private static MessageDigest createPrototype(String name)
173 throws NoSuchAlgorithmException {
174 MessageDigest md = MessageDigest.getInstance(name);
175 // The digest object can be a delegate which does not itself
176 // implement Cloneable, but clone() succeeds nevertheless, so
177 // we just call the method to see if it works.
178 try {
179 md.clone();
180 return md;
181 } catch (CloneNotSupportedException e) {
182 return new MessageDigestPrototype(name);
183 }
184 }
185 }