View Javadoc
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    *      https://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  package org.apache.commons.codec.digest;
18  
19  import static org.junit.jupiter.api.Assertions.assertArrayEquals;
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertFalse;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertThrows;
24  import static org.junit.jupiter.api.Assumptions.assumeTrue;
25  
26  import java.io.ByteArrayInputStream;
27  import java.io.IOException;
28  import java.nio.file.Files;
29  import java.nio.file.Path;
30  import java.nio.file.StandardOpenOption;
31  import java.security.NoSuchAlgorithmException;
32  import java.util.ArrayList;
33  import java.util.Arrays;
34  import java.util.List;
35  import java.util.stream.Stream;
36  
37  import javax.crypto.Mac;
38  
39  import org.apache.commons.lang3.JavaVersion;
40  import org.apache.commons.lang3.SystemUtils;
41  import org.junit.jupiter.api.AfterEach;
42  import org.junit.jupiter.api.BeforeAll;
43  import org.junit.jupiter.api.BeforeEach;
44  import org.junit.jupiter.api.io.TempDir;
45  import org.junit.jupiter.params.ParameterizedTest;
46  import org.junit.jupiter.params.provider.Arguments;
47  import org.junit.jupiter.params.provider.MethodSource;
48  
49  /**
50   * Tests {@link HmacAlgorithms}.
51   */
52  class HmacAlgorithmsTest {
53  
54      static final String STANDARD_KEY_STRING = "key";
55  
56      static final byte[] STANDARD_KEY_BYTES = STANDARD_KEY_STRING.getBytes();
57  
58      static final byte[] STANDARD_MD5_RESULT_BYTES = { -128, 7, 7, 19, 70, 62, 119, 73, -71, 12, 45, -62, 73, 17, -30, 117 };
59  
60      static final String STANDARD_MD5_RESULT_STRING = "80070713463e7749b90c2dc24911e275";
61  
62      static final String STANDARD_PHRASE_STRING = "The quick brown fox jumps over the lazy dog";
63  
64      static final byte[] STANDARD_PHRASE_BYTES = STANDARD_PHRASE_STRING.getBytes();
65  
66      static final byte[] STANDARD_SHA1_RESULT_BYTES = { -34, 124, -101, -123, -72, -73, -118, -90, -68, -118, 122, 54, -9, 10, -112, 112, 28, -99, -76, -39 };
67  
68      static final String STANDARD_SHA1_RESULT_STRING = "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9";
69  
70      static final byte[] STANDARD_SHA224_RESULT_BYTES = { -120, -1, -117, 84, 103, 93, 57, -72, -9, 35, 34, -26, 95, -7, 69, -59, 45, -106, 55, -103, -120, -83,
71              -94, 86, 57, 116, 126, 105 };
72  
73      static final String STANDARD_SHA224_RESULT_STRING = "88ff8b54675d39b8f72322e65ff945c52d96379988ada25639747e69";
74  
75      static final byte[] STANDARD_SHA256_RESULT_BYTES = { -9, -68, -125, -12, 48, 83, -124, 36, -79, 50, -104, -26, -86, 111, -79, 67, -17, 77, 89, -95, 73, 70,
76              23, 89, -105, 71, -99, -68, 45, 26, 60, -40 };
77  
78      static final String STANDARD_SHA256_RESULT_STRING = "f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8";
79  
80      static final byte[] STANDARD_SHA384_RESULT_BYTES = { -41, -12, 114, 126, 44, 11, 57, -82, 15, 30, 64, -52, -106, -10, 2, 66, -43, -73, -128, 24, 65, -50,
81              -90, -4, 89, 44, 93, 62, 26, -27, 7, 0, 88, 42, -106, -49, 53, -31, -27, 84, -103, 95, -28, -32, 51, -127, -62, 55 };
82  
83      static final String STANDARD_SHA384_RESULT_STRING = "D7F4727E2C0B39AE0F1E40CC96F60242D5B7801841CEA6FC592C5D3E1AE50700582A96CF35E1E554995FE4E03381C237"
84              .toLowerCase();
85  
86      static final byte[] STANDARD_SHA512_RESULT_BYTES = { -76, 42, -16, -112, 87, -70, -63, -30, -44, 23, 8, -28, -118, -112, 46, 9, -75, -1, 127, 18, -85, 66,
87              -118, 79, -24, 102, 83, -57, 61, -46, 72, -5, -126, -7, 72, -91, 73, -9, -73, -111, -91, -76, 25, 21, -18, 77, 30, -61, -109, 83, 87, -28, -30, 49,
88              114, 80, -48, 55, 42, -6, 46, -66, -21, 58 };
89  
90      static final String STANDARD_SHA512_RESULT_STRING = "B42AF09057BAC1E2D41708E48A902E09B5FF7F12AB428A4FE86653C73DD248FB82F948A549F7B791A5B41915EE4D1EC3935357E4E2317250D0372AFA2EBEEB3A"
91              .toLowerCase();
92  
93      private static final byte[] EMPTY_BYTE_ARRAY = {};
94  
95      @TempDir
96      static Path TempDir;
97  
98      static Path TempFile;
99  
100     // TODO HMAC_SHA_224
101     public static Stream<Arguments> data() {
102         List<Arguments> list = Arrays.asList(
103         // @formatter:off
104                 Arguments.of(HmacAlgorithms.HMAC_MD5, STANDARD_MD5_RESULT_BYTES, STANDARD_MD5_RESULT_STRING),
105                 Arguments.of(HmacAlgorithms.HMAC_SHA_1, STANDARD_SHA1_RESULT_BYTES, STANDARD_SHA1_RESULT_STRING),
106                 Arguments.of(HmacAlgorithms.HMAC_SHA_256, STANDARD_SHA256_RESULT_BYTES, STANDARD_SHA256_RESULT_STRING),
107                 Arguments.of(HmacAlgorithms.HMAC_SHA_384, STANDARD_SHA384_RESULT_BYTES, STANDARD_SHA384_RESULT_STRING),
108                 Arguments.of(HmacAlgorithms.HMAC_SHA_512, STANDARD_SHA512_RESULT_BYTES, STANDARD_SHA512_RESULT_STRING));
109         // @formatter:on
110         if (SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8)) {
111             list = new ArrayList<>(list);
112             list.add(Arguments.of(HmacAlgorithms.HMAC_SHA_224, STANDARD_SHA224_RESULT_BYTES, STANDARD_SHA224_RESULT_STRING));
113         }
114         return list.stream();
115     }
116 
117     @BeforeAll
118     public static void init() throws IOException {
119         TempFile = Files.createFile(TempDir.resolve(HmacAlgorithmsTest.class.getSimpleName()));
120         Files.write(TempFile, STANDARD_PHRASE_BYTES, StandardOpenOption.CREATE);
121     }
122 
123     private DigestUtilsTest digestUtilsTest;
124     @BeforeEach
125     public void setUp() throws Exception {
126         digestUtilsTest = new DigestUtilsTest();
127         digestUtilsTest.setUp();
128     }
129 
130     @AfterEach
131     public void tearDown() throws Exception {
132         digestUtilsTest.tearDown();
133         digestUtilsTest = null;
134     }
135 
136     @ParameterizedTest
137     @MethodSource("data")
138     void testAlgorithm(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString)
139             throws NoSuchAlgorithmException {
140         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
141         final String algorithm = hmacAlgorithm.getName();
142         assertNotNull(algorithm);
143         assertFalse(algorithm.isEmpty());
144         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
145         Mac.getInstance(algorithm);
146     }
147 
148     @ParameterizedTest
149     @MethodSource("data")
150     void testGetHmacEmptyKey(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString) {
151         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
152         assertThrows(IllegalArgumentException.class, () -> HmacUtils.getInitializedMac(hmacAlgorithm, EMPTY_BYTE_ARRAY));
153     }
154 
155     @ParameterizedTest
156     @MethodSource("data")
157     void testGetHmacNullKey(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString) {
158         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
159         assertThrows(IllegalArgumentException.class, () -> HmacUtils.getInitializedMac(hmacAlgorithm, null));
160     }
161 
162     @ParameterizedTest
163     @MethodSource("data")
164     void testHmacFailByteArray(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString) {
165         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
166         assertThrows(IllegalArgumentException.class, () -> new HmacUtils(hmacAlgorithm, (byte[]) null).hmac(STANDARD_PHRASE_BYTES));
167     }
168 
169     @ParameterizedTest
170     @MethodSource("data")
171     void testHmacFailInputStream(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString) {
172         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
173         assertThrows(IllegalArgumentException.class, () -> new HmacUtils(hmacAlgorithm, (byte[]) null).hmac(new ByteArrayInputStream(STANDARD_PHRASE_BYTES)));
174     }
175 
176     @ParameterizedTest
177     @MethodSource("data")
178     void testHmacFailString(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString) {
179         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
180         assertThrows(IllegalArgumentException.class, () -> new HmacUtils(hmacAlgorithm, (String) null).hmac(STANDARD_PHRASE_STRING));
181     }
182 
183     @ParameterizedTest
184     @MethodSource("data")
185     void testHmacHexFailByteArray(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString) {
186         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
187         assertThrows(IllegalArgumentException.class, () -> new HmacUtils(hmacAlgorithm, (byte[]) null).hmac(STANDARD_PHRASE_BYTES));
188     }
189 
190     @ParameterizedTest
191     @MethodSource("data")
192     void testHmacHexFailInputStream(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString) {
193         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
194         assertThrows(IllegalArgumentException.class, () -> new HmacUtils(hmacAlgorithm, (byte[]) null).hmac(new ByteArrayInputStream(STANDARD_PHRASE_BYTES)));
195     }
196 
197     @ParameterizedTest
198     @MethodSource("data")
199     void testHmacHexFailString(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString) {
200         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
201         assertThrows(IllegalArgumentException.class, () -> new HmacUtils(hmacAlgorithm, (String) null).hmac(STANDARD_PHRASE_STRING));
202     }
203 
204     @ParameterizedTest
205     @MethodSource("data")
206     void testInitializedMac(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString) {
207         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
208         final Mac mac = HmacUtils.getInitializedMac(hmacAlgorithm, STANDARD_KEY_BYTES);
209         final Mac mac2 = HmacUtils.getInitializedMac(hmacAlgorithm.getName(), STANDARD_KEY_BYTES);
210         assertArrayEquals(standardResultBytes, HmacUtils.updateHmac(mac, STANDARD_PHRASE_STRING).doFinal());
211         assertArrayEquals(standardResultBytes, HmacUtils.updateHmac(mac2, STANDARD_PHRASE_STRING).doFinal());
212     }
213 
214     @ParameterizedTest
215     @MethodSource("data")
216     void testMacByteArray(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString) {
217         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
218         assertArrayEquals(standardResultBytes, new HmacUtils(hmacAlgorithm, STANDARD_KEY_BYTES).hmac(STANDARD_PHRASE_BYTES));
219     }
220 
221     @ParameterizedTest
222     @MethodSource("data")
223     void testMacHexByteArray(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString) {
224         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
225         assertEquals(standardResultString, new HmacUtils(hmacAlgorithm, STANDARD_KEY_BYTES).hmacHex(STANDARD_PHRASE_BYTES));
226     }
227 
228     @ParameterizedTest
229     @MethodSource("data")
230     void testMacHexFile(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString)
231             throws IOException {
232         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
233         assertEquals(standardResultString, new HmacUtils(hmacAlgorithm, STANDARD_KEY_BYTES).hmacHex(TempFile.toFile()));
234     }
235 
236     @ParameterizedTest
237     @MethodSource("data")
238     void testMacHexInputStream(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString)
239             throws IOException {
240         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
241         assertEquals(standardResultString, new HmacUtils(hmacAlgorithm, STANDARD_KEY_BYTES).hmacHex(new ByteArrayInputStream(STANDARD_PHRASE_BYTES)));
242     }
243 
244     @ParameterizedTest
245     @MethodSource("data")
246     void testMacHexPath(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString)
247             throws IOException {
248         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
249         assertEquals(standardResultString, new HmacUtils(hmacAlgorithm, STANDARD_KEY_BYTES).hmacHex(TempFile));
250     }
251 
252     @ParameterizedTest
253     @MethodSource("data")
254     void testMacHexString(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString) {
255         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
256         assertEquals(standardResultString, new HmacUtils(hmacAlgorithm, STANDARD_KEY_BYTES).hmacHex(STANDARD_PHRASE_STRING));
257     }
258 
259     @ParameterizedTest
260     @MethodSource("data")
261     void testMacInputStream(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString) throws IOException {
262         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
263         assertArrayEquals(standardResultBytes, new HmacUtils(hmacAlgorithm, STANDARD_KEY_BYTES).hmac(new ByteArrayInputStream(STANDARD_PHRASE_BYTES)));
264     }
265 
266     @ParameterizedTest
267     @MethodSource("data")
268     void testMacString(final HmacAlgorithms hmacAlgorithm, final byte[] standardResultBytes, final String standardResultString) {
269         assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
270         assertArrayEquals(standardResultBytes, new HmacUtils(hmacAlgorithm, STANDARD_KEY_BYTES).hmac(STANDARD_PHRASE_STRING));
271     }
272 
273 }