6babb4c92baf58ce6fa15a50b2f3c76a68f02c29
[aaf/authz.git] / cadi / core / src / main / java / org / onap / aaf / cadi / Hash.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
4  * ===========================================================================
5  * Copyright (c) 2018 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
22 package org.onap.aaf.cadi;
23
24 import java.nio.ByteBuffer;
25 import java.security.MessageDigest;
26 import java.security.NoSuchAlgorithmException;
27
28 public class Hash {
29         private static char hexDigit[] = "0123456789abcdef".toCharArray();
30         
31 /////////////////////////////////
32 // MD5
33 /////////////////////////////////
34         /**
35          * Encrypt MD5 from Byte Array to Byte Array
36          * @param input
37          * @return
38          * @throws NoSuchAlgorithmException
39          */
40         public static byte[] hashMD5 (byte[] input) throws NoSuchAlgorithmException {
41                 // Note: Protect against Multi-thread issues with new MessageDigest 
42                 MessageDigest md = MessageDigest.getInstance("MD5");
43                 md.update(input); 
44                 return md.digest();
45         }
46
47         /**
48          * Encrypt MD5 from Byte Array to Byte Array
49          * @param input
50          * @return
51          * @throws NoSuchAlgorithmException
52          */
53         public static byte[] hashMD5 (byte[] input, int offset, int length) throws NoSuchAlgorithmException {
54                 // Note: Protect against Multi-thread issues with new MessageDigest 
55                 MessageDigest md = MessageDigest.getInstance("MD5");
56                 md.update(input,offset,length); 
57                 return md.digest();
58         }
59
60
61
62         /**
63          * Convenience Function: Encrypt MD5 from String to String Hex representation 
64          * 
65          * @param input
66          * @return
67          * @throws NoSuchAlgorithmException
68          */
69         public static String hashMD5asStringHex(String input) throws NoSuchAlgorithmException {
70                 byte[] output = hashMD5(input.getBytes());
71                 StringBuilder sb = new StringBuilder("0x");
72                  for (byte b : output) {
73                     sb.append(hexDigit[(b >> 4) & 0x0f]);
74                     sb.append(hexDigit[b & 0x0f]);
75                  }
76                  return sb.toString();
77         }
78
79 /////////////////////////////////
80 // SHA256
81 /////////////////////////////////
82         /**
83          * SHA256 Hashing
84          */
85         public static byte[] hashSHA256(byte[] input) throws NoSuchAlgorithmException {
86                 // Note: Protect against Multi-thread issues with new MessageDigest 
87                 MessageDigest md = MessageDigest.getInstance("SHA-256");
88                 md.update(input); 
89                 return md.digest();
90         }
91
92         /**
93          * SHA256 Hashing
94          */
95         public static byte[] hashSHA256(byte[] input, int offset, int length) throws NoSuchAlgorithmException {
96                 // Note: Protect against Multi-thread issues with new MessageDigest 
97                 MessageDigest md = MessageDigest.getInstance("SHA-256");
98                 md.update(input,offset,length); 
99                 return md.digest();
100         }
101         
102         /**
103          * Convenience Function: Hash from String to String Hex representation
104          * 
105          * @param input
106          * @return
107          * @throws NoSuchAlgorithmException
108          */
109         public static String hashSHA256asStringHex(String input) throws NoSuchAlgorithmException {
110                 return toHex(hashSHA256(input.getBytes()));
111         }
112
113         /**
114          * Convenience Function: Hash from String to String Hex representation
115          * 
116          * @param input
117          * @return
118          * @throws NoSuchAlgorithmException
119          */
120         public static String hashSHA256asStringHex(String input, int salt) throws NoSuchAlgorithmException {
121                 byte[] in = input.getBytes();
122                 ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE + in.length);
123                 bb.putInt(salt);
124                 bb.put(input.getBytes());
125                 return toHex(Hash.hashSHA256(bb.array()));
126         }
127         
128         /**
129          * Compare two byte arrays for equivalency
130          * @param ba1
131          * @param ba2
132          * @return
133          */
134         public static boolean isEqual(byte ba1[], byte ba2[]) {
135                 if(ba1.length!=ba2.length)return false;
136                 for(int i = 0;i<ba1.length; ++i) {
137                         if(ba1[i]!=ba2[i])return false;
138                 }
139                 return true;
140         }
141
142         public static int compareTo(byte[] a, byte[] b) {
143                 int end = Math.min(a.length, b.length);
144                 int compare = 0;
145                 for(int i=0;compare == 0 && i<end;++i) {
146                         compare = a[i]-b[i];
147                 }
148                 if(compare==0)compare=a.length-b.length;
149                 return compare;
150         }
151
152         public static String toHexNo0x(byte[] ba) {
153                 StringBuilder sb = new StringBuilder();
154                  for (byte b : ba) {
155                     sb.append(hexDigit[(b >> 4) & 0x0f]);
156                     sb.append(hexDigit[b & 0x0f]);
157                  }
158                  return sb.toString();
159         }
160
161         public static String toHex(byte[] ba) {
162                 StringBuilder sb = new StringBuilder("0x");
163                  for (byte b : ba) {
164                     sb.append(hexDigit[(b >> 4) & 0x0f]);
165                     sb.append(hexDigit[b & 0x0f]);
166                  }
167                  return sb.toString();
168         }
169         
170         public static String toHex(byte[] ba, int start, int length) {
171                 StringBuilder sb = new StringBuilder("0x");
172                  for (int i=start;i<length;++i) {
173                     sb.append(hexDigit[(ba[i] >> 4) & 0x0f]);
174                     sb.append(hexDigit[ba[i] & 0x0f]);
175                  }
176                  return sb.toString();
177         }
178
179         
180         public static byte[] fromHex(String s)  throws CadiException{
181                 if(!s.startsWith("0x")) {
182                         throw new CadiException("HexString must start with \"0x\"");
183                 }
184                 boolean high = true;
185                 int c;
186                 byte b;
187                 byte[] ba = new byte[(s.length()-2)/2];
188                 int idx;
189                 for(int i=2;i<s.length();++i) {
190                         c = s.charAt(i);
191                         if(c>=0x30 && c<=0x39) {
192                                 b=(byte)(c-0x30);
193                         } else if(c>=0x61 && c<=0x66) {
194                                 b=(byte)(c-0x57);  // account for "A"
195                         } else if(c>=0x41 && c<=0x46) {
196                                 b=(byte)(c-0x37);
197                         } else {
198                                 throw new CadiException("Invalid char '" + c + "' in HexString");
199                         }
200                         idx = (i-2)/2;
201                         if(high) {
202                                 ba[idx]=(byte)(b<<4);
203                                 high = false;
204                         } else {
205                                 ba[idx]|=b;
206                                 high = true;
207                         }
208                 }
209                 return ba;
210         }
211
212         /**
213          * Does not expect to start with "0x"
214          * if Any Character doesn't match, it returns null;
215          * 
216          * @param s
217          * @return
218          */
219         public static byte[] fromHexNo0x(String s) {
220                 int c;
221                 byte b;
222                 byte[] ba;
223                 boolean high;
224                 int start;
225                 if(s.length()%2==0) {
226                         ba = new byte[s.length()/2];
227                         high=true;
228                         start=0;
229                 } else {
230                         ba = new byte[(s.length()/2)+1];
231                         high = false;
232                         start=1;
233                 }
234                 int idx;
235                 for(int i=start;i<s.length();++i) {
236                         c = s.charAt((i-start));
237                         if(c>=0x30 && c<=0x39) {
238                                 b=(byte)(c-0x30);
239                         } else if(c>=0x61 && c<=0x66) {
240                                 b=(byte)(c-0x57);  // account for "A"
241                         } else if(c>=0x41 && c<=0x46) {
242                                 b=(byte)(c-0x37);
243                         } else {
244                                 return null;
245                         }
246                         idx = i/2;
247                         if(high) {
248                                 ba[idx]=(byte)(b<<4);
249                                 high = false;
250                         } else {
251                                 ba[idx]|=b;
252                                 high = true;
253                         }
254                 }
255                 return ba;
256         }
257
258 }