/* * Copyright 2014 Robert Bachmann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.licel.jcardsim.utils; import org.bouncycastle.util.encoders.Hex; /** * Utility methods for dealing with byte arrays. */ public final class ByteUtil { private static final char[] hexArray = "0123456789ABCDEF".toCharArray(); /** * Create byte array from hex string * @param hexString hex string * @return new byte array * @throws java.lang.NullPointerException if <code>hexString</code> is null */ public static byte[] byteArray(String hexString) { if (hexString == null) { throw new NullPointerException("hexArray"); } return Hex.decode(hexString); } /** * Convert byte array into hex string * @param bytes hex string * @return hexString * @throws java.lang.NullPointerException if <code>bytes</code> is null */ public static String hexString(byte[] bytes) { if (bytes == null) { throw new NullPointerException("bytes"); } return hexString(bytes, 0, bytes.length); } /** * Convert byte array into hex string * @param bytes hex string * @param offset offset * @param length length * @return hexString * @throws java.lang.NullPointerException if <code>bytes</code> is null */ public static String hexString(byte[] bytes, int offset, int length) { // http://stackoverflow.com/questions/9655181/convert-from-byte-array-to-hex-string-in-java if (bytes == null) { throw new NullPointerException("bytes"); } char[] hexChars = new char[length * 2]; for ( int j = offset, i=0; j < (offset + length); j++, i++ ) { int v = bytes[j] & 0xFF; hexChars[i * 2] = hexArray[v >>> 4]; hexChars[i * 2 + 1] = hexArray[v & 0x0F]; } return new String(hexChars); } /** * Extract status word from APDU * @param apduBuffer APDU bytes * @return status word * @throws java.lang.NullPointerException if <code>apduBuffer</code> is null * @throws java.lang.IllegalArgumentException if <code>apduBuffer.length</code> is < 2 */ public static short getSW(byte[] apduBuffer) { if (apduBuffer == null) { throw new NullPointerException("bytes"); } if (apduBuffer.length < 2) { throw new IllegalArgumentException("bytes.length must be at least 2"); } return getShort(apduBuffer, apduBuffer.length - 2); } /** * Check status word from APDU * @param apduBuffer APDU bytes * @param expected expected status word * @throws java.lang.NullPointerException if <code>apduBuffer</code> is null * @throws java.lang.IllegalArgumentException if <code>apduBuffer.length</code> is < 2 * @throws java.lang.AssertionError if <code>expected</code> does not match the status word from <code>apduBuffer</code> */ public static void requireSW(byte[] apduBuffer, int expected) { int sw = getSW(apduBuffer) & 0xFFFF; if (sw != expected) { throw new AssertionError(String.format("Expected status word %x but got %x", expected, sw)); } } /** * Check status word from APDU * @param apduBuffer APDU bytes * @param expected expected status word * @throws java.lang.NullPointerException if <code>apduBuffer</code> is null * @throws java.lang.IllegalArgumentException if <code>apduBuffer.length</code> is < 2 * @throws java.lang.AssertionError if <code>expected</code> does not match the status word from <code>apduBuffer</code> */ public static void requireSW(byte[] apduBuffer, short expected) { requireSW(apduBuffer, expected & 0xFFFF); } /** * Read short from array * @see javacard.framework.Util#getShort(byte[], short) * @param bArray byte array * @param offset offset * @return short value */ public static short getShort(byte[] bArray, int offset) { return (short) (((short) bArray[offset] << 8) + ((short) bArray[offset + 1] & 0xff)); } private ByteUtil() {} }