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