/**
* Convert a hex string to a byte array.
* Permits upper or lower case hex.
*
* @param s String must have even number of characters.
* and be formed only of digits 0-9 A-F or
* a-f. No spaces, minus or plus signs.
* @return corresponding byte array.
*/
public static byte[] fromHexString ( String s )
   {
   int stringLength = s.length();
   if ( (stringLength & 0x1) != 0 )
      {
      throw new IllegalArgumentException ( "fromHexString requires an even number of hex characters" );
      }byte[] b = new byte[stringLength / 2];

   for ( int i=0,j=0; i<stringLength; i+=2,j++ )
      {
      int high = charToNibble( s.charAt ( i ) );
      int low = charToNibble( s.charAt ( i+1 ) );
      b[j] = (byte)( ( high << 4 ) | low );
      }
   return b;
   }

/**
* convert a single char to corresponding nibble.
*
* @param c char to convert. must be 0-9 a-f A-F, no
* spaces, plus or minus signs.
*
* @return corresponding integer
*/
private static int charToNibble ( char c )
   {
   if ( '0' <= c && c <= '9' )
      {
      return c - '0';
      }
   else if ( 'a' <= c && c <= 'f' )
      {
      return c - 'a' + 0xa;
      }
   else if ( 'A' <= c && c <= 'F' )
      {
      return c - 'A' + 0xa;
      }
   else
      {
      throw new IllegalArgumentException ( "Invalid hex character: " + c );
      }
   }