A collection of utility methods used throughout this project.
* * @version $Revision: 1.10 $ */ class Util { // Constants and variables // ------------------------------------------------------------------------- // Hex charset private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray(); // Base-64 charset private static final String BASE64_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"; private static final char[] BASE64_CHARSET = BASE64_CHARS.toCharArray(); // Constructor(s) // ------------------------------------------------------------------------- /** Trivial constructor to enforce Singleton pattern. */ private Util() { super(); } // Class methods // ------------------------------------------------------------------------- /** *Returns a string of hexadecimal digits from a byte array. Each byte is * converted to 2 hex symbols; zero(es) included.
* *This method calls the method with same name and three arguments as:
* ** toString(ba, 0, ba.length); ** * @param ba the byte array to convert. * @return a string of hexadecimal characters (two for each byte) * representing the designated input byte array. */ public static String toString(byte[] ba) { return toString(ba, 0, ba.length); } /** *
Returns a string of hexadecimal digits from a byte array, starting at
* offset
and consisting of length
bytes. Each byte
* is converted to 2 hex symbols; zero(es) included.
Returns a string of hexadecimal digits from a byte array. Each byte is * converted to 2 hex symbols; zero(es) included. The argument is * treated as a large little-endian integer and is returned as a * large big-endian integer.
* *This method calls the method with same name and three arguments as:
* ** toReversedString(ba, 0, ba.length); ** * @param ba the byte array to convert. * @return a string of hexadecimal characters (two for each byte) * representing the designated input byte array. */ public static String toReversedString(byte[] ba) { return toReversedString(ba, 0, ba.length); } /** *
Returns a string of hexadecimal digits from a byte array, starting at
* offset
and consisting of length
bytes. Each byte
* is converted to 2 hex symbols; zero(es) included.
The byte array is treated as a large little-endian integer, and * is returned as a large big-endian integer.
* * @param ba the byte array to convert. * @param offset the index from which to start considering the bytes to * convert. * @param length the count of bytes, starting from the designated offset to * convert. * @return a string of hexadecimal characters (two for each byte) * representing the designated input byte sub-array. */ public static final String toReversedString(byte[] ba, int offset, int length) { char[] buf = new char[length * 2]; for (int i = offset+length-1, j = 0, k; i >= offset; ) { k = ba[offset + i--]; buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F]; buf[j++] = HEX_DIGITS[ k & 0x0F]; } return new String(buf); } /** *Returns a byte array from a string of hexadecimal digits.
* * @param s a string of hexadecimal ASCII characters * @return the decoded byte array from the input hexadecimal string. */ public static byte[] toBytesFromString(String s) { int limit = s.length(); byte[] result = new byte[((limit + 1) / 2)]; int i = 0, j = 0; if ((limit % 2) == 1) { result[j++] = (byte) fromDigit(s.charAt(i++)); } while (i < limit) { result[j ] = (byte) (fromDigit(s.charAt(i++)) << 4); result[j++] |= (byte) fromDigit(s.charAt(i++)); } return result; } /** *Returns a byte array from a string of hexadecimal digits, interpreting * them as a large big-endian integer and returning it as a large * little-endian integer.
* * @param s a string of hexadecimal ASCII characters * @return the decoded byte array from the input hexadecimal string. */ public static byte[] toReversedBytesFromString(String s) { int limit = s.length(); byte[] result = new byte[((limit + 1) / 2)]; int i = 0; if ((limit % 2) == 1) { result[i++] = (byte) fromDigit(s.charAt(--limit)); } while (limit > 0) { result[i ] = (byte) fromDigit(s.charAt(--limit)); result[i++] |= (byte) (fromDigit(s.charAt(--limit)) << 4); } return result; } /** *Returns a number from 0
to 15
corresponding
* to the designated hexadecimal digit.
Returns a string of 8 hexadecimal digits (most significant digit first)
* corresponding to the unsigned integer n
.
Returns a string of hexadecimal digits from an integer array. Each int * is converted to 4 hex symbols.
*/ public static String toString(int[] ia) { int length = ia.length; char[] buf = new char[length * 8]; for (int i = 0, j = 0, k; i < length; i++) { k = ia[i]; buf[j++] = HEX_DIGITS[(k >>> 28) & 0x0F]; buf[j++] = HEX_DIGITS[(k >>> 24) & 0x0F]; buf[j++] = HEX_DIGITS[(k >>> 20) & 0x0F]; buf[j++] = HEX_DIGITS[(k >>> 16) & 0x0F]; buf[j++] = HEX_DIGITS[(k >>> 12) & 0x0F]; buf[j++] = HEX_DIGITS[(k >>> 8) & 0x0F]; buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F]; buf[j++] = HEX_DIGITS[ k & 0x0F]; } return new String(buf); } /** *Returns a string of 16 hexadecimal digits (most significant digit first)
* corresponding to the unsigned long n
.
Similar to the toString()
method except that the Unicode
* escape character is inserted before every pair of bytes. Useful to
* externalise byte arrays that will be constructed later from such strings;
* eg. s-box values.
Similar to the toString()
method except that the Unicode
* escape character is inserted before every pair of bytes. Useful to
* externalise byte arrays that will be constructed later from such strings;
* eg. s-box values.
Similar to the toString()
method except that the Unicode
* escape character is inserted before every pair of bytes. Useful to
* externalise integer arrays that will be constructed later from such
* strings; eg. s-box values.
Dumps a byte array as a string, in a format that is easy to read for
* debugging. The string m
is prepended to the start of each
* line.
If offset
and length
are omitted, the whole
* array is used. If m
is omitted, nothing is prepended to each
* line.
Returns a string of 2 hexadecimal digits (most significant digit first)
* corresponding to the lowest 8 bits of n
.
Converts a designated byte array to a Base-64 representation, with the * exceptions that (a) leading 0-byte(s) are ignored, and (b) the character * '.' (dot) shall be used instead of "+' (plus).
* *Used by SASL password file manipulation primitives.
* * @param buffer an arbitrary sequence of bytes to represent in Base-64. * @return unpadded (without the '=' character(s)) Base-64 representation of * the input. */ public static final String toBase64(byte[] buffer) { int len = buffer.length, pos = len % 3; byte b0 = 0, b1 = 0, b2 = 0; switch (pos) { case 1: b2 = buffer[0]; break; case 2: b1 = buffer[0]; b2 = buffer[1]; break; } StringBuffer sb = new StringBuffer(); int c; boolean notleading = false; do { c = (b0 & 0xFC) >>> 2; if (notleading || c != 0) { sb.append(BASE64_CHARSET[c]); notleading = true; } c = ((b0 & 0x03) << 4) | ((b1 & 0xF0) >>> 4); if (notleading || c != 0) { sb.append(BASE64_CHARSET[c]); notleading = true; } c = ((b1 & 0x0F) << 2) | ((b2 & 0xC0) >>> 6); if (notleading || c != 0) { sb.append(BASE64_CHARSET[c]); notleading = true; } c = b2 & 0x3F; if (notleading || c != 0) { sb.append(BASE64_CHARSET[c]); notleading = true; } if (pos >= len) { break; } else { try { b0 = buffer[pos++]; b1 = buffer[pos++]; b2 = buffer[pos++]; } catch (ArrayIndexOutOfBoundsException x) { break; } } } while (true); if (notleading) { return sb.toString(); } return "0"; } /** *The inverse function of the above.
* *Converts a string representing the encoding of some bytes in Base-64 * to their original form.
* * @param str the Base-64 encoded representation of some byte(s). * @return the bytes represented by thestr
.
* @throws NumberFormatException if str
is null
, or
* str
contains an illegal Base-64 character.
* @see #toBase64(byte[])
*/
public static final byte[] fromBase64(String str) {
int len = str.length();
if (len == 0) {
throw new NumberFormatException("Empty string");
}
byte[] a = new byte[len + 1];
int i, j;
for (i = 0; i < len; i++) {
try {
a[i] = (byte) BASE64_CHARS.indexOf(str.charAt(i));
} catch (ArrayIndexOutOfBoundsException x) {
throw new NumberFormatException("Illegal character at #"+i);
}
}
i = len - 1;
j = len;
try {
while (true) {
a[j] = a[i];
if (--i < 0) {
break;
}
a[j] |= (a[i] & 0x03) << 6;
j--;
a[j] = (byte)((a[i] & 0x3C) >>> 2);
if (--i < 0) {
break;
}
a[j] |= (a[i] & 0x0F) << 4;
j--;
a[j] = (byte)((a[i] & 0x30) >>> 4);
if (--i < 0) {
break;
}
a[j] |= (a[i] << 2);
j--;
a[j] = 0;
if (--i < 0) {
break;
}
}
} catch (Exception ignored) {
}
try { // ignore leading 0-bytes
while(a[j] == 0) {
j++;
}
} catch (Exception x) {
return new byte[1]; // one 0-byte
}
byte[] result = new byte[len - j + 1];
System.arraycopy(a, j, result, 0, len - j + 1);
return result;
}
// BigInteger utilities ----------------------------------------------------
/**
* Treats the input as the MSB representation of a number, and discards * leading zero elements. For efficiency, the input is simply returned if no * leading zeroes are found.
* * @param n the {@link BigInteger} to trim. * @return the byte array representation of the designated {@link BigInteger} * with no leading 0-bytes. */ public static final byte[] trim(BigInteger n) { byte[] in = n.toByteArray(); if (in.length == 0 || in[0] != 0) { return in; } int len = in.length; int i = 1; while (in[i] == 0 && i < len) { ++i; } byte[] result = new byte[len - i]; System.arraycopy(in, i, result, 0, len - i); return result; } /** *Returns a hexadecimal dump of the trimmed bytes of a {@link BigInteger}. *
* * @param x the {@link BigInteger} to display. * @return the string representation of the designated {@link BigInteger}. */ public static final String dump(BigInteger x) { return dumpString(trim(x)); } }