J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved. |
| 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. Sun designates this |
| 8 | * particular file as subject to the "Classpath" exception as provided |
| 9 | * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 22 | * CA 95054 USA or visit www.sun.com if you need additional information or |
| 23 | * have any questions. |
| 24 | */ |
| 25 | |
| 26 | package sun.security.provider; |
| 27 | |
| 28 | import java.security.*; |
| 29 | import java.math.BigInteger; |
| 30 | |
| 31 | import static sun.security.provider.ByteArrayAccess.*; |
| 32 | |
| 33 | /** |
| 34 | * This class implements the Secure Hash Algorithm SHA-384 and SHA-512 |
| 35 | * developed by the National Institute of Standards and Technology along |
| 36 | * with the National Security Agency. |
| 37 | * |
| 38 | * The two algorithms are almost identical. This file contains a base |
| 39 | * class SHA5 and two nested static subclasses as the classes to be used |
| 40 | * by the JCA framework. |
| 41 | * |
| 42 | * <p>It implements java.security.MessageDigestSpi, and can be used |
| 43 | * through Java Cryptography Architecture (JCA), as a pluggable |
| 44 | * MessageDigest implementation. |
| 45 | * |
| 46 | * @since 1.4.2 |
| 47 | * @author Valerie Peng |
| 48 | * @author Andreas Sterbenz |
| 49 | */ |
| 50 | abstract class SHA5 extends DigestBase { |
| 51 | |
| 52 | private static final int ITERATION = 80; |
| 53 | // Constants for each round/iteration |
| 54 | private static final long[] ROUND_CONSTS = { |
| 55 | 0x428A2F98D728AE22L, 0x7137449123EF65CDL, 0xB5C0FBCFEC4D3B2FL, |
| 56 | 0xE9B5DBA58189DBBCL, 0x3956C25BF348B538L, 0x59F111F1B605D019L, |
| 57 | 0x923F82A4AF194F9BL, 0xAB1C5ED5DA6D8118L, 0xD807AA98A3030242L, |
| 58 | 0x12835B0145706FBEL, 0x243185BE4EE4B28CL, 0x550C7DC3D5FFB4E2L, |
| 59 | 0x72BE5D74F27B896FL, 0x80DEB1FE3B1696B1L, 0x9BDC06A725C71235L, |
| 60 | 0xC19BF174CF692694L, 0xE49B69C19EF14AD2L, 0xEFBE4786384F25E3L, |
| 61 | 0x0FC19DC68B8CD5B5L, 0x240CA1CC77AC9C65L, 0x2DE92C6F592B0275L, |
| 62 | 0x4A7484AA6EA6E483L, 0x5CB0A9DCBD41FBD4L, 0x76F988DA831153B5L, |
| 63 | 0x983E5152EE66DFABL, 0xA831C66D2DB43210L, 0xB00327C898FB213FL, |
| 64 | 0xBF597FC7BEEF0EE4L, 0xC6E00BF33DA88FC2L, 0xD5A79147930AA725L, |
| 65 | 0x06CA6351E003826FL, 0x142929670A0E6E70L, 0x27B70A8546D22FFCL, |
| 66 | 0x2E1B21385C26C926L, 0x4D2C6DFC5AC42AEDL, 0x53380D139D95B3DFL, |
| 67 | 0x650A73548BAF63DEL, 0x766A0ABB3C77B2A8L, 0x81C2C92E47EDAEE6L, |
| 68 | 0x92722C851482353BL, 0xA2BFE8A14CF10364L, 0xA81A664BBC423001L, |
| 69 | 0xC24B8B70D0F89791L, 0xC76C51A30654BE30L, 0xD192E819D6EF5218L, |
| 70 | 0xD69906245565A910L, 0xF40E35855771202AL, 0x106AA07032BBD1B8L, |
| 71 | 0x19A4C116B8D2D0C8L, 0x1E376C085141AB53L, 0x2748774CDF8EEB99L, |
| 72 | 0x34B0BCB5E19B48A8L, 0x391C0CB3C5C95A63L, 0x4ED8AA4AE3418ACBL, |
| 73 | 0x5B9CCA4F7763E373L, 0x682E6FF3D6B2B8A3L, 0x748F82EE5DEFB2FCL, |
| 74 | 0x78A5636F43172F60L, 0x84C87814A1F0AB72L, 0x8CC702081A6439ECL, |
| 75 | 0x90BEFFFA23631E28L, 0xA4506CEBDE82BDE9L, 0xBEF9A3F7B2C67915L, |
| 76 | 0xC67178F2E372532BL, 0xCA273ECEEA26619CL, 0xD186B8C721C0C207L, |
| 77 | 0xEADA7DD6CDE0EB1EL, 0xF57D4F7FEE6ED178L, 0x06F067AA72176FBAL, |
| 78 | 0x0A637DC5A2C898A6L, 0x113F9804BEF90DAEL, 0x1B710B35131C471BL, |
| 79 | 0x28DB77F523047D84L, 0x32CAAB7B40C72493L, 0x3C9EBE0A15C9BEBCL, |
| 80 | 0x431D67C49C100D4CL, 0x4CC5D4BECB3E42B6L, 0x597F299CFC657E2AL, |
| 81 | 0x5FCB6FAB3AD6FAECL, 0x6C44198C4A475817L |
| 82 | }; |
| 83 | |
| 84 | // buffer used by implCompress() |
| 85 | private final long[] W; |
| 86 | |
| 87 | // state of this object |
| 88 | private final long[] state; |
| 89 | |
| 90 | // initial state value. different between SHA-384 and SHA-512 |
| 91 | private final long[] initialHashes; |
| 92 | |
| 93 | /** |
| 94 | * Creates a new SHA object. |
| 95 | */ |
| 96 | SHA5(String name, int digestLength, long[] initialHashes) { |
| 97 | super(name, digestLength, 128); |
| 98 | this.initialHashes = initialHashes; |
| 99 | state = new long[8]; |
| 100 | W = new long[80]; |
| 101 | implReset(); |
| 102 | } |
| 103 | |
| 104 | /** |
| 105 | * Creates a SHA object with state (for cloning) |
| 106 | */ |
| 107 | SHA5(SHA5 base) { |
| 108 | super(base); |
| 109 | this.initialHashes = base.initialHashes; |
| 110 | this.state = base.state.clone(); |
| 111 | this.W = new long[80]; |
| 112 | } |
| 113 | |
| 114 | final void implReset() { |
| 115 | System.arraycopy(initialHashes, 0, state, 0, state.length); |
| 116 | } |
| 117 | |
| 118 | final void implDigest(byte[] out, int ofs) { |
| 119 | long bitsProcessed = bytesProcessed << 3; |
| 120 | |
| 121 | int index = (int)bytesProcessed & 0x7f; |
| 122 | int padLen = (index < 112) ? (112 - index) : (240 - index); |
| 123 | engineUpdate(padding, 0, padLen + 8); |
| 124 | |
| 125 | i2bBig4((int)(bitsProcessed >>> 32), buffer, 120); |
| 126 | i2bBig4((int)bitsProcessed, buffer, 124); |
| 127 | implCompress(buffer, 0); |
| 128 | |
| 129 | l2bBig(state, 0, out, ofs, engineGetDigestLength()); |
| 130 | } |
| 131 | |
| 132 | /** |
| 133 | * logical function ch(x,y,z) as defined in spec: |
| 134 | * @return (x and y) xor ((complement x) and z) |
| 135 | * @param x long |
| 136 | * @param y long |
| 137 | * @param z long |
| 138 | */ |
| 139 | private static long lf_ch(long x, long y, long z) { |
| 140 | return (x & y) ^ ((~x) & z); |
| 141 | } |
| 142 | |
| 143 | /** |
| 144 | * logical function maj(x,y,z) as defined in spec: |
| 145 | * @return (x and y) xor (x and z) xor (y and z) |
| 146 | * @param x long |
| 147 | * @param y long |
| 148 | * @param z long |
| 149 | */ |
| 150 | private static long lf_maj(long x, long y, long z) { |
| 151 | return (x & y) ^ (x & z) ^ (y & z); |
| 152 | } |
| 153 | |
| 154 | /** |
| 155 | * logical function R(x,s) - right shift |
| 156 | * @return x right shift for s times |
| 157 | * @param x long |
| 158 | * @param s int |
| 159 | */ |
| 160 | private static long lf_R(long x, int s) { |
| 161 | return (x >>> s); |
| 162 | } |
| 163 | |
| 164 | /** |
| 165 | * logical function S(x,s) - right rotation |
| 166 | * @return x circular right shift for s times |
| 167 | * @param x long |
| 168 | * @param s int |
| 169 | */ |
| 170 | private static long lf_S(long x, int s) { |
| 171 | return (x >>> s) | (x << (64 - s)); |
| 172 | } |
| 173 | |
| 174 | /** |
| 175 | * logical function sigma0(x) - xor of results of right rotations |
| 176 | * @return S(x,28) xor S(x,34) xor S(x,39) |
| 177 | * @param x long |
| 178 | */ |
| 179 | private static long lf_sigma0(long x) { |
| 180 | return lf_S(x, 28) ^ lf_S(x, 34) ^ lf_S(x, 39); |
| 181 | } |
| 182 | |
| 183 | /** |
| 184 | * logical function sigma1(x) - xor of results of right rotations |
| 185 | * @return S(x,14) xor S(x,18) xor S(x,41) |
| 186 | * @param x long |
| 187 | */ |
| 188 | private static long lf_sigma1(long x) { |
| 189 | return lf_S(x, 14) ^ lf_S(x, 18) ^ lf_S(x, 41); |
| 190 | } |
| 191 | |
| 192 | /** |
| 193 | * logical function delta0(x) - xor of results of right shifts/rotations |
| 194 | * @return long |
| 195 | * @param x long |
| 196 | */ |
| 197 | private static long lf_delta0(long x) { |
| 198 | return lf_S(x, 1) ^ lf_S(x, 8) ^ lf_R(x, 7); |
| 199 | } |
| 200 | |
| 201 | /** |
| 202 | * logical function delta1(x) - xor of results of right shifts/rotations |
| 203 | * @return long |
| 204 | * @param x long |
| 205 | */ |
| 206 | private static long lf_delta1(long x) { |
| 207 | return lf_S(x, 19) ^ lf_S(x, 61) ^ lf_R(x, 6); |
| 208 | } |
| 209 | |
| 210 | /** |
| 211 | * Compute the hash for the current block. |
| 212 | * |
| 213 | * This is in the same vein as Peter Gutmann's algorithm listed in |
| 214 | * the back of Applied Cryptography, Compact implementation of |
| 215 | * "old" NIST Secure Hash Algorithm. |
| 216 | */ |
| 217 | final void implCompress(byte[] buf, int ofs) { |
| 218 | b2lBig128(buf, ofs, W); |
| 219 | |
| 220 | // The first 16 longs are from the byte stream, compute the rest of |
| 221 | // the W[]'s |
| 222 | for (int t = 16; t < ITERATION; t++) { |
| 223 | W[t] = lf_delta1(W[t-2]) + W[t-7] + lf_delta0(W[t-15]) |
| 224 | + W[t-16]; |
| 225 | } |
| 226 | |
| 227 | long a = state[0]; |
| 228 | long b = state[1]; |
| 229 | long c = state[2]; |
| 230 | long d = state[3]; |
| 231 | long e = state[4]; |
| 232 | long f = state[5]; |
| 233 | long g = state[6]; |
| 234 | long h = state[7]; |
| 235 | |
| 236 | for (int i = 0; i < ITERATION; i++) { |
| 237 | long T1 = h + lf_sigma1(e) + lf_ch(e,f,g) + ROUND_CONSTS[i] + W[i]; |
| 238 | long T2 = lf_sigma0(a) + lf_maj(a,b,c); |
| 239 | h = g; |
| 240 | g = f; |
| 241 | f = e; |
| 242 | e = d + T1; |
| 243 | d = c; |
| 244 | c = b; |
| 245 | b = a; |
| 246 | a = T1 + T2; |
| 247 | } |
| 248 | state[0] += a; |
| 249 | state[1] += b; |
| 250 | state[2] += c; |
| 251 | state[3] += d; |
| 252 | state[4] += e; |
| 253 | state[5] += f; |
| 254 | state[6] += g; |
| 255 | state[7] += h; |
| 256 | } |
| 257 | |
| 258 | /** |
| 259 | * SHA-512 implementation class. |
| 260 | */ |
| 261 | public static final class SHA512 extends SHA5 { |
| 262 | |
| 263 | private static final long[] INITIAL_HASHES = { |
| 264 | 0x6a09e667f3bcc908L, 0xbb67ae8584caa73bL, |
| 265 | 0x3c6ef372fe94f82bL, 0xa54ff53a5f1d36f1L, |
| 266 | 0x510e527fade682d1L, 0x9b05688c2b3e6c1fL, |
| 267 | 0x1f83d9abfb41bd6bL, 0x5be0cd19137e2179L |
| 268 | }; |
| 269 | |
| 270 | public SHA512() { |
| 271 | super("SHA-512", 64, INITIAL_HASHES); |
| 272 | } |
| 273 | |
| 274 | private SHA512(SHA512 base) { |
| 275 | super(base); |
| 276 | } |
| 277 | |
| 278 | public Object clone() { |
| 279 | return new SHA512(this); |
| 280 | } |
| 281 | } |
| 282 | |
| 283 | /** |
| 284 | * SHA-384 implementation class. |
| 285 | */ |
| 286 | public static final class SHA384 extends SHA5 { |
| 287 | |
| 288 | private static final long[] INITIAL_HASHES = { |
| 289 | 0xcbbb9d5dc1059ed8L, 0x629a292a367cd507L, |
| 290 | 0x9159015a3070dd17L, 0x152fecd8f70e5939L, |
| 291 | 0x67332667ffc00b31L, 0x8eb44a8768581511L, |
| 292 | 0xdb0c2e0d64f98fa7L, 0x47b5481dbefa4fa4L |
| 293 | }; |
| 294 | |
| 295 | public SHA384() { |
| 296 | super("SHA-384", 48, INITIAL_HASHES); |
| 297 | } |
| 298 | |
| 299 | private SHA384(SHA384 base) { |
| 300 | super(base); |
| 301 | } |
| 302 | |
| 303 | public Object clone() { |
| 304 | return new SHA384(this); |
| 305 | } |
| 306 | } |
| 307 | |
| 308 | } |