blob: 0b1da393445460bcf000cdd366ce733308930036 [file] [log] [blame]
/*
* 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.fineract.cn.crypto;
import org.apache.fineract.cn.crypto.config.EnableCrypto;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.util.EncodingUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.springframework.util.Base64Utils;
import java.nio.file.Files;
import java.nio.file.Paths;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
classes = {
HashGeneratorSample.SampleSpringConfiguration.class
},
loader = AnnotationConfigContextLoader.class
)
public class HashGeneratorSample {
@Configuration
@EnableCrypto
public static class SampleSpringConfiguration {
public SampleSpringConfiguration() {
super();
}
}
private static final String USERNAME = "nebuchadnezzar";
private static final String TENANT = "sippar";
private static final String DOMAIN = "babylon.ad";
private static final String PASSWORD = "m4duk";
private static final int ITERATION_COUNT = 4096;
private static final int HASH_LENGTH = 256;
@Autowired
private SaltGenerator saltGenerator;
@Autowired
private HashGenerator hashGenerator;
public HashGeneratorSample() {
super();
}
@Test
public void clientPasswordHashSpecification() throws Exception {
// 1. create user specific salt, username+tenant+TLD, Base64 URL encoded
final StringBuilder saltBuilder = new StringBuilder();
saltBuilder.append(USERNAME).append(TENANT).append(DOMAIN);
final byte[] salt = Base64Utils.encode(saltBuilder.toString().getBytes());
// 2. encode user password URL safe with Base64
final String encodedPassword = Base64Utils.encodeToString(PASSWORD.getBytes());
// 3. create user password hash, to be send to service
final byte[] hash = this.hashGenerator.hash(encodedPassword, salt, ITERATION_COUNT, HASH_LENGTH);
Assert.assertNotNull(hash);
Assert.assertTrue(hash.length > 0);
}
@Test
public void servicePasswordHashSpecification() throws Exception {
// 0. retrieve user password
final byte[] password = Files.readAllBytes(
Paths.get(getClass().getClassLoader()
.getResource(".password")
.toURI()));
// 1. read stored secret
final byte[] storedSecret = Files.readAllBytes(
Paths.get(getClass().getClassLoader()
.getResource(".secret")
.toURI()));
// 2. create variable salt, to be stored with user info
final byte[] variableSalt = this.saltGenerator.createRandomSalt();
// 3. concatenate variable salt and secret to create unique salt for this user
final byte[] salt = EncodingUtils.concatenate(variableSalt, storedSecret);
// 4. create hash to be stored with user info
final byte[] hash = this.hashGenerator.hash(Base64Utils.encodeToString(password), salt, ITERATION_COUNT, HASH_LENGTH);
Assert.assertNotNull(hash);
Assert.assertTrue(hash.length > 0);
}
@Test
public void clientPasswordIsEqual() throws Exception {
// 0. retrieve user password
final byte[] password = Files.readAllBytes(
Paths.get(getClass().getClassLoader()
.getResource(".password")
.toURI()));
// 1. read stored secret
final byte[] storedSecret = Files.readAllBytes(
Paths.get(getClass().getClassLoader()
.getResource(".secret")
.toURI()));
// 2. read stored variable salt from user info
final byte[] storedSalt = Files.readAllBytes(
Paths.get(getClass().getClassLoader()
.getResource(".salt")
.toURI()));
// 3. read stored hash from user info
final byte[] storedHash = Files.readAllBytes(
Paths.get(getClass().getClassLoader()
.getResource(".hash")
.toURI()));
// 4. check if password is equal with stored hash
Assert.assertTrue(this.hashGenerator.isEqual(storedHash, password, storedSecret, storedSalt, ITERATION_COUNT, HASH_LENGTH));
}
}