001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Yuri A. Kropachev
019: * @version $Revision$
020: */package org.apache.harmony.security.provider.crypto;
021:
022: /**
023: * This class contains methods providing SHA-1 functionality to use in classes. <BR>
024: * The methods support the algorithm described in "SECURE HASH STANDARD", FIPS PUB 180-2, <BR>
025: * "http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf" <BR>
026: * <BR>
027: * The class contains two package level access methods, -
028: * "void updateHash(int[], byte[], int, int)" and "void computeHash(int[])", -
029: * performing the following operations. <BR>
030: * <BR>
031: * The "updateHash(..)" method appends new bytes to existing ones
032: * within limit of a frame of 64 bytes (16 words).
033: * Once a length of accumulated bytes reaches the limit
034: * the "computeHash(int[])" method is invoked on the frame to compute updated hash,
035: * and the number of bytes in the frame is set to 0.
036: * Thus, after appending all bytes, the frame contain only those bytes
037: * that were not used in computing final hash value yet. <BR>
038: * <BR>
039: * The "computeHash(..)" method generates a 160 bit hash value using
040: * a 512 bit message stored in first 16 words of int[] array argument and
041: * current hash value stored in five words, beginning HASH_OFFSET, of the array argument.
042: * Computation is done according to SHA-1 algorithm. <BR>
043: * <BR>
044: * The resulting hash value replaces the previous hash value in the array;
045: * original bits of the message are not preserved.
046: */
047:
048: public class SHA1Impl implements SHA1_Data {
049:
050: /**
051: * The method generates a 160 bit hash value using
052: * a 512 bit message stored in first 16 words of int[] array argument and
053: * current hash value stored in five words, beginning OFFSET+1, of the array argument.
054: * Computation is done according to SHA-1 algorithm.
055: *
056: * The resulting hash value replaces the previous hash value in the array;
057: * original bits of the message are not preserved.
058: *
059: * No checks on argument supplied, that is,
060: * a calling method is responsible for such checks.
061: * In case of incorrect array passed to the method
062: * either NPE or IndexOutOfBoundException gets thrown by JVM.
063: *
064: * @params
065: * arrW - integer array; arrW.length >= (BYTES_OFFSET+6); <BR>
066: * only first (BYTES_OFFSET+6) words are used
067: */
068: static void computeHash(int arrW[]) {
069:
070: int a = arrW[HASH_OFFSET];
071: int b = arrW[HASH_OFFSET + 1];
072: int c = arrW[HASH_OFFSET + 2];
073: int d = arrW[HASH_OFFSET + 3];
074: int e = arrW[HASH_OFFSET + 4];
075:
076: int temp;
077:
078: // In this implementation the "d. For t = 0 to 79 do" loop
079: // is split into four loops. The following constants:
080: // K = 5A827999 0 <= t <= 19
081: // K = 6ED9EBA1 20 <= t <= 39
082: // K = 8F1BBCDC 40 <= t <= 59
083: // K = CA62C1D6 60 <= t <= 79
084: // are hex literals in the loops.
085:
086: for (int t = 16; t < 80; t++) {
087:
088: temp = arrW[t - 3] ^ arrW[t - 8] ^ arrW[t - 14]
089: ^ arrW[t - 16];
090: arrW[t] = (temp << 1) | (temp >>> 31);
091: }
092:
093: for (int t = 0; t < 20; t++) {
094:
095: temp = ((a << 5) | (a >>> 27)) + ((b & c) | ((~b) & d))
096: + (e + arrW[t] + 0x5A827999);
097: e = d;
098: d = c;
099: c = (b << 30) | (b >>> 2);
100: b = a;
101: a = temp;
102: }
103: for (int t = 20; t < 40; t++) {
104:
105: temp = (((a << 5) | (a >>> 27))) + (b ^ c ^ d)
106: + (e + arrW[t] + 0x6ED9EBA1);
107: e = d;
108: d = c;
109: c = (b << 30) | (b >>> 2);
110: b = a;
111: a = temp;
112: }
113: for (int t = 40; t < 60; t++) {
114:
115: temp = ((a << 5) | (a >>> 27))
116: + ((b & c) | (b & d) | (c & d))
117: + (e + arrW[t] + 0x8F1BBCDC);
118: e = d;
119: d = c;
120: c = (b << 30) | (b >>> 2);
121: b = a;
122: a = temp;
123: }
124: for (int t = 60; t < 80; t++) {
125:
126: temp = (((a << 5) | (a >>> 27))) + (b ^ c ^ d)
127: + (e + arrW[t] + 0xCA62C1D6);
128: e = d;
129: d = c;
130: c = (b << 30) | (b >>> 2);
131: b = a;
132: a = temp;
133: }
134:
135: arrW[HASH_OFFSET] += a;
136: arrW[HASH_OFFSET + 1] += b;
137: arrW[HASH_OFFSET + 2] += c;
138: arrW[HASH_OFFSET + 3] += d;
139: arrW[HASH_OFFSET + 4] += e;
140: }
141:
142: /**
143: * The method appends new bytes to existing ones
144: * within limit of a frame of 64 bytes (16 words).
145: *
146: * Once a length of accumulated bytes reaches the limit
147: * the "computeHash(int[])" method is invoked on the array to compute updated hash,
148: * and the number of bytes in the frame is set to 0.
149: * Thus, after appending all bytes, the array contain only those bytes
150: * that were not used in computing final hash value yet.
151: *
152: * No checks on arguments passed to the method, that is,
153: * a calling method is responsible for such checks.
154: *
155: * @params
156: * intArray - int array containing bytes to which to append;
157: * intArray.length >= (BYTES_OFFSET+6)
158: * @params
159: * byteInput - array of bytes to use for the update
160: * @params
161: * from - the offset to start in the "byteInput" array
162: * @params
163: * to - a number of the last byte in the input array to use,
164: * that is, for first byte "to"==0, for last byte "to"==input.length-1
165: */
166: static void updateHash(int intArray[], byte byteInput[],
167: int fromByte, int toByte) {
168:
169: // As intArray contains a packed bytes
170: // the buffer's index is in the intArray[BYTES_OFFSET] element
171:
172: int index = intArray[BYTES_OFFSET];
173: int i = fromByte;
174: int maxWord;
175: int nBytes;
176:
177: int wordIndex = index >> 2;
178: int byteIndex = index & 0x03;
179:
180: intArray[BYTES_OFFSET] = (index + toByte - fromByte + 1) & 077;
181:
182: // In general case there are 3 stages :
183: // - appending bytes to non-full word,
184: // - writing 4 bytes into empty words,
185: // - writing less than 4 bytes in last word
186:
187: if (byteIndex != 0) { // appending bytes in non-full word (as if)
188:
189: for (; (i <= toByte) && (byteIndex < 4); i++) {
190: intArray[wordIndex] |= (byteInput[i] & 0xFF) << ((3 - byteIndex) << 3);
191: byteIndex++;
192: }
193: if (byteIndex == 4) {
194: wordIndex++;
195: if (wordIndex == 16) { // intArray is full, computing hash
196:
197: computeHash(intArray);
198: wordIndex = 0;
199: }
200: }
201: if (i > toByte) { // all input bytes appended
202: return;
203: }
204: }
205:
206: // writing full words
207:
208: maxWord = (toByte - i + 1) >> 2; // # of remaining full words, may be "0"
209: for (int k = 0; k < maxWord; k++) {
210:
211: intArray[wordIndex] = (((int) byteInput[i] & 0xFF) << 24)
212: | (((int) byteInput[i + 1] & 0xFF) << 16)
213: | (((int) byteInput[i + 2] & 0xFF) << 8)
214: | (((int) byteInput[i + 3] & 0xFF));
215: i += 4;
216: wordIndex++;
217:
218: if (wordIndex < 16) { // buffer is not full yet
219: continue;
220: }
221: computeHash(intArray); // buffer is full, computing hash
222: wordIndex = 0;
223: }
224:
225: // writing last incomplete word
226: // after writing free byte positions are set to "0"s
227:
228: nBytes = toByte - i + 1;
229: if (nBytes != 0) {
230:
231: int w = ((int) byteInput[i] & 0xFF) << 24;
232:
233: if (nBytes != 1) {
234: w |= ((int) byteInput[i + 1] & 0xFF) << 16;
235: if (nBytes != 2) {
236: w |= ((int) byteInput[i + 2] & 0xFF) << 8;
237: }
238: }
239: intArray[wordIndex] = w;
240: }
241:
242: return;
243: }
244:
245: }
|