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.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertNotNull;
21  import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
22  import static org.junit.jupiter.api.Assertions.assertTrue;
23  
24  import org.junit.jupiter.api.Test;
25  
26  public class CryptTest {
27  
28      // Allow CLI testing
29      // CLASSPATH=target/classes:target/test-classes/ java org.apache.commons.codec.digest.CryptTest
30      public static void main(final String[] args) {
31          final String hash;
32          switch (args.length) {
33              case 1:
34                  hash = Crypt.crypt(args[0]);
35                  System.out.println(hash.length() + ": " + hash);
36                  break;
37              case 2:
38                  hash = Crypt.crypt(args[0], args[1]);
39                  System.out.println(hash.length() + "; " + hash);
40                  break;
41              default:
42                  System.out.println("Enter key [salt (remember to quote this!)]");
43                  break;
44          }
45      }
46  
47      // Helper method
48      private void startsWith(final String string, final String prefix) {
49          assertTrue(string.startsWith(prefix), string + " should start with " + prefix);
50      }
51  
52      @Test
53      public void testBadSalt() {
54          // No salt
55          assertThrowsExactly(IllegalArgumentException.class, () -> Crypt.crypt("secret", "$1$"));
56          assertThrowsExactly(IllegalArgumentException.class, () -> Crypt.crypt("secret", "$5$"));
57          assertThrowsExactly(IllegalArgumentException.class, () -> Crypt.crypt("secret", "$6$"));
58          // wrong char
59          assertThrowsExactly(IllegalArgumentException.class, () -> Crypt.crypt("secret", "$1$%"));
60          assertThrowsExactly(IllegalArgumentException.class, () -> Crypt.crypt("secret", "$5$!"));
61          assertThrowsExactly(IllegalArgumentException.class, () -> Crypt.crypt("secret", "$6$_"));
62      }
63  
64      @Test
65      public void testBadType() {
66          assertThrowsExactly(IllegalArgumentException.class, () -> Crypt.crypt("secret", "$2$xxxx"));
67          assertThrowsExactly(IllegalArgumentException.class, () -> Crypt.crypt("secret", "$3$xxxx"));
68          assertThrowsExactly(IllegalArgumentException.class, () -> Crypt.crypt("secret", "$4$"));
69      }
70  
71      @Test
72      public void testCrypt() {
73          assertNotNull(new Crypt()); // just for Test Coverage
74      }
75      @Test
76      public void testCryptWithBytes() {
77          final byte[] keyBytes = { 'b', 'y', 't', 'e' };
78          final String hash = Crypt.crypt(keyBytes);
79          assertEquals(hash, Crypt.crypt("byte", hash));
80      }
81  
82      /**
83       * An empty string as salt is invalid.
84       *
85       * The C and Perl implementations return an empty string, PHP threads it
86       * as NULL. Our implementation should throw an Exception as any resulting
87       * hash would not be verifiable with other implementations of crypt().
88       */
89      @Test
90      public void testCryptWithEmptySalt() {
91          assertThrowsExactly(IllegalArgumentException.class, () -> Crypt.crypt("secret", ""));
92      }
93      @Test
94      public void testDefaultCryptVariant() {
95          // If salt is null or completely omitted, a random "$6$" is used.
96          assertTrue(Crypt.crypt("secret").startsWith("$6$"));
97          assertTrue(Crypt.crypt("secret", null).startsWith("$6$"));
98      }
99      @Test
100     public void testSamples() { // From Javadoc
101         assertEquals("$1$xxxx$aMkevjfEIpa35Bh3G4bAc.", Crypt.crypt("secret", "$1$xxxx"));
102         assertEquals("xxWAum7tHdIUw", Crypt.crypt("secret", "xx"));
103     }
104     @Test
105     public void testStored() { // From Javadoc
106         assertEquals("$1$xxxx$aMkevjfEIpa35Bh3G4bAc.", Crypt.crypt("secret", "$1$xxxx$aMkevjfEIpa35Bh3G4bAc."));
107         assertEquals("xxWAum7tHdIUw", Crypt.crypt("secret", "xxWAum7tHdIUw"));
108     }
109 
110     @Test
111     public void testType() {
112         startsWith(Crypt.crypt("secret", "xxxx"), "xx");
113         startsWith(Crypt.crypt("secret", "$1$xxxx"), "$1$xxxx$");
114         startsWith(Crypt.crypt("secret", "$5$xxxx"), "$5$xxxx$");
115         startsWith(Crypt.crypt("secret", "$6$xxxx"), "$6$xxxx$");
116     }
117 }