20 * or visit www.oracle.com if you need additional information or have any |
21 * or visit www.oracle.com if you need additional information or have any |
21 * questions. |
22 * questions. |
22 */ |
23 */ |
23 |
24 |
24 import static java.lang.System.out; |
25 import static java.lang.System.out; |
25 |
|
26 import java.nio.ByteBuffer; |
26 import java.nio.ByteBuffer; |
27 import java.security.DigestException; |
27 import java.security.DigestException; |
28 import java.security.MessageDigest; |
28 import java.security.MessageDigest; |
29 import java.util.Random; |
29 import java.security.NoSuchAlgorithmException; |
|
30 import java.security.Security; |
|
31 import jdk.testlibrary.RandomFactory; |
30 |
32 |
31 /** |
33 /** |
32 * @test |
34 * @test |
33 * @bug 8050371 |
35 * @bug 8050371 8156059 |
34 * @summary Check md.digest(data) value whether same with digest output value |
36 * @summary Check md.digest(data) value whether same with digest output value |
35 * with various update/digest methods. |
37 * with various update/digest methods. |
36 * @author Kevin Liu |
38 * @author Kevin Liu |
37 * @key randomness |
39 * @key randomness |
|
40 * @library /lib/testlibrary |
38 */ |
41 */ |
39 |
42 |
40 public class TestSameValue { |
43 public class TestSameValue { |
41 |
44 |
42 public static void main(String[] args) throws Exception { |
45 public static void main(String[] args) throws Exception { |
47 private void run() throws Exception { |
50 private void run() throws Exception { |
48 |
51 |
49 byte[] data = new byte[6706]; |
52 byte[] data = new byte[6706]; |
50 MessageDigest md = null; |
53 MessageDigest md = null; |
51 // Initialize input data |
54 // Initialize input data |
52 new Random().nextBytes(data); |
55 RandomFactory.getRandom().nextBytes(data); |
53 |
56 |
54 String[] providers = { |
57 String[] algorithmArr = { "SHA", "Sha", "MD5", "md5", "SHA-224", |
55 null, "SUN" |
58 "SHA-256", "SHA-384", "SHA-512", "SHA3-224", "SHA3-256", |
56 }; |
59 "SHA3-384", "SHA3-512" }; |
57 String[] algorithmArr = { |
60 |
58 "SHA", "Sha", "MD5", "md5", "SHA-224", "SHA-256", "SHA-384", |
61 for (String algorithm : algorithmArr) { |
59 "SHA-512" |
62 try { |
60 }; |
63 md = MessageDigest.getInstance(algorithm); |
61 |
64 |
62 for (String algorithm: algorithmArr) { |
65 for (UpdateDigestMethod updateMethod : UpdateDigestMethod |
63 for (String provider: providers) { |
|
64 if (provider != null) { |
|
65 md = MessageDigest.getInstance(algorithm, provider); |
|
66 } else { |
|
67 md = MessageDigest.getInstance(algorithm); |
|
68 } |
|
69 for (UpdateDigestMethod updateMethod: UpdateDigestMethod |
|
70 .values()) { |
66 .values()) { |
71 byte[] output = updateMethod.updateDigest(data, md); |
67 byte[] output = updateMethod.updateDigest(data, md); |
72 // Get the output and the "correct" one |
68 // Get the output and the "correct" one |
73 byte[] standard = md.digest(data); |
69 byte[] standard = md.digest(data); |
74 // Compare input and output |
70 // Compare input and output |
75 if (!MessageDigest.isEqual(output, standard)) { |
71 if (!MessageDigest.isEqual(output, standard)) { |
76 throw new RuntimeException( |
72 throw new RuntimeException( |
77 "Test failed at algorithm/provider/numUpdate:" |
73 "Test failed at algorithm/provider/numUpdate:" |
78 + algorithm + "/" + provider + "/" |
74 + algorithm + "/" + md.getProvider() |
79 + updateMethod); |
75 + "/" + updateMethod); |
80 } |
76 } |
81 } |
77 } |
|
78 } catch (NoSuchAlgorithmException nae) { |
|
79 if (algorithm.startsWith("SHA3") && !isSHA3supported()) { |
|
80 continue; |
|
81 } else { |
|
82 throw nae; |
|
83 } |
82 } |
84 } |
83 } |
85 } |
84 |
86 |
85 out.println("All " + algorithmArr.length |
87 out.println("All " |
86 * UpdateDigestMethod.values().length * providers.length |
88 + algorithmArr.length * UpdateDigestMethod.values().length |
87 + " tests Passed"); |
89 + " tests Passed"); |
88 } |
90 } |
89 |
91 |
|
92 // SHA-3 hash algorithms are only supported by "SUN" provider |
|
93 // and "OracleUcrypto" provider on Solaris 12.0 or later |
|
94 // This method checks if system supports SHA-3 |
|
95 private boolean isSHA3supported() { |
|
96 if (Security.getProvider("SUN") != null) { |
|
97 return true; |
|
98 } |
|
99 if (Security.getProvider("OracleUcrypto") != null |
|
100 && "SunOS".equals(System.getProperty("os.name")) |
|
101 && System.getProperty("os.version").compareTo("5.12") >= 0) { |
|
102 return true; |
|
103 } |
|
104 return false; |
|
105 } |
|
106 |
90 private static enum UpdateDigestMethod { |
107 private static enum UpdateDigestMethod { |
91 |
108 |
92 /* |
109 /* |
93 * update the data one by one using method update(byte input) then |
110 * update the data one by one using method update(byte input) then do |
94 * do digest (giving the output buffer, offset, and the number of |
111 * digest (giving the output buffer, offset, and the number of bytes to |
95 * bytes to put in the output buffer) |
112 * put in the output buffer) |
96 */ |
113 */ |
97 UPDATE_DIGEST_BUFFER { |
114 UPDATE_DIGEST_BUFFER { |
98 @Override |
115 @Override |
99 public byte[] updateDigest(byte[] data, MessageDigest md) |
116 public byte[] updateDigest(byte[] data, MessageDigest md) |
100 throws DigestException { |
117 throws DigestException { |
101 for (byte element: data) { |
118 for (byte element : data) { |
102 md.update(element); |
119 md.update(element); |
103 } |
120 } |
104 byte[] output = new byte[md.getDigestLength()]; |
121 byte[] output = new byte[md.getDigestLength()]; |
105 int len = md.digest(output, 0, output.length); |
122 int len = md.digest(output, 0, output.length); |
106 if (len != output.length) { |
123 if (len != output.length) { |
107 throw new RuntimeException( |
124 throw new RuntimeException( |
108 "ERROR" + ": digest length differs!"); |
125 "ERROR" + ": digest length differs!"); |
109 } |
126 } |
110 return output; |
127 return output; |
111 } |
128 } |
112 }, |
129 }, |
113 |
130 |
114 /* |
131 /* |
115 * update the data one by one using method update(byte input) |
132 * update the data one by one using method update(byte input) then do |
116 * then do digest |
133 * digest |
117 */ |
134 */ |
118 UPDATE_DIGEST { |
135 UPDATE_DIGEST { |
119 @Override |
136 @Override |
120 public byte[] updateDigest(byte[] data, MessageDigest md) { |
137 public byte[] updateDigest(byte[] data, MessageDigest md) { |
121 for (byte element: data) { |
138 for (byte element : data) { |
122 md.update(element); |
139 md.update(element); |
123 } |
140 } |
124 return md.digest(); |
141 return md.digest(); |
125 } |
142 } |
126 }, |
143 }, |
190 } |
207 } |
191 byte[] output = new byte[md.getDigestLength()]; |
208 byte[] output = new byte[md.getDigestLength()]; |
192 int len = md.digest(output, 0, output.length); |
209 int len = md.digest(output, 0, output.length); |
193 if (len != output.length) { |
210 if (len != output.length) { |
194 throw new RuntimeException( |
211 throw new RuntimeException( |
195 "ERROR" + ": digest length differs!"); |
212 "ERROR" + ": digest length differs!"); |
196 } |
213 } |
197 return output; |
214 return output; |
198 } |
215 } |
199 }, |
216 }, |
200 |
217 |
201 /* |
218 /* |
202 * update the data 2 bytes each time, after finishing updating, |
219 * update the data 2 bytes each time, after finishing updating, do |
203 * do digest |
220 * digest |
204 */ |
221 */ |
205 UPDATE_BYTES_DIGEST { |
222 UPDATE_BYTES_DIGEST { |
206 @Override |
223 @Override |
207 public byte[] updateDigest(byte[] data, MessageDigest md) { |
224 public byte[] updateDigest(byte[] data, MessageDigest md) { |
208 for (int i=0;i<data.length/2;i++){ |
225 for (int i = 0; i < data.length / 2; i++) { |
209 md.update(data,i*2,2); |
226 md.update(data, i * 2, 2); |
210 } |
227 } |
211 return md.digest(); |
228 return md.digest(); |
212 } |
229 } |
213 }, |
230 }, |
214 |
231 |
215 /* |
232 /* |
216 * update the data one by one using method update(byte[] input, |
233 * update the data one by one using method update(byte[] input, int |
217 * int offset, int len) for the leading bytes (length is |
234 * offset, int len) for the leading bytes (length is |
218 * "data.length-LASTNBYTES"), then do digest (do a final |
235 * "data.length-LASTNBYTES"), then do digest (do a final update using |
219 * update using the left LASTNBYTES bytes which is passed |
236 * the left LASTNBYTES bytes which is passed as a parameter for digest |
220 * as a parameter for digest method then complete the digest) |
237 * method then complete the digest) |
221 */ |
238 */ |
222 UPDATE_BUFFER_LEADING_DIGEST_REMAIN { |
239 UPDATE_BUFFER_LEADING_DIGEST_REMAIN { |
223 @Override |
240 @Override |
224 public byte[] updateDigest(byte[] data, MessageDigest md) { |
241 public byte[] updateDigest(byte[] data, MessageDigest md) { |
225 for (int i = 0; i < data.length - LASTNBYTES; i++) { |
242 for (int i = 0; i < data.length - LASTNBYTES; i++) { |
231 return md.digest(REMAIN); |
248 return md.digest(REMAIN); |
232 } |
249 } |
233 }, |
250 }, |
234 |
251 |
235 /* |
252 /* |
236 * update the data one by one using method update(byte input) |
253 * update the data one by one using method update(byte input) for the |
237 * for the leading bytes (length is "data.length-LASTNBYTES"), |
254 * leading bytes (length is "data.length-LASTNBYTES"), then do digest |
238 * then do digest (do a final update using the left LASTNBYTES |
255 * (do a final update using the left LASTNBYTES bytes which is passed as |
239 * bytes which is passed as a parameter for digest method, |
256 * a parameter for digest method, then complete the digest) |
240 * then complete the digest) |
|
241 */ |
257 */ |
242 UPDATE_LEADING_DIGEST_REMAIN { |
258 UPDATE_LEADING_DIGEST_REMAIN { |
243 @Override |
259 @Override |
244 public byte[] updateDigest(byte[] data, MessageDigest md) { |
260 public byte[] updateDigest(byte[] data, MessageDigest md) { |
245 for (int i = 0; i < data.length - LASTNBYTES; i++) { |
261 for (int i = 0; i < data.length - LASTNBYTES; i++) { |
251 return md.digest(REMAIN); |
267 return md.digest(REMAIN); |
252 } |
268 } |
253 }, |
269 }, |
254 |
270 |
255 /* |
271 /* |
256 * update all the data at once as a ByteBuffer, then do digest |
272 * update all the data at once as a ByteBuffer, then do digest (giving |
257 * (giving the output buffer, offset, and the number of bytes |
273 * the output buffer, offset, and the number of bytes to put in the |
258 * to put in the output buffer) |
274 * output buffer) |
259 */ |
275 */ |
260 UPDATE_BYTE_BUFFER_DIGEST_BUFFER { |
276 UPDATE_BYTE_BUFFER_DIGEST_BUFFER { |
261 @Override |
277 @Override |
262 public byte[] updateDigest(byte[] data, MessageDigest md) |
278 public byte[] updateDigest(byte[] data, MessageDigest md) |
263 throws DigestException { |
279 throws DigestException { |
264 md.update(ByteBuffer.wrap(data)); |
280 md.update(ByteBuffer.wrap(data)); |
265 byte[] output = new byte[md.getDigestLength()]; |
281 byte[] output = new byte[md.getDigestLength()]; |
266 int len = md.digest(output, 0, output.length); |
282 int len = md.digest(output, 0, output.length); |
267 if (len != output.length) { |
283 if (len != output.length) { |
268 throw new RuntimeException( |
284 throw new RuntimeException( |
269 "ERROR" + ": digest length differs!"); |
285 "ERROR" + ": digest length differs!"); |
270 } |
286 } |
271 return output; |
287 return output; |
272 } |
288 } |
273 }, |
289 }, |
274 |
290 |