-
Notifications
You must be signed in to change notification settings - Fork 263
/
SunUnixMD5CryptTest.java
142 lines (117 loc) · 6.43 KB
/
SunUnixMD5CryptTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
* JBoss, Home of Professional Open Source
* Copyright 2014 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.wildfly.security.password.impl;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.security.InvalidKeyException;
import java.security.spec.InvalidKeySpecException;
import org.junit.Test;
import org.wildfly.security.password.interfaces.SunUnixMD5CryptPassword;
import org.wildfly.security.password.spec.EncryptablePasswordSpec;
import org.wildfly.security.password.spec.IteratedSaltedPasswordAlgorithmSpec;
import org.wildfly.security.password.util.ModularCrypt;
/**
* Tests for the Sun variant of Unix MD5 Crypt. The expected results for
* these test cases were generated using the {@code crypt} function from
* the Python {@code crypt} module on a Sun Solaris 10 machine.
*
* @author <a href="mailto:fjuma@redhat.com">Farah Juma</a>
*/
public class SunUnixMD5CryptTest {
@Test
public void testParseCryptStringWithoutRounds() throws InvalidKeySpecException {
testParseCryptString("$md5$zrdhpMlZ$$wBvMOEqbSjU.hu5T2VEP01", 0);
}
@Test
public void testParseCryptStringWithRounds() throws InvalidKeySpecException {
testParseCryptString("$md5,rounds=1000$saltstring$$1wGsmnKgDGdu03LxKu0VI1", 1_000);
}
@Test
public void testParseCryptStringWithBareSalt() throws InvalidKeySpecException {
testParseCryptString("$md5,rounds=1500$saltstring$F9DNxgHVXWaeLS9zUaWXd.", 1_500);
}
private static void testParseCryptString(String cryptString, int iterCount) throws InvalidKeySpecException {
SunUnixMD5CryptPassword password = (SunUnixMD5CryptPassword) ModularCrypt.decode(cryptString);
assertEquals(iterCount, password.getIterationCount());
// Use the spec to build a new crypt string and compare it to the original
assertEquals(cryptString, ModularCrypt.encodeAsString(password));
}
private static void generateAndVerify(String cryptString, String correctPassword) throws InvalidKeyException, InvalidKeySpecException {
final PasswordFactorySpiImpl spi = new PasswordFactorySpiImpl();
SunUnixMD5CryptPassword password = (SunUnixMD5CryptPassword) ModularCrypt.decode(cryptString);
final String algorithm = password.getAlgorithm();
// password is in raw form, need to translate first before verifying
password = (SunUnixMD5CryptPassword) spi.engineTranslatePassword(algorithm, password);
// Use the spec to generate a SunUnixMD5CryptPasswordImpl and then verify the hash using the correct password
assertTrue(spi.engineVerify(algorithm, password, correctPassword.toCharArray()));
assertFalse(spi.engineVerify(algorithm, password, "wrongpassword".toCharArray()));
// Create a new password using EncryptablePasswordSpec and check if the hash matches the hash from the spec
SunUnixMD5CryptPasswordImpl password2 = (SunUnixMD5CryptPasswordImpl) spi.engineGeneratePassword(algorithm,
new EncryptablePasswordSpec(correctPassword.toCharArray(), new IteratedSaltedPasswordAlgorithmSpec(password.getIterationCount(), password.getSalt())));
assertArrayEquals(password.getHash(), password2.getHash());
// Use the new password to obtain a spec and then check if this spec yields the same crypt string
assertEquals(cryptString, ModularCrypt.encodeAsString(password2));
}
@Test
public void testHashEmptyPassword() throws InvalidKeyException, InvalidKeySpecException {
String password = "";
String cryptString = "$md5,rounds=10000$saltstring$$uwcsteApj7mCi4AIwYIT5.";
generateAndVerify(cryptString, password);
}
@Test
public void testHashEmptyPasswordWithBareSalt() throws InvalidKeyException, InvalidKeySpecException {
String password = "";
String cryptString = "$md5,rounds=10000$saltstring$gWOS3RRZtQ5TiYRg.vBx40";
generateAndVerify(cryptString, password);
}
@Test
public void testHashShortPassword() throws InvalidKeyException, InvalidKeySpecException {
String password = "Hello world!";
String cryptString = "$md5$saltstringsalt$$MsEJKkfiaflU4ioBHkqWe0";
generateAndVerify(cryptString, password);
}
@Test
public void testHashShortPasswordWithBareSalt() throws InvalidKeyException, InvalidKeySpecException {
String password = "Hello world!";
String cryptString = "$md5$saltstringsalt$uOXM5LLS7ZtN3eYYS54sM/";
generateAndVerify(cryptString, password);
}
@Test
public void testHashLongPassword() throws InvalidKeyException, InvalidKeySpecException {
String password = "This is a very very very long password! This is the 2nd sentence in THE password. This is a test.@$%";
String cryptString = "$md5,rounds=10000$saltstringsaltstring$$Occfaf7BttKIkRRUARiWU0";
generateAndVerify(cryptString, password);
}
@Test
public void testHashLongPasswordWithBareSalt() throws InvalidKeyException, InvalidKeySpecException {
String password = "This is a very very very long password! This is the 2nd sentence in THE password. This is a test.@$%";
String cryptString = "$md5,rounds=10000$saltstringsaltstring$0xbVBdJfPIual8oRvkU/f.";
generateAndVerify(cryptString, password);
}
@Test
public void testKnownCryptStrings() throws InvalidKeyException, InvalidKeySpecException {
// Crypt string with bare salt
generateAndVerify("$md5$RPgLF6IJ$WTvAlUJ7MqH5xak2FMEwS/", "passwd");
// Crypt strings with "$$" after the salt
generateAndVerify("$md5$zrdhpMlZ$$wBvMOEqbSjU.hu5T2VEP01", "Gpcs3_adm");
generateAndVerify("$md5$vyy8.OVF$$FY4TWzuauRl4.VQNobqMY.", "aa12345678");
generateAndVerify("$md5$3UqYqndY$$6P.aaWOoucxxq.l00SS9k0", "this");
}
}