Added oparent to sdc main
[sdc.git] / security-utils / src / main / java / org / openecomp / sdc / security / Passwords.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.openecomp.sdc.security;
22
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 import java.math.BigInteger;
27 import java.security.MessageDigest;
28 import java.security.NoSuchAlgorithmException;
29 import java.security.SecureRandom;
30 import java.util.Arrays;
31 import java.util.Random;
32
33
34 public class Passwords {
35
36         private static Logger log = LoggerFactory.getLogger( Passwords.class);
37         private static final Random RANDOM = new SecureRandom();
38         private static final int SALT = 0;
39         private static final int HASH = 1;
40         private static final String HASH_ALGORITHM = "SHA-256";
41
42         /**
43          * static utility class
44          */
45         private Passwords() {
46         }
47
48         /**
49          * the method calculates a hash with a generated salt for the given password
50          * 
51          * @param password
52          * @return a "salt:hash" value
53          */
54         public static String hashPassword(String password) {
55                 if (password!=null){
56                         byte[] salt = getNextSalt();
57                         byte[] byteData = hash(salt, password.getBytes());
58                         if (byteData != null) {
59                                 return toHex(salt) + ":" + toHex(byteData);
60                         }
61                 }
62                 return null;
63         }
64
65         /**
66          * the method checks if the given password matches the calculated hash
67          * 
68          * @param password
69          * @param expectedHash
70          * @return
71          */
72         public static boolean isExpectedPassword(String password, String expectedHash) {
73                 if (password==null && expectedHash==null)
74                         return true;
75                 if (password==null || expectedHash==null)       //iff exactly 1 is null
76                         return false;
77                 if (!expectedHash.contains(":")){
78                         log.error("invalid password expecting hash at the prefix of the password (ex. e0277df331f4ff8f74752ac4a8fbe03b:6dfbad308cdf53c9ff2ee2dca811ee92f1b359586b33027580e2ff92578edbd0)\n" +
79                                         "\t\t\t");
80                         return false;
81                 }
82                 String[] params = expectedHash.split(":");
83                 return isExpectedPassword(password, params[SALT], params[HASH]);
84         }
85
86         /**
87          * the method checks if the given password matches the calculated hash
88          * 
89          * @param password
90          * @param salt
91          * @param hash
92          *            the hash generated using the salt
93          * @return true if the password matched the hash
94          */
95         public static boolean isExpectedPassword(String password, String salt, String hash) {
96                 if ( password == null &&  hash == null )
97                         return true;
98                 if ( salt == null ){
99                         log.error("salt must be initialized");
100                         return false;
101                 }
102                 //unintialized params
103                 if ( password == null ||  hash == null )
104                         return false;
105                 byte[] saltBytes = fromHex(salt);
106                 byte[] hashBytes = fromHex(hash);
107
108                 byte[] byteData = hash(saltBytes, password.getBytes());
109                 if (byteData != null) {
110                         return Arrays.equals(byteData, hashBytes);
111                 }
112                 return false;
113         }
114
115         public static void main(String[] args) {
116                 if (args.length > 1 || args.length > 0) {
117                         System.out.println("[" + hashPassword(args[0]) + "]");
118                 } else {
119                         System.out.println("no passward passed.");
120                 }
121
122         }
123
124         /**
125          * Returns a random salt to be used to hash a password.
126          * 
127          * @return a 16 bytes random salt
128          */
129         private static byte[] getNextSalt() {
130                 byte[] salt = new byte[16];
131                 RANDOM.nextBytes(salt);
132                 return salt;
133         }
134
135         /**
136          * hase's the salt and value using the chosen algorithm
137          * 
138          * @param salt
139          * @param password
140          * @return an array of bytes resulting from the hash
141          */
142         private static byte[] hash(byte[] salt, byte[] password) {
143                 MessageDigest md;
144                 byte[] byteData = null;
145                 try {
146                         md = MessageDigest.getInstance(HASH_ALGORITHM);
147                         md.update(salt);
148                         md.update(password);
149                         byteData = md.digest();
150                 } catch (NoSuchAlgorithmException e) {
151                     log.error("invalid algorithm name {}", e);
152                         System.out.println("invalid algorithm name");
153                 }
154                 return byteData;
155         }
156
157         /**
158          * Converts a string of hexadecimal characters into a byte array.
159          *
160          * @param hex
161          *            the hex string
162          * @return the hex string decoded into a byte array
163          */
164         private static byte[] fromHex(String hex) {
165                 if ( hex == null )
166                         return null;
167                 byte[] binary = new byte[hex.length() / 2];
168                 for (int i = 0; i < binary.length; i++) {
169                         binary[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
170                 }
171                 return binary;
172         }
173
174         /**
175          * Converts a byte array into a hexadecimal string.
176          *
177          * @param array
178          *            the byte array to convert
179          * @return a length*2 character string encoding the byte array
180          */
181         private static String toHex(byte[] array) {
182                 BigInteger bi = new BigInteger(1, array);
183                 String hex = bi.toString(16);
184                 int paddingLength = (array.length * 2) - hex.length();
185                 if (paddingLength > 0)
186                         return String.format("%0" + paddingLength + "d", 0) + hex;
187                 else
188                         return hex;
189         }
190 }