View Javadoc
1   package org.bouncycastle.crypto.digests;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * SNMP Java Client
6    * ჻჻჻჻჻჻
7    * Copyright 2023 Sentry Software, Westhawk
8    * ჻჻჻჻჻჻
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
23   */
24  
25  
26  /**
27   * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349.
28   *
29   * It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5
30   * is the "endienness" of the word processing!
31   */
32  public class SHA1Digest
33      extends GeneralDigest
34  {
35      private static final int    DIGEST_LENGTH = 20;
36  
37      private int     H1, H2, H3, H4, H5;
38  
39      private int[]   X = new int[80];
40      private int     xOff;
41  
42      /**
43       * Standard constructor
44       */
45      public SHA1Digest()
46      {
47          reset();
48      }
49  
50      /**
51       * Copy constructor.  This will copy the state of the provided
52       * message digest.
53       */
54      public SHA1Digest(SHA1Digest t)
55      {
56          super(t);
57  
58          H1 = t.H1;
59          H2 = t.H2;
60          H3 = t.H3;
61          H4 = t.H4;
62          H5 = t.H5;
63  
64          System.arraycopy(t.X, 0, X, 0, t.X.length);
65          xOff = t.xOff;
66      }
67  
68      public String getAlgorithmName()
69      {
70          return "SHA-1";
71      }
72  
73      public int getDigestSize()
74      {
75          return DIGEST_LENGTH;
76      }
77  
78      protected void processWord(
79          byte[]  in,
80          int     inOff)
81      {
82          X[xOff++] = ((in[inOff] & 0xff) << 24) | ((in[inOff + 1] & 0xff) << 16)
83                      | ((in[inOff + 2] & 0xff) << 8) | ((in[inOff + 3] & 0xff)); 
84  
85          if (xOff == 16)
86          {
87              processBlock();
88          }
89      }
90  
91      private void unpackWord(
92          int     word,
93          byte[]  out,
94          int     outOff)
95      {
96          out[outOff]     = (byte)(word >>> 24);
97          out[outOff + 1] = (byte)(word >>> 16);
98          out[outOff + 2] = (byte)(word >>> 8);
99          out[outOff + 3] = (byte)word;
100     }
101 
102     protected void processLength(
103         long    bitLength)
104     {
105         if (xOff > 14)
106         {
107             processBlock();
108         }
109 
110         X[14] = (int)(bitLength >>> 32);
111         X[15] = (int)(bitLength & 0xffffffff);
112     }
113 
114     public int doFinal(
115         byte[]  out,
116         int     outOff)
117     {
118         finish();
119 
120         unpackWord(H1, out, outOff);
121         unpackWord(H2, out, outOff + 4);
122         unpackWord(H3, out, outOff + 8);
123         unpackWord(H4, out, outOff + 12);
124         unpackWord(H5, out, outOff + 16);
125 
126         reset();
127 
128         return DIGEST_LENGTH;
129     }
130 
131     /**
132      * reset the chaining variables
133      */
134     public void reset()
135     {
136         super.reset();
137 
138         H1 = 0x67452301;
139         H2 = 0xefcdab89;
140         H3 = 0x98badcfe;
141         H4 = 0x10325476;
142         H5 = 0xc3d2e1f0;
143 
144         xOff = 0;
145         for (int i = 0; i != X.length; i++)
146         {
147             X[i] = 0;
148         }
149     }
150 
151     //
152     // Additive constants
153     //
154     private static final int    Y1 = 0x5a827999;
155     private static final int    Y2 = 0x6ed9eba1;
156     private static final int    Y3 = 0x8f1bbcdc;
157     private static final int    Y4 = 0xca62c1d6;
158 
159     private int f(
160         int    u,
161         int    v,
162         int    w)
163     {
164         return ((u & v) | ((~u) & w));
165     }
166 
167     private int h(
168         int    u,
169         int    v,
170         int    w)
171     {
172         return (u ^ v ^ w);
173     }
174 
175     private int g(
176         int    u,
177         int    v,
178         int    w)
179     {
180         return ((u & v) | (u & w) | (v & w));
181     }
182 
183     private int rotateLeft(
184         int    x,
185         int    n)
186     {
187         return (x << n) | (x >>> (32 - n));
188     }
189 
190     protected void processBlock()
191     {
192         //
193         // expand 16 word block into 80 word block.
194         //
195         for (int i = 16; i <= 79; i++)
196         {
197             X[i] = rotateLeft((X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]), 1);
198         }
199 
200         //
201         // set up working variables.
202         //
203         int     A = H1;
204         int     B = H2;
205         int     C = H3;
206         int     D = H4;
207         int     E = H5;
208 
209         //
210         // round 1
211         //
212         for (int j = 0; j <= 19; j++)
213         {
214             int     t = rotateLeft(A, 5) + f(B, C, D) + E + X[j] + Y1;
215 
216             E = D;
217             D = C;
218             C = rotateLeft(B, 30);
219             B = A;
220             A = t;
221         }
222 
223         //
224         // round 2
225         //
226         for (int j = 20; j <= 39; j++)
227         {
228             int     t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y2;
229 
230             E = D;
231             D = C;
232             C = rotateLeft(B, 30);
233             B = A;
234             A = t;
235         }
236 
237         //
238         // round 3
239         //
240         for (int j = 40; j <= 59; j++)
241         {
242             int     t = rotateLeft(A, 5) + g(B, C, D) + E + X[j] + Y3;
243 
244             E = D;
245             D = C;
246             C = rotateLeft(B, 30);
247             B = A;
248             A = t;
249         }
250 
251         //
252         // round 4
253         //
254         for (int j = 60; j <= 79; j++)
255         {
256             int     t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y4;
257 
258             E = D;
259             D = C;
260             C = rotateLeft(B, 30);
261             B = A;
262             A = t;
263         }
264 
265         H1 += A;
266         H2 += B;
267         H3 += C;
268         H4 += D;
269         H5 += E;
270 
271         //
272         // reset the offset and clean out the word buffer.
273         //
274         xOff = 0;
275         for (int i = 0; i != X.length; i++)
276         {
277             X[i] = 0;
278         }
279     }
280 }