001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.codec.digest;
018    
019    import static org.junit.Assert.assertEquals;
020    import static org.junit.Assert.assertNotNull;
021    import static org.junit.Assert.assertNotSame;
022    import static org.junit.Assert.assertTrue;
023    
024    import org.apache.commons.codec.Charsets;
025    import org.junit.Test;
026    
027    public class UnixCryptTest {
028    
029        @Test
030        public void testCtor() {
031            assertNotNull(new UnixCrypt());
032        }
033    
034        @Test
035        public void testUnixCryptStrings() {
036            // trivial test
037            assertEquals("xxWAum7tHdIUw", Crypt.crypt("secret", "xx"));
038            // empty data
039            assertEquals("12UFlHxel6uMM", Crypt.crypt("", "12"));
040            // salt gets cut at maximum length
041            assertEquals("12FJgqDtVOg7Q", Crypt.crypt("secret", "12"));
042            assertEquals("12FJgqDtVOg7Q", Crypt.crypt("secret", "12345678"));
043        }
044    
045        @Test
046        public void testUnixCryptBytes() {
047            // An empty Bytearray equals an empty String
048            assertEquals("12UFlHxel6uMM", Crypt.crypt(new byte[0], "12"));
049            // UTF-8 stores \u00e4 "a with diaeresis" as two bytes 0xc3 0xa4.
050            assertEquals("./287bds2PjVw", Crypt.crypt("t\u00e4st", "./"));
051            // ISO-8859-1 stores "a with diaeresis" as single byte 0xe4.
052            assertEquals("./bLIFNqo9XKQ", Crypt.crypt("t\u00e4st".getBytes(Charsets.ISO_8859_1), "./"));
053            assertEquals("./bLIFNqo9XKQ", Crypt.crypt(new byte[]{(byte) 0x74, (byte) 0xe4, (byte) 0x73, (byte) 0x74}, "./"));
054        }
055    
056        /**
057         * Some salts are invalid for crypt(3) but not for unixCrypt().
058         */
059        @Test
060        public void testUnixCryptExplicitCall() {
061            // A call to crypt() with an empty salt would result in a "$6$" hash.
062            // Using unixCrypt() explicitly results in a random salt.
063            assertTrue(UnixCrypt.crypt("secret".getBytes()).matches("^[a-zA-Z0-9./]{13}$"));
064            assertTrue(UnixCrypt.crypt("secret".getBytes(), null).matches("^[a-zA-Z0-9./]{13}$"));
065        }
066    
067        /**
068         * Single character salts are illegal!
069         * E.g. with glibc 2.13, crypt("secret", "x") = "xxZREZpkHZpkI" but
070         * crypt("secret", "xx") = "xxWAum7tHdIUw" which makes it unverifyable.
071         */
072        @Test(expected = IllegalArgumentException.class)
073        public void testUnixCryptWithHalfSalt() {
074            UnixCrypt.crypt("secret", "x");
075        }
076    
077        /**
078         * Unimplemented "$foo$" salt prefixes would be threated as UnixCrypt salt.
079         */
080        @Test(expected = IllegalArgumentException.class)
081        public void testUnicCryptInvalidSalt() {
082            UnixCrypt.crypt("secret", "$a");
083        }
084    
085        @Test(expected = NullPointerException.class)
086        public void testUnixCryptNullData() {
087            UnixCrypt.crypt((byte[]) null);
088        }
089    
090        @Test(expected = IllegalArgumentException.class)
091        public void testUnixCryptWithEmptySalt() {
092            UnixCrypt.crypt("secret", "");
093        }
094    
095        @Test
096        public void testUnixCryptWithoutSalt() {
097            String hash = UnixCrypt.crypt("foo");
098            assertTrue(hash.matches("^[a-zA-Z0-9./]{13}$"));
099            String hash2 = UnixCrypt.crypt("foo");
100            assertNotSame(hash, hash2);
101        }
102    }