1 /* Sha512.java -- 2 Copyright (C) 2003, 2006 Free Software Foundation, Inc. 3 4 This file is a part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or (at 9 your option) any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 19 USA 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 39 package gnu.java.security.hash; 40 41 import gnu.java.security.Registry; 42 import gnu.java.security.util.Util; 43 44 /** 45 * Implementation of SHA2-3 [SHA-512] per the IETF Draft Specification. 46 * <p> 47 * References: 48 * <ol> 49 * <li><a href="http://ftp.ipv4.heanet.ie/pub/ietf/internet-drafts/draft-ietf-ipsec-ciph-aes-cbc-03.txt"> 50 * Descriptions of SHA-256, SHA-384, and SHA-512</a>,</li> 51 * <li>http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf</li> 52 * </ol> 53 */ 54 public class Sha512 55 extends BaseHash 56 { 57 private static final long[] k = { 58 0x428a2f98d728ae22L, 0x7137449123ef65cdL, 0xb5c0fbcfec4d3b2fL, 59 0xe9b5dba58189dbbcL, 0x3956c25bf348b538L, 0x59f111f1b605d019L, 60 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L, 0xd807aa98a3030242L, 61 0x12835b0145706fbeL, 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L, 62 0x72be5d74f27b896fL, 0x80deb1fe3b1696b1L, 0x9bdc06a725c71235L, 63 0xc19bf174cf692694L, 0xe49b69c19ef14ad2L, 0xefbe4786384f25e3L, 64 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L, 0x2de92c6f592b0275L, 65 0x4a7484aa6ea6e483L, 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L, 66 0x983e5152ee66dfabL, 0xa831c66d2db43210L, 0xb00327c898fb213fL, 67 0xbf597fc7beef0ee4L, 0xc6e00bf33da88fc2L, 0xd5a79147930aa725L, 68 0x06ca6351e003826fL, 0x142929670a0e6e70L, 0x27b70a8546d22ffcL, 69 0x2e1b21385c26c926L, 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL, 70 0x650a73548baf63deL, 0x766a0abb3c77b2a8L, 0x81c2c92e47edaee6L, 71 0x92722c851482353bL, 0xa2bfe8a14cf10364L, 0xa81a664bbc423001L, 72 0xc24b8b70d0f89791L, 0xc76c51a30654be30L, 0xd192e819d6ef5218L, 73 0xd69906245565a910L, 0xf40e35855771202aL, 0x106aa07032bbd1b8L, 74 0x19a4c116b8d2d0c8L, 0x1e376c085141ab53L, 0x2748774cdf8eeb99L, 75 0x34b0bcb5e19b48a8L, 0x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL, 76 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L, 0x748f82ee5defb2fcL, 77 0x78a5636f43172f60L, 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL, 78 0x90befffa23631e28L, 0xa4506cebde82bde9L, 0xbef9a3f7b2c67915L, 79 0xc67178f2e372532bL, 0xca273eceea26619cL, 0xd186b8c721c0c207L, 80 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L, 0x06f067aa72176fbaL, 81 0x0a637dc5a2c898a6L, 0x113f9804bef90daeL, 0x1b710b35131c471bL, 82 0x28db77f523047d84L, 0x32caab7b40c72493L, 0x3c9ebe0a15c9bebcL, 83 0x431d67c49c100d4cL, 0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL, 84 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L }; 85 86 private static final int BLOCK_SIZE = 128; // inner block size in bytes 87 88 private static final String DIGEST0 = 89 "DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA20A9EEEE64B55D39A" 90 + "2192992A274FC1A836BA3C23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F"; 91 92 private static final long[] w = new long[80]; 93 94 /** caches the result of the correctness test, once executed. */ 95 private static Boolean valid; 96 97 /** 512-bit interim result. */ 98 private long h0, h1, h2, h3, h4, h5, h6, h7; 99 100 /** Trivial 0-arguments constructor. */ Sha512()101 public Sha512() 102 { 103 super(Registry.SHA512_HASH, 64, BLOCK_SIZE); 104 } 105 106 /** 107 * Private constructor for cloning purposes. 108 * 109 * @param md the instance to clone. 110 */ Sha512(Sha512 md)111 private Sha512(Sha512 md) 112 { 113 this(); 114 115 this.h0 = md.h0; 116 this.h1 = md.h1; 117 this.h2 = md.h2; 118 this.h3 = md.h3; 119 this.h4 = md.h4; 120 this.h5 = md.h5; 121 this.h6 = md.h6; 122 this.h7 = md.h7; 123 this.count = md.count; 124 this.buffer = (byte[]) md.buffer.clone(); 125 } 126 G(long hh0, long hh1, long hh2, long hh3, long hh4, long hh5, long hh6, long hh7, byte[] in, int offset)127 public static final long[] G(long hh0, long hh1, long hh2, long hh3, 128 long hh4, long hh5, long hh6, long hh7, 129 byte[] in, int offset) 130 { 131 return sha(hh0, hh1, hh2, hh3, hh4, hh5, hh6, hh7, in, offset); 132 } 133 clone()134 public Object clone() 135 { 136 return new Sha512(this); 137 } 138 transform(byte[] in, int offset)139 protected void transform(byte[] in, int offset) 140 { 141 long[] result = sha(h0, h1, h2, h3, h4, h5, h6, h7, in, offset); 142 h0 = result[0]; 143 h1 = result[1]; 144 h2 = result[2]; 145 h3 = result[3]; 146 h4 = result[4]; 147 h5 = result[5]; 148 h6 = result[6]; 149 h7 = result[7]; 150 } 151 padBuffer()152 protected byte[] padBuffer() 153 { 154 int n = (int)(count % BLOCK_SIZE); 155 int padding = (n < 112) ? (112 - n) : (240 - n); 156 byte[] result = new byte[padding + 16]; 157 // padding is always binary 1 followed by binary 0s 158 result[0] = (byte) 0x80; 159 // save number of bits, casting the long to an array of 8 bytes 160 // TODO: FIX Only ~35 bits of 128 bit counter usable this way 161 long bits = count << 3; 162 padding += 8; 163 result[padding++] = (byte)(bits >>> 56); 164 result[padding++] = (byte)(bits >>> 48); 165 result[padding++] = (byte)(bits >>> 40); 166 result[padding++] = (byte)(bits >>> 32); 167 result[padding++] = (byte)(bits >>> 24); 168 result[padding++] = (byte)(bits >>> 16); 169 result[padding++] = (byte)(bits >>> 8); 170 result[padding ] = (byte) bits; 171 return result; 172 } 173 getResult()174 protected byte[] getResult() 175 { 176 return new byte[] { 177 (byte)(h0 >>> 56), (byte)(h0 >>> 48), (byte)(h0 >>> 40), (byte)(h0 >>> 32), 178 (byte)(h0 >>> 24), (byte)(h0 >>> 16), (byte)(h0 >>> 8), (byte) h0, 179 (byte)(h1 >>> 56), (byte)(h1 >>> 48), (byte)(h1 >>> 40), (byte)(h1 >>> 32), 180 (byte)(h1 >>> 24), (byte)(h1 >>> 16), (byte)(h1 >>> 8), (byte) h1, 181 (byte)(h2 >>> 56), (byte)(h2 >>> 48), (byte)(h2 >>> 40), (byte)(h2 >>> 32), 182 (byte)(h2 >>> 24), (byte)(h2 >>> 16), (byte)(h2 >>> 8), (byte) h2, 183 (byte)(h3 >>> 56), (byte)(h3 >>> 48), (byte)(h3 >>> 40), (byte)(h3 >>> 32), 184 (byte)(h3 >>> 24), (byte)(h3 >>> 16), (byte)(h3 >>> 8), (byte) h3, 185 (byte)(h4 >>> 56), (byte)(h4 >>> 48), (byte)(h4 >>> 40), (byte)(h4 >>> 32), 186 (byte)(h4 >>> 24), (byte)(h4 >>> 16), (byte)(h4 >>> 8), (byte) h4, 187 (byte)(h5 >>> 56), (byte)(h5 >>> 48), (byte)(h5 >>> 40), (byte)(h5 >>> 32), 188 (byte)(h5 >>> 24), (byte)(h5 >>> 16), (byte)(h5 >>> 8), (byte) h5, 189 (byte)(h6 >>> 56), (byte)(h6 >>> 48), (byte)(h6 >>> 40), (byte)(h6 >>> 32), 190 (byte)(h6 >>> 24), (byte)(h6 >>> 16), (byte)(h6 >>> 8), (byte) h6, 191 (byte)(h7 >>> 56), (byte)(h7 >>> 48), (byte)(h7 >>> 40), (byte)(h7 >>> 32), 192 (byte)(h7 >>> 24), (byte)(h7 >>> 16), (byte)(h7 >>> 8), (byte) h7 }; 193 } 194 resetContext()195 protected void resetContext() 196 { 197 // magic SHA-512 initialisation constants 198 h0 = 0x6a09e667f3bcc908L; 199 h1 = 0xbb67ae8584caa73bL; 200 h2 = 0x3c6ef372fe94f82bL; 201 h3 = 0xa54ff53a5f1d36f1L; 202 h4 = 0x510e527fade682d1L; 203 h5 = 0x9b05688c2b3e6c1fL; 204 h6 = 0x1f83d9abfb41bd6bL; 205 h7 = 0x5be0cd19137e2179L; 206 } 207 selfTest()208 public boolean selfTest() 209 { 210 if (valid == null) 211 { 212 Sha512 md = new Sha512(); 213 md.update((byte) 0x61); // a 214 md.update((byte) 0x62); // b 215 md.update((byte) 0x63); // c 216 String result = Util.toString(md.digest()); 217 valid = Boolean.valueOf(DIGEST0.equals(result)); 218 } 219 return valid.booleanValue(); 220 } 221 sha(long hh0, long hh1, long hh2, long hh3, long hh4, long hh5, long hh6, long hh7, byte[] in, int offset)222 private static synchronized final long[] sha(long hh0, long hh1, long hh2, 223 long hh3, long hh4, long hh5, 224 long hh6, long hh7, byte[] in, 225 int offset) 226 { 227 long A = hh0; 228 long B = hh1; 229 long C = hh2; 230 long D = hh3; 231 long E = hh4; 232 long F = hh5; 233 long G = hh6; 234 long H = hh7; 235 long T, T2; 236 int r; 237 for (r = 0; r < 16; r++) 238 w[r] = (long) in[offset++] << 56 239 | ((long) in[offset++] & 0xFF) << 48 240 | ((long) in[offset++] & 0xFF) << 40 241 | ((long) in[offset++] & 0xFF) << 32 242 | ((long) in[offset++] & 0xFF) << 24 243 | ((long) in[offset++] & 0xFF) << 16 244 | ((long) in[offset++] & 0xFF) << 8 245 | ((long) in[offset++] & 0xFF); 246 for (r = 16; r < 80; r++) 247 { 248 T = w[r - 2]; 249 T2 = w[r - 15]; 250 w[r] = (((T >>> 19) | (T << 45)) ^ ((T >>> 61) | (T << 3)) ^ (T >>> 6)) 251 + w[r - 7] 252 + (((T2 >>> 1) | (T2 << 63)) 253 ^ ((T2 >>> 8) | (T2 << 56)) 254 ^ (T2 >>> 7)) 255 + w[r - 16]; 256 } 257 for (r = 0; r < 80; r++) 258 { 259 T = H 260 + (((E >>> 14) | (E << 50)) 261 ^ ((E >>> 18) | (E << 46)) 262 ^ ((E >>> 41) | (E << 23))) 263 + ((E & F) ^ ((~E) & G)) + k[r] + w[r]; 264 T2 = (((A >>> 28) | (A << 36)) 265 ^ ((A >>> 34) | (A << 30)) 266 ^ ((A >>> 39) | (A << 25))) 267 + ((A & B) ^ (A & C) ^ (B & C)); 268 H = G; 269 G = F; 270 F = E; 271 E = D + T; 272 D = C; 273 C = B; 274 B = A; 275 A = T + T2; 276 } 277 return new long[] { 278 hh0 + A, hh1 + B, hh2 + C, hh3 + D, 279 hh4 + E, hh5 + F, hh6 + G, hh7 + H }; 280 } 281 } 282