Home | History | Annotate | Download | only in crypto
      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      */
     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      */
    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