package mixconfig.tools.dataretention.smartcard; import java.io.UnsupportedEncodingException; import java.util.Map; public class Helpers { private static byte hexBase = (byte) 0xFF; /** * Converts a short (2 byte) into a byte array of size two. * * @param shortValue * - ab * @return - {a, b} */ public static byte[] shortToBytes(short shortValue) { byte[] bytes = new byte[2]; bytes[0] = (byte) (((hexBase << 8) & shortValue) >> 8); bytes[1] = (byte) (hexBase & shortValue); return bytes; } /** * Reverts {@link #shortToBytes(short)}. * * @param bytes * - {a, b} * @return - (short) (ab) */ public static short bytesToShort(byte[] bytes) { return (short) ((bytes[0] << 8) | (bytes[1] & 0x00FF)); } /** * Returns a string containing the hex digit pairs of a byte array. * * @param data * @return * * @see #byteToHex(byte) */ public static String bytesToHexDigits(byte[] data) { if (data == null) { return "null"; } StringBuffer buf = new StringBuffer(); for (int i = 0; i < data.length; i++) { buf.append(byteToHex(data[i])); buf.append(" "); } return (buf.toString()); } /** * Returns two hex digits (00 - FF) according to the value of data. * * @param data * @return */ public static String byteToHex(byte data) { StringBuffer buf = new StringBuffer(); buf.append(toHexChar((data >>> 4) & 0x0F)); buf.append(toHexChar(data & 0x0F)); return buf.toString(); } /** * Copied from deprecated class DataRetenrionSmartCard TODO: javadoc * * @param i * @return */ public static char toHexChar(int i) { if ((0 <= i) && (i <= 9)) { return (char) ('0' + i); } else { return (char) ('a' + (i - 10)); } } /** * This method copies the next maximalLength bytes from the offset into a * new array, which is returned. If offset+maximalLength >= data.length the * returned array is shorter (could be of length zero). * * @param data * @param offset * @param maximalLength * @return */ public static byte[] copyOfRange(byte[] data, int offset, int maximalLength) { int length = maximalLength; if (offset + maximalLength >= data.length) { length = data.length - offset; } byte[] copy = new byte[length]; for (int i = 0; i < length; i++) { copy[i] = data[i + offset]; } return copy; } /** * Concatenates to byte array. * * @param head * = {h0, ..., hn} * @param tail * = {t0, ..., tm} * @return {h0, ..., hn, t0, ..., tm} */ public static byte[] concatenate(byte[] head, byte[] tail) { if (head == null) { return tail; } if (tail == null) { return head; } byte[] concatenation = new byte[head.length + tail.length]; for (int i = 0; i < head.length; i++) { concatenation[i] = head[i]; } for (int i = 0; i < tail.length; i++) { concatenation[i + head.length] = tail[i]; } return concatenation; } /** * Converts an username to a byte array. * * @param string * @return */ public static byte[] stringToUtf8Bytes(String string) { try { return string.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException("Must not happen, UTF-8 is always supported", e); } } /** * Undoes {@link #stringToUtf8Bytes(String)} * * @param uft8Bytes * @return */ public static String utf8BytesToString(byte[] uft8Bytes) { try { return new String(uft8Bytes, "UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException("Must not happen, UTF-8 is always supported", e); } } /** * * Converts an password (must only contain digits) to a byte array. * * @param stringPin * @return */ public static byte[] loginPasswordToBytes(String stringPin) { byte[] bytePin = new byte[stringPin.length()]; for (int i = 0; i < bytePin.length; i++) { byte digit = Byte.valueOf(stringPin.charAt(i) + "").byteValue(); if (digit < 0 || digit > 9) { throw new IllegalArgumentException("Password (" + stringPin + ") must contain only digits."); } bytePin[i] = digit; } return bytePin; } /** * Encodes an user, so that it can be send in as data in a APDU to the * ANONCardApplet. * * @param name * @param pin * @return */ public static byte[] packUser(String name, String pin) { byte[] encodedName = stringToUtf8Bytes(name); encodedName = concatenate(new byte[] { (byte) encodedName.length }, encodedName); return concatenate(encodedName, loginPasswordToBytes(pin)); } /** * Encodes a set of user, so that it can be send in as data in a APDU to the * ANONCardApplet. * * @param users * @return */ public static byte[] packUsers(Map users) { if (users == null) { return new byte[] {}; } byte[] encodedUsers = new byte[] {}; for (String name : users.keySet()) { encodedUsers = concatenate(encodedUsers, packUser(name, users.get(name))); } return encodedUsers; } /** * Encodes a boolean value, so that it can be send to the ANONCardApplet. * * @param value * @return */ public static byte packBoolean(boolean value) { if (value) { return ApduConstants.TRUE; } else { return ApduConstants.FALSE; } } }