public static byte[] decode(byte[] bytes) {
        if (bytes == null) throw new NullPointerException("bytes");
        if (bytes.length % 2 != 0) throw new IllegalArgumentException("Hex data length must be a multiple of 2");

        int retlen = bytes.length / 2;
        byte[] ret = new byte[retlen];

        for (int i=0; i < retlen; i++) {
	    byte c = bytes[i*2];
	    byte d = bytes[i*2+1];
	    if (c < 0 || d < 0 ||
                c > HEXTABLEINV.length || d > HEXTABLEINV.length) {
                throw new IllegalArgumentException("Data contains invalid hex character");
            }
            byte b = HEXTABLEINV[c];
            if (b < 0)
                throw new IllegalArgumentException("Data contains invalid hex character");
            ret[i] = (byte) (b << 4);
            b = HEXTABLEINV[d];
            if (b < 0)
                throw new IllegalArgumentException("Data contains invalid hex character");
            ret[i] |= b;
        }

        return ret;
    }