001/* 002 * Copyright 2023 Vonage 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.vonage.client.sms; 017 018import com.vonage.client.VonageUnexpectedException; 019import java.io.UnsupportedEncodingException; 020 021 022/** 023 * Static helper methods for working with hex values. 024 */ 025public class HexUtil { 026 027 private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', }; 028 029 private HexUtil() { 030 // This class may not be instantiated. 031 } 032 033 /** 034 * translate a byte array of raw data into a String with a hex representation of that data 035 * 036 * @param bytes raw binary data 037 * 038 * @return String Hex representation of the raw data 039 */ 040 public static String bytesToHex(byte[] bytes) { 041 return bytesToHex(bytes, null); 042 } 043 044 /** 045 * translate a byte array of raw data into a String with a hex representation of that data. 046 * Each octet will be separated with a specific separator. 047 * 048 * @param bytes raw binary data 049 * @param separator This string will be injected into the output in between each octet in the stream 050 * 051 * @return String Hex representation of the raw data with each octet separated by 'separator' 052 */ 053 public static String bytesToHex(byte[] bytes, String separator) { 054 StringBuilder tmpBuffer = new StringBuilder(); 055 if (bytes != null) { 056 for (byte c : bytes) { 057 int b = c; 058 if (b < 0) 059 b += 256; 060 if (separator != null) 061 tmpBuffer.append(separator); 062 tmpBuffer.append(HEX_CHARS[(b & 0xf0) / 0x10]); // note, this benchmarks faster than using >> 4 063 tmpBuffer.append(HEX_CHARS[b & 0x0f]); 064 } 065 } 066 return tmpBuffer.toString(); 067 } 068 069 /** 070 * Converts a Hex encoded String into a byte vector. 071 * 072 * @param str The String to be encoded. 073 * 074 * @return A byte vector representing the String. 075 */ 076 public static byte[] hexToBytes(String str) { 077 if (str == null) 078 return null; 079 byte[] hexChars; 080 try { 081 hexChars = str.toUpperCase().getBytes("ISO_8859-1"); 082 } catch (UnsupportedEncodingException e) { 083 throw new VonageUnexpectedException("ISO_8859_1 is an unsupported encoding in this JVM"); 084 } 085 int size = hexChars.length; 086 byte[] bytes = new byte[size / 2]; 087 int first; 088 int second; 089 090 int rIndex = 0; 091 // Convert to bytes. 092 for (int i = 0; i+1 <size; i= i + 2) { 093 094 // Convert first 095 first = hexChars[i]; 096 if (first < 58) 097 first = ((first - 48) * 16); // 0 - 9 098 else 099 first = ((first - 55) * 16); // A - F 100 101 // Convert second 102 second = hexChars[i + 1]; 103 if (second < 58) 104 second = second - 48; // 0 - 9 105 else 106 second = second - 55; // A - F 107 108 //Value must be between -128 and 127 109 int total = (first + second); 110 if (total > 127) 111 total = (256 + total); 112 113 bytes[rIndex] = (byte) total; 114 rIndex++; 115 } 116 return bytes; 117 } 118 119}