Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.keystore.cts;
     18 
     19 import java.nio.ByteBuffer;
     20 
     21 /**
     22  * Hexadecimal encoding where each byte is represented by two hexadecimal digits.
     23  *
     24  * @hide
     25  */
     26 public class HexEncoding {
     27 
     28   /** Hidden constructor to prevent instantiation. */
     29   private HexEncoding() {}
     30 
     31   private static final char[] HEX_DIGITS = "0123456789abcdef".toCharArray();
     32 
     33   /**
     34    * Encodes the provided data as a hexadecimal string.
     35    */
     36   public static String encode(byte[] data) {
     37     return encode(data, 0, data.length);
     38   }
     39 
     40   /**
     41    * Encodes the provided data as a hexadecimal string.
     42    */
     43   public static String encode(byte[] data, int offset, int len) {
     44     StringBuilder result = new StringBuilder(len * 2);
     45     for (int i = 0; i < len; i++) {
     46       byte b = data[offset + i];
     47       result.append(HEX_DIGITS[(b >>> 4) & 0x0f]);
     48       result.append(HEX_DIGITS[b & 0x0f]);
     49     }
     50     return result.toString();
     51   }
     52 
     53   /**
     54    * Encodes the provided data as a hexadecimal string.
     55    */
     56   public static String encode(ByteBuffer buf) {
     57     return encode(buf.array(), buf.arrayOffset() + buf.position(), buf.remaining());
     58   }
     59 
     60   /**
     61    * Decodes the provided hexadecimal string into an array of bytes.
     62    */
     63   public static byte[] decode(String encoded) {
     64     // IMPLEMENTATION NOTE: Special care is taken to permit odd number of hexadecimal digits.
     65     int resultLengthBytes = (encoded.length() + 1) / 2;
     66     byte[] result = new byte[resultLengthBytes];
     67     int resultOffset = 0;
     68     int encodedCharOffset = 0;
     69     if ((encoded.length() % 2) != 0) {
     70       // Odd number of digits -- the first digit is the lower 4 bits of the first result byte.
     71       result[resultOffset++] = (byte) getHexadecimalDigitValue(encoded.charAt(encodedCharOffset));
     72       encodedCharOffset++;
     73     }
     74     for (int len = encoded.length(); encodedCharOffset < len; encodedCharOffset += 2) {
     75       result[resultOffset++] = (byte)
     76           ((getHexadecimalDigitValue(encoded.charAt(encodedCharOffset)) << 4)
     77           | getHexadecimalDigitValue(encoded.charAt(encodedCharOffset + 1)));
     78     }
     79     return result;
     80   }
     81 
     82   private static int getHexadecimalDigitValue(char c) {
     83     if ((c >= 'a') && (c <= 'f')) {
     84       return (c - 'a') + 0x0a;
     85     } else if ((c >= 'A') && (c <= 'F')) {
     86       return (c - 'A') + 0x0a;
     87     } else if ((c >= '0') && (c <= '9')) {
     88       return c - '0';
     89     } else {
     90       throw new IllegalArgumentException(
     91           "Invalid hexadecimal digit at position : '" + c + "' (0x" + Integer.toHexString(c) + ")");
     92     }
     93   }
     94 }
     95