Source for gnu.java.security.hash.Sha160

   1: /* Sha160.java --
   2:    Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
   3: 
   4: This file is a 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 of the License, or (at
   9: your option) 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; if not, write to the Free Software
  18: Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
  19: 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.hash;
  40: 
  41: import gnu.java.security.Registry;
  42: import gnu.java.security.util.Util;
  43: 
  44: /**
  45:  * The Secure Hash Algorithm (SHA-1) is required for use with the Digital
  46:  * Signature Algorithm (DSA) as specified in the Digital Signature Standard
  47:  * (DSS) and whenever a secure hash algorithm is required for federal
  48:  * applications. For a message of length less than 2^64 bits, the SHA-1
  49:  * produces a 160-bit condensed representation of the message called a message
  50:  * digest. The message digest is used during generation of a signature for the
  51:  * message. The SHA-1 is also used to compute a message digest for the received
  52:  * version of the message during the process of verifying the signature. Any
  53:  * change to the message in transit will, with very high probability, result in
  54:  * a different message digest, and the signature will fail to verify.
  55:  * <p>
  56:  * The SHA-1 is designed to have the following properties: it is
  57:  * computationally infeasible to find a message which corresponds to a given
  58:  * message digest, or to find two different messages which produce the same
  59:  * message digest.
  60:  * <p>
  61:  * References:
  62:  * <ol>
  63:  *    <li><a href="http://www.itl.nist.gov/fipspubs/fip180-1.htm">SECURE HASH
  64:  *    STANDARD</a><br>
  65:  *    Federal Information, Processing Standards Publication 180-1, 1995 April 17.
  66:  *    </li>
  67:  * </ol>
  68:  */
  69: public class Sha160
  70:     extends BaseHash
  71: {
  72:   private static final int BLOCK_SIZE = 64; // inner block size in bytes
  73: 
  74:   private static final String DIGEST0 = "A9993E364706816ABA3E25717850C26C9CD0D89D";
  75: 
  76:   private static final int[] w = new int[80];
  77: 
  78:   /** caches the result of the correctness test, once executed. */
  79:   private static Boolean valid;
  80: 
  81:   /** 160-bit interim result. */
  82:   private int h0, h1, h2, h3, h4;
  83: 
  84:   /** Trivial 0-arguments constructor. */
  85:   public Sha160()
  86:   {
  87:     super(Registry.SHA160_HASH, 20, BLOCK_SIZE);
  88:   }
  89: 
  90:   /**
  91:    * Private constructor for cloning purposes.
  92:    *
  93:    * @param md the instance to clone.
  94:    */
  95:   private Sha160(Sha160 md)
  96:   {
  97:     this();
  98: 
  99:     this.h0 = md.h0;
 100:     this.h1 = md.h1;
 101:     this.h2 = md.h2;
 102:     this.h3 = md.h3;
 103:     this.h4 = md.h4;
 104:     this.count = md.count;
 105:     this.buffer = (byte[]) md.buffer.clone();
 106:   }
 107: 
 108:   public static final int[] G(int hh0, int hh1, int hh2, int hh3, int hh4,
 109:                               byte[] in, int offset)
 110:   {
 111:     return sha(hh0, hh1, hh2, hh3, hh4, in, offset);
 112:   }
 113: 
 114:   public Object clone()
 115:   {
 116:     return new Sha160(this);
 117:   }
 118: 
 119:   protected void transform(byte[] in, int offset)
 120:   {
 121:     int[] result = sha(h0, h1, h2, h3, h4, in, offset);
 122:     h0 = result[0];
 123:     h1 = result[1];
 124:     h2 = result[2];
 125:     h3 = result[3];
 126:     h4 = result[4];
 127:   }
 128: 
 129:   protected byte[] padBuffer()
 130:   {
 131:     int n = (int)(count % BLOCK_SIZE);
 132:     int padding = (n < 56) ? (56 - n) : (120 - n);
 133:     byte[] result = new byte[padding + 8];
 134:     // padding is always binary 1 followed by binary 0s
 135:     result[0] = (byte) 0x80;
 136:     // save number of bits, casting the long to an array of 8 bytes
 137:     long bits = count << 3;
 138:     result[padding++] = (byte)(bits >>> 56);
 139:     result[padding++] = (byte)(bits >>> 48);
 140:     result[padding++] = (byte)(bits >>> 40);
 141:     result[padding++] = (byte)(bits >>> 32);
 142:     result[padding++] = (byte)(bits >>> 24);
 143:     result[padding++] = (byte)(bits >>> 16);
 144:     result[padding++] = (byte)(bits >>> 8);
 145:     result[padding  ] = (byte) bits;
 146:     return result;
 147:   }
 148: 
 149:   protected byte[] getResult()
 150:   {
 151:     return new byte[] {
 152:         (byte)(h0 >>> 24), (byte)(h0 >>> 16), (byte)(h0 >>> 8), (byte) h0,
 153:         (byte)(h1 >>> 24), (byte)(h1 >>> 16), (byte)(h1 >>> 8), (byte) h1,
 154:         (byte)(h2 >>> 24), (byte)(h2 >>> 16), (byte)(h2 >>> 8), (byte) h2,
 155:         (byte)(h3 >>> 24), (byte)(h3 >>> 16), (byte)(h3 >>> 8), (byte) h3,
 156:         (byte)(h4 >>> 24), (byte)(h4 >>> 16), (byte)(h4 >>> 8), (byte) h4 };
 157:   }
 158: 
 159:   protected void resetContext()
 160:   {
 161:     // magic SHA-1/RIPEMD160 initialisation constants
 162:     h0 = 0x67452301;
 163:     h1 = 0xEFCDAB89;
 164:     h2 = 0x98BADCFE;
 165:     h3 = 0x10325476;
 166:     h4 = 0xC3D2E1F0;
 167:   }
 168: 
 169:   public boolean selfTest()
 170:   {
 171:     if (valid == null)
 172:       {
 173:         Sha160 md = new Sha160();
 174:         md.update((byte) 0x61); // a
 175:         md.update((byte) 0x62); // b
 176:         md.update((byte) 0x63); // c
 177:         String result = Util.toString(md.digest());
 178:         valid = Boolean.valueOf(DIGEST0.equals(result));
 179:       }
 180:     return valid.booleanValue();
 181:   }
 182: 
 183:   private static synchronized final int[] sha(int hh0, int hh1, int hh2,
 184:                                               int hh3, int hh4, byte[] in,
 185:                                               int offset)
 186:   {
 187:     int A = hh0;
 188:     int B = hh1;
 189:     int C = hh2;
 190:     int D = hh3;
 191:     int E = hh4;
 192:     int r, T;
 193:     for (r = 0; r < 16; r++)
 194:       w[r] =  in[offset++]         << 24
 195:            | (in[offset++] & 0xFF) << 16
 196:            | (in[offset++] & 0xFF) << 8
 197:            | (in[offset++] & 0xFF);
 198:     for (r = 16; r < 80; r++)
 199:       {
 200:         T = w[r - 3] ^ w[r - 8] ^ w[r - 14] ^ w[r - 16];
 201:         w[r] = T << 1 | T >>> 31;
 202:       }
 203:     for (r = 0; r < 20; r++) // rounds 0-19
 204:       {
 205:         T = (A << 5 | A >>> 27) + ((B & C) | (~B & D)) + E + w[r] + 0x5A827999;
 206:         E = D;
 207:         D = C;
 208:         C = B << 30 | B >>> 2;
 209:         B = A;
 210:         A = T;
 211:       }
 212:     for (r = 20; r < 40; r++) // rounds 20-39
 213:       {
 214:         T = (A << 5 | A >>> 27) + (B ^ C ^ D) + E + w[r] + 0x6ED9EBA1;
 215:         E = D;
 216:         D = C;
 217:         C = B << 30 | B >>> 2;
 218:         B = A;
 219:         A = T;
 220:       }
 221:     for (r = 40; r < 60; r++) // rounds 40-59
 222:       {
 223:         T = (A << 5 | A >>> 27) + (B & C | B & D | C & D) + E + w[r] + 0x8F1BBCDC;
 224:         E = D;
 225:         D = C;
 226:         C = B << 30 | B >>> 2;
 227:         B = A;
 228:         A = T;
 229:       }
 230:     for (r = 60; r < 80; r++) // rounds 60-79
 231:       {
 232:         T = (A << 5 | A >>> 27) + (B ^ C ^ D) + E + w[r] + 0xCA62C1D6;
 233:         E = D;
 234:         D = C;
 235:         C = B << 30 | B >>> 2;
 236:         B = A;
 237:         A = T;
 238:       }
 239:     return new int[] { hh0 + A, hh1 + B, hh2 + C, hh3 + D, hh4 + E };
 240:   }
 241: }