Source for gnu.java.security.provider.SHA

   1: /* SHA.java -- Class implementing the SHA-1 algorithm as specified in [1].
   2:    Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
   3: 
   4: This file is 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, or (at your option)
   9: 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; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 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.provider;
  40: 
  41: import java.security.MessageDigest;
  42: 
  43: /**
  44:    This class implements the SHA-1 algorithm as described in [1].
  45: 
  46:    [1] Federal Information Processing Standards Publication 180-1.
  47:    Specifications for the Secure Hash Standard.  April 17, 1995.
  48: 
  49:    @see java.security.MessageDigest
  50: */
  51: public class SHA extends MessageDigest implements Cloneable
  52: {
  53:   public SHA ()
  54:   {
  55:     super("SHA");
  56:     engineReset ();
  57:   }
  58: 
  59:   public int engineGetDigestLength()
  60:   {
  61:     return 20;
  62:   }
  63: 
  64:   public void engineUpdate (byte b)
  65:   {
  66:     int i = ((int)bytecount) & 0x3f; //wgs
  67:     int shift = (3 - i % 4) << 3;
  68:     int idx = i / 4;
  69: 
  70:     i = (int)b;
  71:     W[idx] = (W[idx] & ~(0xff << shift)) | ((i & 0xff) << shift);
  72: 
  73:     // if we've filled up a block, then process it
  74:     if (((++bytecount) & 0x3f) == 0)
  75:       munch ();
  76:   }
  77: 
  78:   // This could be optimized.
  79:   public void engineUpdate (byte bytes[], int off, int len)
  80:   {
  81:     if (len < 0)
  82:       throw new ArrayIndexOutOfBoundsException ();
  83: 
  84:     int end = off + len;
  85:     while (off < end)
  86:       engineUpdate (bytes[off++]);
  87:   }
  88: 
  89:   public void engineReset ()
  90:   {
  91:     bytecount = 0;
  92:     // magic numbers from [1] p. 10.
  93:     H0 = 0x67452301;
  94:     H1 = 0xefcdab89;
  95:     H2 = 0x98badcfe;
  96:     H3 = 0x10325476;
  97:     H4 = 0xc3d2e1f0;
  98:   }
  99: 
 100:   public byte[] engineDigest ()
 101:   {
 102:     long bitcount = bytecount << 3;
 103:     engineUpdate ((byte)0x80); // 10000000 in binary; the start of the padding
 104: 
 105:     // add the rest of the padding to fill this block out, but leave 8
 106:     // bytes to put in the original bytecount
 107:     while ((bytecount & 0x3f) != 56)
 108:       engineUpdate ((byte)0);
 109: 
 110:     // add the length of the original, unpadded block to the end of
 111:     // the padding
 112:     W[14] = (int)(bitcount >>> 32);
 113:     W[15] = (int)bitcount;
 114:     bytecount += 8;
 115: 
 116:     // digest the fully padded block
 117:     munch ();
 118: 
 119:     byte[] result
 120:       = new byte[] {(byte)(H0 >>> 24), (byte)(H0 >>> 16),
 121:             (byte)(H0 >>> 8), (byte)H0,
 122:             (byte)(H1 >>> 24), (byte)(H1 >>> 16),
 123:             (byte)(H1 >>> 8), (byte)H1,
 124:             (byte)(H2 >>> 24), (byte)(H2 >>> 16),
 125:             (byte)(H2 >>> 8), (byte)H2,
 126:             (byte)(H3 >>> 24), (byte)(H3 >>> 16),
 127:             (byte)(H3 >>> 8), (byte)H3,
 128:             (byte)(H4 >>> 24), (byte)(H4 >>> 16),
 129:             (byte)(H4 >>> 8), (byte)H4};
 130:     
 131:     engineReset ();
 132:     return result;
 133:   }
 134: 
 135:   // Process a single block.  This is pretty much copied verbatim from
 136:   // [1] pp. 9, 10.
 137:   private void munch ()
 138:   {
 139:     for (int t = 16; t < 80; ++ t)
 140:       {
 141:     int Wt = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
 142:     W[t] = Wt << 1 | Wt >>> 31;
 143:       }
 144: 
 145:     int A = H0;
 146:     int B = H1;
 147:     int C = H2;
 148:     int D = H3;
 149:     int E = H4;
 150: 
 151:     for (int t = 0; t < 20; ++ t)
 152:       {
 153:     int TEMP = (A << 5 | A >>> 27) // S^5(A)
 154:       + ((B & C) | (~B & D))       // f_t(B,C,D)
 155:       + E + W[t]
 156:       + 0x5a827999;                // K_t
 157: 
 158:     E = D;
 159:     D = C;
 160:     C = B << 30 | B >>> 2;         // S^30(B)
 161:     B = A;
 162:     A = TEMP;
 163:       }
 164: 
 165:     for (int t = 20; t < 40; ++ t)
 166:       {
 167:     int TEMP = (A << 5 | A >>> 27) // S^5(A)
 168:       + (B ^ C ^ D)                // f_t(B,C,D)
 169:       + E + W[t]                   
 170:       + 0x6ed9eba1;                // K_t
 171: 
 172:     E = D;
 173:     D = C;
 174:     C = B << 30 | B >>> 2;         // S^30(B)
 175:     B = A;
 176:     A = TEMP;
 177:       }
 178: 
 179:     for (int t = 40; t < 60; ++ t)
 180:       {
 181:     int TEMP = (A << 5 | A >>> 27) // S^5(A)
 182:       + (B & C | B & D | C & D)    // f_t(B,C,D)
 183:       + E + W[t]
 184:       + 0x8f1bbcdc;                // K_t
 185: 
 186:     E = D;
 187:     D = C;
 188:     C = B << 30 | B >>> 2;         // S^30(B)
 189:     B = A;
 190:     A = TEMP;
 191:       }
 192: 
 193:     for (int t = 60; t < 80; ++ t)
 194:       {
 195:     int TEMP = (A << 5 | A >>> 27) // S^5(A)
 196:       + (B ^ C ^ D)                // f_t(B,C,D)
 197:       + E + W[t]
 198:       + 0xca62c1d6;                // K_t
 199: 
 200:     E = D;
 201:     D = C;
 202:     C = B << 30 | B >>> 2;         // S^30(B)
 203:     B = A;
 204:     A = TEMP;
 205:       }
 206: 
 207:     H0 += A;
 208:     H1 += B;
 209:     H2 += C;
 210:     H3 += D;
 211:     H4 += E;
 212: 
 213:     // Reset W by clearing it.
 214:     for (int t = 0; t < 80; ++ t)
 215:       W[t] = 0;
 216:   }
 217:   
 218:   public Object clone ()
 219:   {
 220:     return new SHA (this);
 221:   }
 222: 
 223:   private SHA (SHA copy)
 224:   {
 225:     this ();
 226:     bytecount = copy.bytecount;
 227:     H0 = copy.H0;
 228:     H1 = copy.H1;
 229:     H2 = copy.H2;
 230:     H3 = copy.H3;
 231:     H4 = copy.H4;
 232:     System.arraycopy (copy.W, 0, W, 0, 80);
 233:   }
 234:   
 235:   private final int W[] = new int[80];
 236:   private long bytecount;
 237:   private int H0;
 238:   private int H1;
 239:   private int H2;
 240:   private int H3;
 241:   private int H4;
 242: }