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 }