1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 /** 18 * @author Yuri A. Kropachev 19 * @version $Revision$ 20 */ 21 22 23 package org.apache.harmony.security.provider.crypto; 24 25 26 /** 27 * This class contains methods providing SHA-1 functionality to use in classes. <BR> 28 * The methods support the algorithm described in "SECURE HASH STANDARD", FIPS PUB 180-2, <BR> 29 * "http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf" <BR> 30 * <BR> 31 * The class contains two package level access methods, - 32 * "void updateHash(int[], byte[], int, int)" and "void computeHash(int[])", - 33 * performing the following operations. <BR> 34 * <BR> 35 * The "updateHash(..)" method appends new bytes to existing ones 36 * within limit of a frame of 64 bytes (16 words). 37 * Once a length of accumulated bytes reaches the limit 38 * the "computeHash(int[])" method is invoked on the frame to compute updated hash, 39 * and the number of bytes in the frame is set to 0. 40 * Thus, after appending all bytes, the frame contain only those bytes 41 * that were not used in computing final hash value yet. <BR> 42 * <BR> 43 * The "computeHash(..)" method generates a 160 bit hash value using 44 * a 512 bit message stored in first 16 words of int[] array argument and 45 * current hash value stored in five words, beginning HASH_OFFSET, of the array argument. 46 * Computation is done according to SHA-1 algorithm. <BR> 47 * <BR> 48 * The resulting hash value replaces the previous hash value in the array; 49 * original bits of the message are not preserved. 50 */ 51 52 53 public class SHA1Impl implements SHA1_Data { 54 55 56 /** 57 * The method generates a 160 bit hash value using 58 * a 512 bit message stored in first 16 words of int[] array argument and 59 * current hash value stored in five words, beginning OFFSET+1, of the array argument. 60 * Computation is done according to SHA-1 algorithm. 61 * 62 * The resulting hash value replaces the previous hash value in the array; 63 * original bits of the message are not preserved. 64 * 65 * No checks on argument supplied, that is, 66 * a calling method is responsible for such checks. 67 * In case of incorrect array passed to the method 68 * either NPE or IndexOutOfBoundException gets thrown by JVM. 69 * 70 * @params 71 * arrW - integer array; arrW.length >= (BYTES_OFFSET+6); <BR> 72 * only first (BYTES_OFFSET+6) words are used 73 */ 74 static void computeHash(int[] arrW) { 75 76 int a = arrW[HASH_OFFSET ]; 77 int b = arrW[HASH_OFFSET +1]; 78 int c = arrW[HASH_OFFSET +2]; 79 int d = arrW[HASH_OFFSET +3]; 80 int e = arrW[HASH_OFFSET +4]; 81 82 int temp; 83 84 // In this implementation the "d. For t = 0 to 79 do" loop 85 // is split into four loops. The following constants: 86 // K = 5A827999 0 <= t <= 19 87 // K = 6ED9EBA1 20 <= t <= 39 88 // K = 8F1BBCDC 40 <= t <= 59 89 // K = CA62C1D6 60 <= t <= 79 90 // are hex literals in the loops. 91 92 for ( int t = 16; t < 80 ; t++ ) { 93 94 temp = arrW[t-3] ^ arrW[t-8] ^ arrW[t-14] ^ arrW[t-16]; 95 arrW[t] = ( temp<<1 ) | ( temp>>>31 ); 96 } 97 98 for ( int t = 0 ; t < 20 ; t++ ) { 99 100 temp = ( ( a<<5 ) | ( a>>>27 ) ) + 101 ( ( b & c) | ((~b) & d) ) + 102 ( e + arrW[t] + 0x5A827999 ) ; 103 e = d; 104 d = c; 105 c = ( b<<30 ) | ( b>>>2 ) ; 106 b = a; 107 a = temp; 108 } 109 for ( int t = 20 ; t < 40 ; t++ ) { 110 111 temp = ((( a<<5 ) | ( a>>>27 ))) + (b ^ c ^ d) + (e + arrW[t] + 0x6ED9EBA1) ; 112 e = d; 113 d = c; 114 c = ( b<<30 ) | ( b>>>2 ) ; 115 b = a; 116 a = temp; 117 } 118 for ( int t = 40 ; t < 60 ; t++ ) { 119 120 temp = (( a<<5 ) | ( a>>>27 )) + ((b & c) | (b & d) | (c & d)) + 121 (e + arrW[t] + 0x8F1BBCDC) ; 122 e = d; 123 d = c; 124 c = ( b<<30 ) | ( b>>>2 ) ; 125 b = a; 126 a = temp; 127 } 128 for ( int t = 60 ; t < 80 ; t++ ) { 129 130 temp = ((( a<<5 ) | ( a>>>27 ))) + (b ^ c ^ d) + (e + arrW[t] + 0xCA62C1D6) ; 131 e = d; 132 d = c; 133 c = ( b<<30 ) | ( b>>>2 ) ; 134 b = a; 135 a = temp; 136 } 137 138 arrW[HASH_OFFSET ] += a; 139 arrW[HASH_OFFSET +1] += b; 140 arrW[HASH_OFFSET +2] += c; 141 arrW[HASH_OFFSET +3] += d; 142 arrW[HASH_OFFSET +4] += e; 143 } 144 145 /** 146 * The method appends new bytes to existing ones 147 * within limit of a frame of 64 bytes (16 words). 148 * 149 * Once a length of accumulated bytes reaches the limit 150 * the "computeHash(int[])" method is invoked on the array to compute updated hash, 151 * and the number of bytes in the frame is set to 0. 152 * Thus, after appending all bytes, the array contain only those bytes 153 * that were not used in computing final hash value yet. 154 * 155 * No checks on arguments passed to the method, that is, 156 * a calling method is responsible for such checks. 157 * 158 * @params 159 * intArray - int array containing bytes to which to append; 160 * intArray.length >= (BYTES_OFFSET+6) 161 * @params 162 * byteInput - array of bytes to use for the update 163 * @params 164 * from - the offset to start in the "byteInput" array 165 * @params 166 * to - a number of the last byte in the input array to use, 167 * that is, for first byte "to"==0, for last byte "to"==input.length-1 168 */ 169 static void updateHash(int[] intArray, byte[] byteInput, int fromByte, int toByte) { 170 171 // As intArray contains a packed bytes 172 // the buffer's index is in the intArray[BYTES_OFFSET] element 173 174 int index = intArray[BYTES_OFFSET]; 175 int i = fromByte; 176 int maxWord; 177 int nBytes; 178 179 int wordIndex = index >>2; 180 int byteIndex = index & 0x03; 181 182 intArray[BYTES_OFFSET] = ( index + toByte - fromByte + 1 ) & 077 ; 183 184 // In general case there are 3 stages : 185 // - appending bytes to non-full word, 186 // - writing 4 bytes into empty words, 187 // - writing less than 4 bytes in last word 188 189 if ( byteIndex != 0 ) { // appending bytes in non-full word (as if) 190 191 for ( ; ( i <= toByte ) && ( byteIndex < 4 ) ; i++ ) { 192 intArray[wordIndex] |= ( byteInput[i] & 0xFF ) << ((3 - byteIndex)<<3) ; 193 byteIndex++; 194 } 195 if ( byteIndex == 4 ) { 196 wordIndex++; 197 if ( wordIndex == 16 ) { // intArray is full, computing hash 198 199 computeHash(intArray); 200 wordIndex = 0; 201 } 202 } 203 if ( i > toByte ) { // all input bytes appended 204 return ; 205 } 206 } 207 208 // writing full words 209 210 maxWord = (toByte - i + 1) >> 2; // # of remaining full words, may be "0" 211 for ( int k = 0; k < maxWord ; k++ ) { 212 213 intArray[wordIndex] = ( ((int) byteInput[i ] & 0xFF) <<24 ) | 214 ( ((int) byteInput[i +1] & 0xFF) <<16 ) | 215 ( ((int) byteInput[i +2] & 0xFF) <<8 ) | 216 ( ((int) byteInput[i +3] & 0xFF) ) ; 217 i += 4; 218 wordIndex++; 219 220 if ( wordIndex < 16 ) { // buffer is not full yet 221 continue; 222 } 223 computeHash(intArray); // buffer is full, computing hash 224 wordIndex = 0; 225 } 226 227 // writing last incomplete word 228 // after writing free byte positions are set to "0"s 229 230 nBytes = toByte - i +1; 231 if ( nBytes != 0 ) { 232 233 int w = ((int) byteInput[i] & 0xFF) <<24 ; 234 235 if ( nBytes != 1 ) { 236 w |= ((int) byteInput[i +1] & 0xFF) <<16 ; 237 if ( nBytes != 2) { 238 w |= ((int) byteInput[i +2] & 0xFF) <<8 ; 239 } 240 } 241 intArray[wordIndex] = w; 242 } 243 244 return ; 245 } 246 247 } 248