content: // Licensed to the Apache Software Foundation (ASF) under one
  // or more contributor license agreements.  See the NOTICE file
  // distributed with this work for additional information
  // regarding copyright ownership.  The ASF licenses this file
  // to you 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.apache.cloudstack.auth.test;
  
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.fail;
  import static org.mockito.Mockito.when;
  
  import java.io.UnsupportedEncodingException;
  import java.security.NoSuchAlgorithmException;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.Map;
  
  import javax.naming.ConfigurationException;
  
  import org.apache.cloudstack.auth.SHA256SaltedUserAuthenticator;
  import org.bouncycastle.util.encoders.Base64;
  import org.junit.Before;
  import org.junit.Test;
  import org.junit.runner.RunWith;
  import org.mockito.InjectMocks;
  import org.mockito.Mock;
  import org.mockito.junit.MockitoJUnitRunner;
  
  import com.cloud.user.UserAccount;
  import com.cloud.user.dao.UserAccountDao;
  
  @RunWith(MockitoJUnitRunner.class)
  public class AuthenticatorTest {
  
      @Mock
      UserAccount adminAccount;
  
      @Mock
      UserAccount adminAccount20Byte;
  
      @Mock
      UserAccountDao _userAccountDao;
  
      @InjectMocks
      SHA256SaltedUserAuthenticator authenticator;
  
      @Before
      public void setUp() throws Exception {
          try {
              authenticator.configure("SHA256", Collections.<String, Object> emptyMap());
          } catch (ConfigurationException e) {
              fail(e.toString());
          }
  
          when(_userAccountDao.getUserAccount("admin", 0L)).thenReturn(adminAccount);
          when(_userAccountDao.getUserAccount("admin20Byte", 0L)).thenReturn(adminAccount20Byte);
          when(_userAccountDao.getUserAccount("fake", 0L)).thenReturn(null);
          //32 byte salt, and password="password"
          when(adminAccount.getPassword()).thenReturn("WS3UHhBPKHZeV+G3jnn7G2N3luXgLSfL+2ORDieXa1U=:VhuFOrOU2IpsjKYH8cH1VDaDBh/VivjMcuADjeEbIig=");
          //20 byte salt, and password="password"
          when(adminAccount20Byte.getPassword()).thenReturn("QL2NsxVEmRuDaNRkvIyADny7C5w=:JoegiytiWnoBAxmSD/PwBZZYqkr746x2KzPrZNw4NgI=");
  
      }
  
      @Test
      public void testEncode() throws UnsupportedEncodingException, NoSuchAlgorithmException {
  
          String encodedPassword = authenticator.encode("password");
  
          String storedPassword[] = encodedPassword.split(":");
          assertEquals("hash must consist of two components", 2, storedPassword.length);
  
          byte salt[] = Base64.decode(storedPassword[0]);
          String hashedPassword = authenticator.encode("password", salt);
  
          assertEquals("compare hashes", storedPassword[1], hashedPassword);
  
      }
  
      @Test
      public void testAuthentication() throws UnsupportedEncodingException, NoSuchAlgorithmException {
          Map<String, Object[]> dummyMap = new HashMap<String, Object[]>();
          assertEquals("32 byte salt authenticated", true, authenticator.authenticate("admin", "password", 0L, dummyMap).first());
          assertEquals("20 byte salt authenticated", true, authenticator.authenticate("admin20Byte", "password", 0L, dummyMap).first());
          assertEquals("fake user not authenticated", false, authenticator.authenticate("fake", "fake", 0L, dummyMap).first());
          assertEquals("bad password not authenticated", false, authenticator.authenticate("admin", "fake", 0L, dummyMap).first());
          assertEquals("20 byte user bad password not authenticated", false, authenticator.authenticate("admin20Byte", "fake", 0L, dummyMap).first());
      }
  
  //    @Test
  //    public void testTiming() throws UnsupportedEncodingException, NoSuchAlgorithmException {
  //        Map<String, Object[]> dummyMap = new HashMap<String, Object[]>();
  //        Double threshold = (double)500000; //half a millisecond
  //
  //        Long t1 = System.nanoTime();
  //        authenticator.authenticate("admin", "password", 0L, dummyMap);
  //        Long t2 = System.nanoTime();
  //        authenticator.authenticate("admin20Byte", "password", 0L, dummyMap);
  //        Long t3 = System.nanoTime();
  //        authenticator.authenticate("fake", "fake", 0L, dummyMap);
  //        Long t4 = System.nanoTime();
  //        authenticator.authenticate("admin", "fake", 0L, dummyMap);
  //        Long t5 = System.nanoTime();
  //        Long diff1 = t2 - t1;
  //        Long diff2 = t3 - t2;
  //        Long diff3 = t4 - t3;
  //        Long diff4 = t5 - t4;
  //        Assert.assertTrue("All computation times within " + threshold / 1000000 + " milisecond",
  //                (diff1 <= threshold) && (diff2 <= threshold) && (diff3 <= threshold) && (diff4 <= threshold));
  //    }
  }
  