1 package org.openecomp.sdc.securityutil;/*-
2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
24 import java.math.BigInteger;
25 import java.security.MessageDigest;
26 import java.security.NoSuchAlgorithmException;
27 import java.security.SecureRandom;
28 import java.util.Arrays;
29 import java.util.Random;
32 public class Passwords {
34 private static Logger log = LoggerFactory.getLogger( Passwords.class.getName());
35 private static final Random RANDOM = new SecureRandom();
36 private static final int SALT = 0;
37 private static final int HASH = 1;
38 private static final String HASH_ALGORITHM = "SHA-256";
41 * static utility class
47 * the method calculates a hash with a generated salt for the given password
50 * @return a "salt:hash" value
52 public static String hashPassword(String password) {
54 byte[] salt = getNextSalt();
55 byte byteData[] = hash(salt, password.getBytes());
56 if (byteData != null) {
57 return toHex(salt) + ":" + toHex(byteData);
64 * the method checks if the given password matches the calculated hash
70 public static boolean isExpectedPassword(String password, String expectedHash) {
71 if (password==null && expectedHash==null)
73 if (password==null || expectedHash==null) //iff exactly 1 is null
75 if (!expectedHash.contains(":")){
76 log.error("invalid password expecting hash at the prefix of the password (ex. e0277df331f4ff8f74752ac4a8fbe03b:6dfbad308cdf53c9ff2ee2dca811ee92f1b359586b33027580e2ff92578edbd0)\n" +
80 String[] params = expectedHash.split(":");
81 return isExpectedPassword(password, params[SALT], params[HASH]);
85 * the method checks if the given password matches the calculated hash
90 * the hash generated using the salt
91 * @return true if the password matched the hash
93 public static boolean isExpectedPassword(String password, String salt, String hash) {
94 if ( password == null && hash == null )
97 log.error("salt must be initialized");
100 //unintialized params
101 if ( password == null || hash == null )
103 byte[] saltBytes = fromHex(salt);
104 byte[] hashBytes = fromHex(hash);
106 byte byteData[] = hash(saltBytes, password.getBytes());
107 if (byteData != null) {
108 return Arrays.equals(byteData, hashBytes);
113 public static void main(String[] args) {
114 if (args.length > 1 || args.length > 0) {
115 System.out.println("[" + hashPassword(args[0]) + "]");
117 System.out.println("no passward passed.");
123 * Returns a random salt to be used to hash a password.
125 * @return a 16 bytes random salt
127 private static byte[] getNextSalt() {
128 byte[] salt = new byte[16];
129 RANDOM.nextBytes(salt);
134 * hase's the salt and value using the chosen algorithm
138 * @return an array of bytes resulting from the hash
140 private static byte[] hash(byte[] salt, byte[] password) {
142 byte[] byteData = null;
144 md = MessageDigest.getInstance(HASH_ALGORITHM);
147 byteData = md.digest();
148 } catch (NoSuchAlgorithmException e) {
149 System.out.println("invalid algorithm name");
155 * Converts a string of hexadecimal characters into a byte array.
159 * @return the hex string decoded into a byte array
161 private static byte[] fromHex(String hex) {
164 byte[] binary = new byte[hex.length() / 2];
165 for (int i = 0; i < binary.length; i++) {
166 binary[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
172 * Converts a byte array into a hexadecimal string.
175 * the byte array to convert
176 * @return a length*2 character string encoding the byte array
178 private static String toHex(byte[] array) {
179 BigInteger bi = new BigInteger(1, array);
180 String hex = bi.toString(16);
181 int paddingLength = (array.length * 2) - hex.length();
182 if (paddingLength > 0)
183 return String.format("%0" + paddingLength + "d", 0) + hex;