/* * 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.apacheds; import static org.junit.Assert.assertTrue; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.Provider; import java.security.Security; import java.security.spec.InvalidKeySpecException; import org.apache.directory.api.ldap.model.constants.LdapSecurityConstants; import org.apache.directory.api.ldap.model.password.PasswordUtil; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.wildfly.security.WildFlyElytronProvider; import org.wildfly.security.password.PasswordFactory; import org.wildfly.security.password.interfaces.UnixDESCryptPassword; import org.wildfly.security.password.spec.SaltedHashPasswordSpec; import org.wildfly.security.util.Alphabet.Base64Alphabet; import org.wildfly.security.util.CodePointIterator; /** * A simple test case to verify that we can use an Apache DS generated {crypt} value with our {@link org.wildfly.security.password.interfaces.UnixDESCryptPassword UnixDESCryptPassword} * implementation. Note that Apache DS uses the standard Unix DES Crypt algorithm. * * @author <a href="mailto:darran.lofthouse@jboss.com">Darran Lofthouse</a> */ public class CryptCompatibilityTest { private static final Provider provider = new WildFlyElytronProvider(); @BeforeClass public static void register() { Security.addProvider(provider); } @AfterClass public static void remove() { Security.removeProvider(provider.getName()); } private static final String PASSWORD = "cryptIt"; private static final String LONG_PASSWORD = "cryptPassword"; // more than 8 characters @Test public void testComparison() throws InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException { byte[] forStorage = PasswordUtil.createStoragePassword(PASSWORD.getBytes(StandardCharsets.UTF_8), LdapSecurityConstants.HASH_METHOD_CRYPT); System.out.println(new String(forStorage, StandardCharsets.UTF_8)); byte[] saltBytes = new byte[2]; byte[] digestBase64 = new byte[forStorage.length - 9]; System.arraycopy(forStorage, 7, saltBytes, 0, 2); System.arraycopy(forStorage, 9, digestBase64, 0, digestBase64.length); final short salt = (short) convertSaltRepresentation(saltBytes); byte[] digest = CodePointIterator.ofUtf8Bytes(digestBase64).base64Decode(Base64Alphabet.MOD_CRYPT, false).drain(); SaltedHashPasswordSpec spec = new SaltedHashPasswordSpec(digest, ByteBuffer.allocate(2).putShort(salt).array()); PasswordFactory pf = PasswordFactory.getInstance(UnixDESCryptPassword.ALGORITHM_CRYPT_DES); UnixDESCryptPassword password = (UnixDESCryptPassword) pf.generatePassword(spec); assertTrue(pf.verify(password, (PASSWORD).toCharArray())); System.out.println("Have something split out."); } @Test public void testComparisonWithLongPassword() throws InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException { byte[] forStorage = PasswordUtil.createStoragePassword(LONG_PASSWORD.getBytes(StandardCharsets.UTF_8), LdapSecurityConstants.HASH_METHOD_CRYPT); System.out.println(new String(forStorage, StandardCharsets.UTF_8)); byte[] saltBytes = new byte[2]; byte[] digestBase64 = new byte[forStorage.length - 9]; System.arraycopy(forStorage, 7, saltBytes, 0, 2); System.arraycopy(forStorage, 9, digestBase64, 0, digestBase64.length); final short salt = (short) convertSaltRepresentation(saltBytes); byte[] digest = CodePointIterator.ofUtf8Bytes(digestBase64).base64Decode(Base64Alphabet.MOD_CRYPT, false).drain(); SaltedHashPasswordSpec spec = new SaltedHashPasswordSpec(digest, ByteBuffer.allocate(2).putShort(salt).array()); PasswordFactory pf = PasswordFactory.getInstance(UnixDESCryptPassword.ALGORITHM_CRYPT_DES); UnixDESCryptPassword password = (UnixDESCryptPassword) pf.generatePassword(spec); assertTrue(pf.verify(password, (LONG_PASSWORD).toCharArray())); } private static int convertSaltRepresentation(final byte[] saltBytes) throws InvalidKeySpecException { int salt = 0; for (int i = 1; i >= 0; i--) { salt = ( salt << 6 ) | ( 0x00ff & Base64Alphabet.MOD_CRYPT.decode(saltBytes[i])); } return salt; } }