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