Source for gnu.java.security.util.Util

   1: /* Util.java -- various utility routines.
   2:    Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
   3: 
   4: This file is a part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2 of the License, or (at
   9: your option) any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; if not, write to the Free Software
  18: Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
  19: USA
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version.  */
  37: 
  38: 
  39: package gnu.java.security.util;
  40: 
  41: import gnu.java.lang.CPStringBuilder;
  42: 
  43: import java.math.BigInteger;
  44: 
  45: /**
  46:  * A collection of utility methods used throughout this project.
  47:  */
  48: public class Util
  49: {
  50:   // Hex charset
  51:   private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();
  52: 
  53:   // Base-64 charset
  54:   private static final String BASE64_CHARS =
  55:       "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
  56: 
  57:   private static final char[] BASE64_CHARSET = BASE64_CHARS.toCharArray();
  58: 
  59:   /** Trivial constructor to enforce Singleton pattern. */
  60:   private Util()
  61:   {
  62:     super();
  63:   }
  64: 
  65:   /**
  66:    * Returns a string of hexadecimal digits from a byte array. Each byte is
  67:    * converted to 2 hex symbols; zero(es) included.
  68:    * <p>
  69:    * This method calls the method with same name and three arguments as:
  70:    * <pre>
  71:    * toString(ba, 0, ba.length);
  72:    * </pre>
  73:    *
  74:    * @param ba the byte array to convert.
  75:    * @return a string of hexadecimal characters (two for each byte) representing
  76:    *         the designated input byte array.
  77:    */
  78:   public static String toString(byte[] ba)
  79:   {
  80:     return toString(ba, 0, ba.length);
  81:   }
  82: 
  83:   /**
  84:    * Returns a string of hexadecimal digits from a byte array, starting at
  85:    * <code>offset</code> and consisting of <code>length</code> bytes. Each
  86:    * byte is converted to 2 hex symbols; zero(es) included.
  87:    *
  88:    * @param ba the byte array to convert.
  89:    * @param offset the index from which to start considering the bytes to
  90:    *          convert.
  91:    * @param length the count of bytes, starting from the designated offset to
  92:    *          convert.
  93:    * @return a string of hexadecimal characters (two for each byte) representing
  94:    *         the designated input byte sub-array.
  95:    */
  96:   public static final String toString(byte[] ba, int offset, int length)
  97:   {
  98:     char[] buf = new char[length * 2];
  99:     for (int i = 0, j = 0, k; i < length;)
 100:       {
 101:         k = ba[offset + i++];
 102:         buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F];
 103:         buf[j++] = HEX_DIGITS[ k        & 0x0F];
 104:       }
 105:     return new String(buf);
 106:   }
 107: 
 108:   /**
 109:    * Returns a string of hexadecimal digits from a byte array. Each byte is
 110:    * converted to 2 hex symbols; zero(es) included. The argument is treated as a
 111:    * large little-endian integer and is returned as a large big-endian integer.
 112:    * <p>
 113:    * This method calls the method with same name and three arguments as:
 114:    * <pre>
 115:    * toReversedString(ba, 0, ba.length);
 116:    * </pre>
 117:    *
 118:    * @param ba the byte array to convert.
 119:    * @return a string of hexadecimal characters (two for each byte) representing
 120:    *         the designated input byte array.
 121:    */
 122:   public static String toReversedString(byte[] ba)
 123:   {
 124:     return toReversedString(ba, 0, ba.length);
 125:   }
 126: 
 127:   /**
 128:    * Returns a string of hexadecimal digits from a byte array, starting at
 129:    * <code>offset</code> and consisting of <code>length</code> bytes. Each
 130:    * byte is converted to 2 hex symbols; zero(es) included.
 131:    * <p>
 132:    * The byte array is treated as a large little-endian integer, and is returned
 133:    * as a large big-endian integer.
 134:    *
 135:    * @param ba the byte array to convert.
 136:    * @param offset the index from which to start considering the bytes to
 137:    *          convert.
 138:    * @param length the count of bytes, starting from the designated offset to
 139:    *          convert.
 140:    * @return a string of hexadecimal characters (two for each byte) representing
 141:    *         the designated input byte sub-array.
 142:    */
 143:   public static final String toReversedString(byte[] ba, int offset, int length)
 144:   {
 145:     char[] buf = new char[length * 2];
 146:     for (int i = offset + length - 1, j = 0, k; i >= offset;)
 147:       {
 148:         k = ba[offset + i--];
 149:         buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F];
 150:         buf[j++] = HEX_DIGITS[ k        & 0x0F];
 151:       }
 152:     return new String(buf);
 153:   }
 154: 
 155:   /**
 156:    * <p>
 157:    * Returns a byte array from a string of hexadecimal digits.
 158:    * </p>
 159:    *
 160:    * @param s a string of hexadecimal ASCII characters
 161:    * @return the decoded byte array from the input hexadecimal string.
 162:    */
 163:   public static byte[] toBytesFromString(String s)
 164:   {
 165:     int limit = s.length();
 166:     byte[] result = new byte[((limit + 1) / 2)];
 167:     int i = 0, j = 0;
 168:     if ((limit % 2) == 1)
 169:       result[j++] = (byte) fromDigit(s.charAt(i++));
 170:     while (i < limit)
 171:       {
 172:         result[j  ] = (byte) (fromDigit(s.charAt(i++)) << 4);
 173:         result[j++] |= (byte) fromDigit(s.charAt(i++));
 174:       }
 175:     return result;
 176:   }
 177: 
 178:   /**
 179:    * Returns a byte array from a string of hexadecimal digits, interpreting them
 180:    * as a large big-endian integer and returning it as a large little-endian
 181:    * integer.
 182:    *
 183:    * @param s a string of hexadecimal ASCII characters
 184:    * @return the decoded byte array from the input hexadecimal string.
 185:    */
 186:   public static byte[] toReversedBytesFromString(String s)
 187:   {
 188:     int limit = s.length();
 189:     byte[] result = new byte[((limit + 1) / 2)];
 190:     int i = 0;
 191:     if ((limit % 2) == 1)
 192:       result[i++] = (byte) fromDigit(s.charAt(--limit));
 193:     while (limit > 0)
 194:       {
 195:         result[i  ] = (byte) fromDigit(s.charAt(--limit));
 196:         result[i++] |= (byte) (fromDigit(s.charAt(--limit)) << 4);
 197:       }
 198:     return result;
 199:   }
 200: 
 201:   /**
 202:    * Returns a number from <code>0</code> to <code>15</code> corresponding
 203:    * to the designated hexadecimal digit.
 204:    *
 205:    * @param c a hexadecimal ASCII symbol.
 206:    */
 207:   public static int fromDigit(char c)
 208:   {
 209:     if (c >= '0' && c <= '9')
 210:       return c - '0';
 211:     else if (c >= 'A' && c <= 'F')
 212:       return c - 'A' + 10;
 213:     else if (c >= 'a' && c <= 'f')
 214:       return c - 'a' + 10;
 215:     else
 216:       throw new IllegalArgumentException("Invalid hexadecimal digit: " + c);
 217:   }
 218: 
 219:   /**
 220:    * Returns a string of 8 hexadecimal digits (most significant digit first)
 221:    * corresponding to the unsigned integer <code>n</code>.
 222:    *
 223:    * @param n the unsigned integer to convert.
 224:    * @return a hexadecimal string 8-character long.
 225:    */
 226:   public static String toString(int n)
 227:   {
 228:     char[] buf = new char[8];
 229:     for (int i = 7; i >= 0; i--)
 230:       {
 231:         buf[i] = HEX_DIGITS[n & 0x0F];
 232:         n >>>= 4;
 233:       }
 234:     return new String(buf);
 235:   }
 236: 
 237:   /**
 238:    * Returns a string of hexadecimal digits from an integer array. Each int is
 239:    * converted to 4 hex symbols.
 240:    */
 241:   public static String toString(int[] ia)
 242:   {
 243:     int length = ia.length;
 244:     char[] buf = new char[length * 8];
 245:     for (int i = 0, j = 0, k; i < length; i++)
 246:       {
 247:         k = ia[i];
 248:         buf[j++] = HEX_DIGITS[(k >>> 28) & 0x0F];
 249:         buf[j++] = HEX_DIGITS[(k >>> 24) & 0x0F];
 250:         buf[j++] = HEX_DIGITS[(k >>> 20) & 0x0F];
 251:         buf[j++] = HEX_DIGITS[(k >>> 16) & 0x0F];
 252:         buf[j++] = HEX_DIGITS[(k >>> 12) & 0x0F];
 253:         buf[j++] = HEX_DIGITS[(k >>>  8) & 0x0F];
 254:         buf[j++] = HEX_DIGITS[(k >>>  4) & 0x0F];
 255:         buf[j++] = HEX_DIGITS[ k         & 0x0F];
 256:       }
 257:     return new String(buf);
 258:   }
 259: 
 260:   /**
 261:    * Returns a string of 16 hexadecimal digits (most significant digit first)
 262:    * corresponding to the unsigned long <code>n</code>.
 263:    *
 264:    * @param n the unsigned long to convert.
 265:    * @return a hexadecimal string 16-character long.
 266:    */
 267:   public static String toString(long n)
 268:   {
 269:     char[] b = new char[16];
 270:     for (int i = 15; i >= 0; i--)
 271:       {
 272:         b[i] = HEX_DIGITS[(int)(n & 0x0FL)];
 273:         n >>>= 4;
 274:       }
 275:     return new String(b);
 276:   }
 277: 
 278:   /**
 279:    * Similar to the <code>toString()</code> method except that the Unicode
 280:    * escape character is inserted before every pair of bytes. Useful to
 281:    * externalise byte arrays that will be constructed later from such strings;
 282:    * eg. s-box values.
 283:    *
 284:    * @throws ArrayIndexOutOfBoundsException if the length is odd.
 285:    */
 286:   public static String toUnicodeString(byte[] ba)
 287:   {
 288:     return toUnicodeString(ba, 0, ba.length);
 289:   }
 290: 
 291:   /**
 292:    * Similar to the <code>toString()</code> method except that the Unicode
 293:    * escape character is inserted before every pair of bytes. Useful to
 294:    * externalise byte arrays that will be constructed later from such strings;
 295:    * eg. s-box values.
 296:    *
 297:    * @throws ArrayIndexOutOfBoundsException if the length is odd.
 298:    */
 299:   public static final String toUnicodeString(byte[] ba, int offset, int length)
 300:   {
 301:     CPStringBuilder sb = new CPStringBuilder();
 302:     int i = 0;
 303:     int j = 0;
 304:     int k;
 305:     sb.append('\n').append("\"");
 306:     while (i < length)
 307:       {
 308:         sb.append("\\u");
 309:         k = ba[offset + i++];
 310:         sb.append(HEX_DIGITS[(k >>> 4) & 0x0F]);
 311:         sb.append(HEX_DIGITS[ k        & 0x0F]);
 312:         k = ba[offset + i++];
 313:         sb.append(HEX_DIGITS[(k >>> 4) & 0x0F]);
 314:         sb.append(HEX_DIGITS[ k        & 0x0F]);
 315:         if ((++j % 8) == 0)
 316:           sb.append("\"+").append('\n').append("\"");
 317:       }
 318:     sb.append("\"").append('\n');
 319:     return sb.toString();
 320:   }
 321: 
 322:   /**
 323:    * Similar to the <code>toString()</code> method except that the Unicode
 324:    * escape character is inserted before every pair of bytes. Useful to
 325:    * externalise integer arrays that will be constructed later from such
 326:    * strings; eg. s-box values.
 327:    *
 328:    * @throws ArrayIndexOutOfBoundsException if the length is not a multiple of
 329:    *           4.
 330:    */
 331:   public static String toUnicodeString(int[] ia)
 332:   {
 333:     CPStringBuilder sb = new CPStringBuilder();
 334:     int i = 0;
 335:     int j = 0;
 336:     int k;
 337:     sb.append('\n').append("\"");
 338:     while (i < ia.length)
 339:       {
 340:         k = ia[i++];
 341:         sb.append("\\u");
 342:         sb.append(HEX_DIGITS[(k >>> 28) & 0x0F]);
 343:         sb.append(HEX_DIGITS[(k >>> 24) & 0x0F]);
 344:         sb.append(HEX_DIGITS[(k >>> 20) & 0x0F]);
 345:         sb.append(HEX_DIGITS[(k >>> 16) & 0x0F]);
 346:         sb.append("\\u");
 347:         sb.append(HEX_DIGITS[(k >>> 12) & 0x0F]);
 348:         sb.append(HEX_DIGITS[(k >>>  8) & 0x0F]);
 349:         sb.append(HEX_DIGITS[(k >>>  4) & 0x0F]);
 350:         sb.append(HEX_DIGITS[ k         & 0x0F]);
 351:         if ((++j % 4) == 0)
 352:           sb.append("\"+").append('\n').append("\"");
 353:       }
 354:     sb.append("\"").append('\n');
 355:     return sb.toString();
 356:   }
 357: 
 358:   public static byte[] toBytesFromUnicode(String s)
 359:   {
 360:     int limit = s.length() * 2;
 361:     byte[] result = new byte[limit];
 362:     char c;
 363:     for (int i = 0; i < limit; i++)
 364:       {
 365:         c = s.charAt(i >>> 1);
 366:         result[i] = (byte)(((i & 1) == 0) ? c >>> 8 : c);
 367:       }
 368:     return result;
 369:   }
 370: 
 371:   /**
 372:    * Dumps a byte array as a string, in a format that is easy to read for
 373:    * debugging. The string <code>m</code> is prepended to the start of each
 374:    * line.
 375:    * <p>
 376:    * If <code>offset</code> and <code>length</code> are omitted, the whole
 377:    * array is used. If <code>m</code> is omitted, nothing is prepended to each
 378:    * line.
 379:    *
 380:    * @param data the byte array to be dumped.
 381:    * @param offset the offset within <i>data</i> to start from.
 382:    * @param length the number of bytes to dump.
 383:    * @param m a string to be prepended to each line.
 384:    * @return a string containing the result.
 385:    */
 386:   public static String dumpString(byte[] data, int offset, int length, String m)
 387:   {
 388:     if (data == null)
 389:       return m + "null\n";
 390:     CPStringBuilder sb = new CPStringBuilder(length * 3);
 391:     if (length > 32)
 392:       sb.append(m).append("Hexadecimal dump of ")
 393:           .append(length).append(" bytes...\n");
 394:     // each line will list 32 bytes in 4 groups of 8 each
 395:     int end = offset + length;
 396:     String s;
 397:     int l = Integer.toString(length).length();
 398:     if (l < 4)
 399:       l = 4;
 400:     for (; offset < end; offset += 32)
 401:       {
 402:         if (length > 32)
 403:           {
 404:             s = "         " + offset;
 405:             sb.append(m).append(s.substring(s.length() - l)).append(": ");
 406:           }
 407:         int i = 0;
 408:         for (; i < 32 && offset + i + 7 < end; i += 8)
 409:           sb.append(toString(data, offset + i, 8)).append(' ');
 410:         if (i < 32)
 411:           for (; i < 32 && offset + i < end; i++)
 412:             sb.append(byteToString(data[offset + i]));
 413:         sb.append('\n');
 414:       }
 415:     return sb.toString();
 416:   }
 417: 
 418:   public static String dumpString(byte[] data)
 419:   {
 420:     return (data == null) ? "null\n" : dumpString(data, 0, data.length, "");
 421:   }
 422: 
 423:   public static String dumpString(byte[] data, String m)
 424:   {
 425:     return (data == null) ? "null\n" : dumpString(data, 0, data.length, m);
 426:   }
 427: 
 428:   public static String dumpString(byte[] data, int offset, int length)
 429:   {
 430:     return dumpString(data, offset, length, "");
 431:   }
 432: 
 433:   /**
 434:    * Returns a string of 2 hexadecimal digits (most significant digit first)
 435:    * corresponding to the lowest 8 bits of <code>n</code>.
 436:    *
 437:    * @param n the byte value to convert.
 438:    * @return a string of 2 hex characters representing the input.
 439:    */
 440:   public static String byteToString(int n)
 441:   {
 442:     char[] buf = { HEX_DIGITS[(n >>> 4) & 0x0F], HEX_DIGITS[n & 0x0F] };
 443:     return new String(buf);
 444:   }
 445: 
 446:   /**
 447:    * Converts a designated byte array to a Base-64 representation, with the
 448:    * exceptions that (a) leading 0-byte(s) are ignored, and (b) the character
 449:    * '.' (dot) shall be used instead of "+' (plus).
 450:    * <p>
 451:    * Used by SASL password file manipulation primitives.
 452:    *
 453:    * @param buffer an arbitrary sequence of bytes to represent in Base-64.
 454:    * @return unpadded (without the '=' character(s)) Base-64 representation of
 455:    *         the input.
 456:    */
 457:   public static final String toBase64(byte[] buffer)
 458:   {
 459:     int len = buffer.length, pos = len % 3;
 460:     byte b0 = 0, b1 = 0, b2 = 0;
 461:     switch (pos)
 462:       {
 463:       case 1:
 464:         b2 = buffer[0];
 465:         break;
 466:       case 2:
 467:         b1 = buffer[0];
 468:         b2 = buffer[1];
 469:         break;
 470:       }
 471:     CPStringBuilder sb = new CPStringBuilder();
 472:     int c;
 473:     boolean notleading = false;
 474:     do
 475:       {
 476:         c = (b0 & 0xFC) >>> 2;
 477:         if (notleading || c != 0)
 478:           {
 479:             sb.append(BASE64_CHARSET[c]);
 480:             notleading = true;
 481:           }
 482:         c = ((b0 & 0x03) << 4) | ((b1 & 0xF0) >>> 4);
 483:         if (notleading || c != 0)
 484:           {
 485:             sb.append(BASE64_CHARSET[c]);
 486:             notleading = true;
 487:           }
 488:         c = ((b1 & 0x0F) << 2) | ((b2 & 0xC0) >>> 6);
 489:         if (notleading || c != 0)
 490:           {
 491:             sb.append(BASE64_CHARSET[c]);
 492:             notleading = true;
 493:           }
 494:         c = b2 & 0x3F;
 495:         if (notleading || c != 0)
 496:           {
 497:             sb.append(BASE64_CHARSET[c]);
 498:             notleading = true;
 499:           }
 500:         if (pos >= len)
 501:           break;
 502:         else
 503:           {
 504:             try
 505:               {
 506:                 b0 = buffer[pos++];
 507:                 b1 = buffer[pos++];
 508:                 b2 = buffer[pos++];
 509:               }
 510:             catch (ArrayIndexOutOfBoundsException x)
 511:               {
 512:                 break;
 513:               }
 514:           }
 515:       }
 516:     while (true);
 517: 
 518:     if (notleading)
 519:       return sb.toString();
 520:     return "0";
 521:   }
 522: 
 523:   /**
 524:    * The inverse function of the above.
 525:    * <p>
 526:    * Converts a string representing the encoding of some bytes in Base-64 to
 527:    * their original form.
 528:    *
 529:    * @param str the Base-64 encoded representation of some byte(s).
 530:    * @return the bytes represented by the <code>str</code>.
 531:    * @throws NumberFormatException if <code>str</code> is <code>null</code>,
 532:    *           or <code>str</code> contains an illegal Base-64 character.
 533:    * @see #toBase64(byte[])
 534:    */
 535:   public static final byte[] fromBase64(String str)
 536:   {
 537:     int len = str.length();
 538:     if (len == 0)
 539:       throw new NumberFormatException("Empty string");
 540:     byte[] a = new byte[len + 1];
 541:     int i, j;
 542:     for (i = 0; i < len; i++)
 543:       try
 544:         {
 545:           a[i] = (byte) BASE64_CHARS.indexOf(str.charAt(i));
 546:         }
 547:       catch (ArrayIndexOutOfBoundsException x)
 548:         {
 549:           throw new NumberFormatException("Illegal character at #" + i);
 550:         }
 551:     i = len - 1;
 552:     j = len;
 553:     try
 554:       {
 555:         while (true)
 556:           {
 557:             a[j] = a[i];
 558:             if (--i < 0)
 559:               break;
 560:             a[j] |= (a[i] & 0x03) << 6;
 561:             j--;
 562:             a[j] = (byte)((a[i] & 0x3C) >>> 2);
 563:             if (--i < 0)
 564:               break;
 565:             a[j] |= (a[i] & 0x0F) << 4;
 566:             j--;
 567:             a[j] = (byte)((a[i] & 0x30) >>> 4);
 568:             if (--i < 0)
 569:               break;
 570:             a[j] |= (a[i] << 2);
 571:             j--;
 572:             a[j] = 0;
 573:             if (--i < 0)
 574:               break;
 575:           }
 576:       }
 577:     catch (Exception ignored)
 578:       {
 579:       }
 580:     try
 581:       { // ignore leading 0-bytes
 582:         while (a[j] == 0)
 583:           j++;
 584:       }
 585:     catch (Exception x)
 586:       {
 587:         return new byte[1]; // one 0-byte
 588:       }
 589:     byte[] result = new byte[len - j + 1];
 590:     System.arraycopy(a, j, result, 0, len - j + 1);
 591:     return result;
 592:   }
 593: 
 594:   // BigInteger utilities ----------------------------------------------------
 595: 
 596:   /**
 597:    * Treats the input as the MSB representation of a number, and discards
 598:    * leading zero elements. For efficiency, the input is simply returned if no
 599:    * leading zeroes are found.
 600:    *
 601:    * @param n the {@link BigInteger} to trim.
 602:    * @return the byte array representation of the designated {@link BigInteger}
 603:    *         with no leading 0-bytes.
 604:    */
 605:   public static final byte[] trim(BigInteger n)
 606:   {
 607:     byte[] in = n.toByteArray();
 608:     if (in.length == 0 || in[0] != 0)
 609:       return in;
 610:     int len = in.length;
 611:     int i = 1;
 612:     while (in[i] == 0 && i < len)
 613:       ++i;
 614:     byte[] result = new byte[len - i];
 615:     System.arraycopy(in, i, result, 0, len - i);
 616:     return result;
 617:   }
 618: 
 619:   /**
 620:    * Returns a hexadecimal dump of the trimmed bytes of a {@link BigInteger}.
 621:    *
 622:    * @param x the {@link BigInteger} to display.
 623:    * @return the string representation of the designated {@link BigInteger}.
 624:    */
 625:   public static final String dump(BigInteger x)
 626:   {
 627:     return dumpString(trim(x));
 628:   }
 629: }