View Javadoc
1   package org.bouncycastle.crypto.digests;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * SNMP Java Client
6    * ჻჻჻჻჻჻
7    * Copyright 2023 MetricsHub, 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      private static final int DIGEST_LENGTH = 20;
35  
36      private int H1, H2, H3, H4, H5;
37  
38      private int[] X = new int[80];
39      private int xOff;
40  
41      /**
42       * Standard constructor
43       */
44      public SHA1Digest() {
45          reset();
46      }
47  
48      /**
49       * Copy constructor. This will copy the state of the provided
50       * message digest.
51       */
52      public SHA1Digest(SHA1Digest t) {
53          super(t);
54  
55          H1 = t.H1;
56          H2 = t.H2;
57          H3 = t.H3;
58          H4 = t.H4;
59          H5 = t.H5;
60  
61          System.arraycopy(t.X, 0, X, 0, t.X.length);
62          xOff = t.xOff;
63      }
64  
65      public String getAlgorithmName() {
66          return "SHA-1";
67      }
68  
69      public int getDigestSize() {
70          return DIGEST_LENGTH;
71      }
72  
73      protected void processWord(
74              byte[] in,
75              int inOff) {
76          X[xOff++] = ((in[inOff] & 0xff) << 24) | ((in[inOff + 1] & 0xff) << 16)
77                  | ((in[inOff + 2] & 0xff) << 8) | ((in[inOff + 3] & 0xff));
78  
79          if (xOff == 16) {
80              processBlock();
81          }
82      }
83  
84      private void unpackWord(
85              int word,
86              byte[] out,
87              int outOff) {
88          out[outOff] = (byte) (word >>> 24);
89          out[outOff + 1] = (byte) (word >>> 16);
90          out[outOff + 2] = (byte) (word >>> 8);
91          out[outOff + 3] = (byte) word;
92      }
93  
94      protected void processLength(
95              long bitLength) {
96          if (xOff > 14) {
97              processBlock();
98          }
99  
100         X[14] = (int) (bitLength >>> 32);
101         X[15] = (int) (bitLength & 0xffffffff);
102     }
103 
104     public int doFinal(
105             byte[] out,
106             int outOff) {
107         finish();
108 
109         unpackWord(H1, out, outOff);
110         unpackWord(H2, out, outOff + 4);
111         unpackWord(H3, out, outOff + 8);
112         unpackWord(H4, out, outOff + 12);
113         unpackWord(H5, out, outOff + 16);
114 
115         reset();
116 
117         return DIGEST_LENGTH;
118     }
119 
120     /**
121      * reset the chaining variables
122      */
123     public void reset() {
124         super.reset();
125 
126         H1 = 0x67452301;
127         H2 = 0xefcdab89;
128         H3 = 0x98badcfe;
129         H4 = 0x10325476;
130         H5 = 0xc3d2e1f0;
131 
132         xOff = 0;
133         for (int i = 0; i != X.length; i++) {
134             X[i] = 0;
135         }
136     }
137 
138     //
139     // Additive constants
140     //
141     private static final int Y1 = 0x5a827999;
142     private static final int Y2 = 0x6ed9eba1;
143     private static final int Y3 = 0x8f1bbcdc;
144     private static final int Y4 = 0xca62c1d6;
145 
146     private int f(
147             int u,
148             int v,
149             int w) {
150         return ((u & v) | ((~u) & w));
151     }
152 
153     private int h(
154             int u,
155             int v,
156             int w) {
157         return (u ^ v ^ w);
158     }
159 
160     private int g(
161             int u,
162             int v,
163             int w) {
164         return ((u & v) | (u & w) | (v & w));
165     }
166 
167     private int rotateLeft(
168             int x,
169             int n) {
170         return (x << n) | (x >>> (32 - n));
171     }
172 
173     protected void processBlock() {
174         //
175         // expand 16 word block into 80 word block.
176         //
177         for (int i = 16; i <= 79; i++) {
178             X[i] = rotateLeft((X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]), 1);
179         }
180 
181         //
182         // set up working variables.
183         //
184         int A = H1;
185         int B = H2;
186         int C = H3;
187         int D = H4;
188         int E = H5;
189 
190         //
191         // round 1
192         //
193         for (int j = 0; j <= 19; j++) {
194             int t = rotateLeft(A, 5) + f(B, C, D) + E + X[j] + Y1;
195 
196             E = D;
197             D = C;
198             C = rotateLeft(B, 30);
199             B = A;
200             A = t;
201         }
202 
203         //
204         // round 2
205         //
206         for (int j = 20; j <= 39; j++) {
207             int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y2;
208 
209             E = D;
210             D = C;
211             C = rotateLeft(B, 30);
212             B = A;
213             A = t;
214         }
215 
216         //
217         // round 3
218         //
219         for (int j = 40; j <= 59; j++) {
220             int t = rotateLeft(A, 5) + g(B, C, D) + E + X[j] + Y3;
221 
222             E = D;
223             D = C;
224             C = rotateLeft(B, 30);
225             B = A;
226             A = t;
227         }
228 
229         //
230         // round 4
231         //
232         for (int j = 60; j <= 79; j++) {
233             int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y4;
234 
235             E = D;
236             D = C;
237             C = rotateLeft(B, 30);
238             B = A;
239             A = t;
240         }
241 
242         H1 += A;
243         H2 += B;
244         H3 += C;
245         H4 += D;
246         H5 += E;
247 
248         //
249         // reset the offset and clean out the word buffer.
250         //
251         xOff = 0;
252         for (int i = 0; i != X.length; i++) {
253             X[i] = 0;
254         }
255     }
256 }