1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.codec.digest;
18
19 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.assertNotSame;
21 import static org.junit.jupiter.api.Assertions.assertThrows;
22 import static org.junit.jupiter.api.Assertions.assertTrue;
23
24 import java.nio.charset.StandardCharsets;
25 import java.util.concurrent.ThreadLocalRandom;
26
27 import org.junit.jupiter.api.Test;
28
29 public class Apr1CryptTest {
30
31 @Test
32 public void testApr1CryptBytes() {
33
34 final byte[] keyBytes = { '!', 'b', 'c', '.' };
35 final String hash = Md5Crypt.apr1Crypt(keyBytes);
36 assertEquals(hash, Md5Crypt.apr1Crypt("!bc.", hash));
37
38
39 assertEquals("$apr1$foo$P27KyD1htb4EllIPEYhqi0", Md5Crypt.apr1Crypt(new byte[0], "$apr1$foo"));
40
41 assertEquals("$apr1$./$EeFrYzWWbmTyGdf4xULYc.", Md5Crypt.apr1Crypt("t\u00e4st", "$apr1$./$"));
42
43 assertEquals("$apr1$./$kCwT1pY9qXAJElYG9q1QE1", Md5Crypt.apr1Crypt("t\u00e4st".getBytes(StandardCharsets.ISO_8859_1), "$apr1$./$"));
44 }
45
46 @Test
47 public void testApr1CryptBytesWithThreadLocalRandom() {
48
49 final byte[] keyBytes = { '!', 'b', 'c', '.' };
50 final ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
51 final String hash = Md5Crypt.apr1Crypt(keyBytes, threadLocalRandom);
52 assertEquals(hash, Md5Crypt.apr1Crypt("!bc.", hash));
53
54
55 assertEquals("$apr1$foo$P27KyD1htb4EllIPEYhqi0", Md5Crypt.apr1Crypt(new byte[0], "$apr1$foo"));
56
57 assertEquals("$apr1$./$EeFrYzWWbmTyGdf4xULYc.", Md5Crypt.apr1Crypt("t\u00e4st", "$apr1$./$"));
58
59 assertEquals("$apr1$./$kCwT1pY9qXAJElYG9q1QE1", Md5Crypt.apr1Crypt("t\u00e4st".getBytes(StandardCharsets.ISO_8859_1), "$apr1$./$"));
60 }
61
62 @Test
63 public void testApr1CryptExplicitCall() {
64
65 assertEquals("$apr1$1234$mAlH7FRST6FiRZ.kcYL.j1", Md5Crypt.apr1Crypt("secret", "1234"));
66
67 assertTrue(Md5Crypt.apr1Crypt("secret".getBytes()).matches("^\\$apr1\\$[a-zA-Z0-9./]{0,8}\\$.{1,}$"));
68 assertTrue(Md5Crypt.apr1Crypt("secret".getBytes(), (String) null).matches("^\\$apr1\\$[a-zA-Z0-9./]{0,8}\\$.{1,}$"));
69 }
70
71 @Test
72 public void testApr1CryptNullData() {
73 assertThrows(NullPointerException.class, () -> Md5Crypt.apr1Crypt((byte[]) null));
74 }
75
76 @Test
77 public void testApr1CryptStrings() {
78
79 assertEquals("$apr1$TqI9WECO$LHZB2DqRlk9nObiB6vJG9.", Md5Crypt.apr1Crypt("secret", "$apr1$TqI9WECO"));
80
81 assertEquals("$apr1$foo$P27KyD1htb4EllIPEYhqi0", Md5Crypt.apr1Crypt("", "$apr1$foo"));
82
83 assertEquals("$apr1$1234$mAlH7FRST6FiRZ.kcYL.j1", Md5Crypt.apr1Crypt("secret", "$apr1$1234"));
84 assertEquals("$apr1$1234$mAlH7FRST6FiRZ.kcYL.j1", Md5Crypt.apr1Crypt("secret", "$apr1$1234$567"));
85 assertEquals("$apr1$1234$mAlH7FRST6FiRZ.kcYL.j1", Md5Crypt.apr1Crypt("secret", "$apr1$1234$567$890"));
86
87 assertEquals("$apr1$12345678$0lqb/6VUFP8JY/s/jTrIk0", Md5Crypt.apr1Crypt("secret", "$apr1$1234567890123456"));
88 assertEquals("$apr1$12345678$0lqb/6VUFP8JY/s/jTrIk0", Md5Crypt.apr1Crypt("secret", "$apr1$123456789012345678"));
89 }
90
91 @Test
92 public void testApr1CryptWithEmptySalt() {
93 assertThrows(IllegalArgumentException.class, () -> Md5Crypt.apr1Crypt("secret".getBytes(), ""));
94 }
95
96 @Test
97 public void testApr1CryptWithInvalidSalt() {
98 assertThrows(IllegalArgumentException.class, () -> Md5Crypt.apr1Crypt(new byte[0], "!"));
99 }
100
101 @Test
102 public void testApr1CryptWithoutSalt() {
103
104 final String hash = Md5Crypt.apr1Crypt("secret");
105 assertTrue(hash.matches("^\\$apr1\\$[a-zA-Z0-9\\./]{8}\\$[a-zA-Z0-9\\./]{22}$"));
106 final String hash2 = Md5Crypt.apr1Crypt("secret");
107 assertNotSame(hash, hash2);
108 }
109
110 @Test
111 public void testApr1LongSalt() {
112 assertEquals("$apr1$12345678$0lqb/6VUFP8JY/s/jTrIk0", Md5Crypt.apr1Crypt("secret", "12345678901234567890"));
113 }
114 }