jdk/src/share/classes/sun/security/util/BigInt.java
changeset 10822 0294e016d9b1
parent 10821 5ec6698ec5a9
parent 10808 882388c78d4e
child 10823 86db042b3385
equal deleted inserted replaced
10821:5ec6698ec5a9 10822:0294e016d9b1
     1 /*
       
     2  * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package sun.security.util;
       
    27 
       
    28 import java.math.BigInteger;
       
    29 
       
    30 
       
    31 /**
       
    32  * A low-overhead arbitrary-precision <em>unsigned</em> integer.
       
    33  * This is intended for use with ASN.1 parsing, and printing of
       
    34  * such parsed values.  Convert to "BigInteger" if you need to do
       
    35  * arbitrary precision arithmetic, rather than just represent
       
    36  * the number as a wrapped array of bytes.
       
    37  *
       
    38  * <P><em><b>NOTE:</b>  This class may eventually disappear, to
       
    39  * be supplanted by big-endian byte arrays which hold both signed
       
    40  * and unsigned arbitrary-precision integers.</em>
       
    41  *
       
    42  * @author David Brownell
       
    43  */
       
    44 public final class BigInt {
       
    45 
       
    46     // Big endian -- MSB first.
       
    47     private byte[]      places;
       
    48 
       
    49     /**
       
    50      * Constructs a "Big" integer from a set of (big-endian) bytes.
       
    51      * Leading zeroes should be stripped off.
       
    52      *
       
    53      * @param data a sequence of bytes, most significant bytes/digits
       
    54      *          first.  CONSUMED.
       
    55      */
       
    56     public BigInt(byte[] data) { places = data.clone(); }
       
    57 
       
    58     /**
       
    59      * Constructs a "Big" integer from a "BigInteger", which must be
       
    60      * positive (or zero) in value.
       
    61      */
       
    62     public BigInt(BigInteger i) {
       
    63         byte[]  temp = i.toByteArray();
       
    64 
       
    65         if ((temp[0] & 0x80) != 0)
       
    66             throw new IllegalArgumentException("negative BigInteger");
       
    67 
       
    68         // XXX we assume exactly _one_ sign byte is used...
       
    69 
       
    70         if (temp[0] != 0)
       
    71             places = temp;
       
    72         else {
       
    73             places = new byte[temp.length - 1];
       
    74             for (int j = 1; j < temp.length; j++)
       
    75                 places[j - 1] = temp[j];
       
    76         }
       
    77     }
       
    78 
       
    79     /**
       
    80      * Constructs a "Big" integer from a normal Java integer.
       
    81      *
       
    82      * @param i the java primitive integer
       
    83      */
       
    84     public BigInt(int i) {
       
    85         if (i < (1 << 8)) {
       
    86             places = new byte[1];
       
    87             places[0] = (byte) i;
       
    88         } else if (i < (1 << 16)) {
       
    89             places = new byte[2];
       
    90             places[0] = (byte) (i >> 8);
       
    91             places[1] = (byte) i;
       
    92         } else if (i < (1 << 24)) {
       
    93             places = new byte[3];
       
    94             places[0] = (byte) (i >> 16);
       
    95             places[1] = (byte) (i >> 8);
       
    96             places[2] = (byte) i;
       
    97         } else {
       
    98             places = new byte[4];
       
    99             places[0] = (byte) (i >> 24);
       
   100             places[1] = (byte) (i >> 16);
       
   101             places[2] = (byte) (i >> 8);
       
   102             places[3] = (byte) i;
       
   103         }
       
   104     }
       
   105 
       
   106     /**
       
   107      * Converts the "big" integer to a java primitive integer.
       
   108      *
       
   109      * @excpet NumberFormatException if 32 bits is insufficient.
       
   110      */
       
   111     public int toInt() {
       
   112         if (places.length > 4)
       
   113             throw new NumberFormatException("BigInt.toLong, too big");
       
   114         int retval = 0, i = 0;
       
   115         for (; i < places.length; i++)
       
   116             retval = (retval << 8) + ((int)places[i] & 0xff);
       
   117         return retval;
       
   118     }
       
   119 
       
   120     /**
       
   121      * Returns a hexadecimal printed representation.  The value is
       
   122      * formatted to fit on lines of at least 75 characters, with
       
   123      * embedded newlines.  Words are separated for readability,
       
   124      * with eight words (32 bytes) per line.
       
   125      */
       
   126     public String toString() { return hexify(); }
       
   127 
       
   128     /**
       
   129      * Returns a BigInteger value which supports many arithmetic
       
   130      * operations. Assumes negative values will never occur.
       
   131      */
       
   132     public BigInteger toBigInteger()
       
   133         { return new BigInteger(1, places); }
       
   134 
       
   135     /**
       
   136      * Returns the data as a byte array.  The most significant bit
       
   137      * of the array is bit zero (as in <code>java.math.BigInteger</code>).
       
   138      */
       
   139     public byte[] toByteArray() { return places.clone(); }
       
   140 
       
   141     private static final String digits = "0123456789abcdef";
       
   142     private String hexify() {
       
   143         if (places.length == 0)
       
   144             return "  0  ";
       
   145 
       
   146         StringBuffer buf = new StringBuffer(places.length * 2);
       
   147         buf.append("    ");     // four spaces
       
   148         for (int i = 0; i < places.length; i++) {
       
   149             buf.append(digits.charAt((places[i] >> 4) & 0x0f));
       
   150             buf.append(digits.charAt(places[i] & 0x0f));
       
   151             if (((i + 1) % 32) == 0) {
       
   152                 if ((i +  1) != places.length)
       
   153                     buf.append("\n    ");       // line after four words
       
   154             } else if (((i + 1) % 4) == 0)
       
   155                 buf.append(' ');                // space between words
       
   156         }
       
   157         return buf.toString();
       
   158     }
       
   159 
       
   160     /**
       
   161      * Returns true iff the parameter is a numerically equivalent
       
   162      * BigInt.
       
   163      *
       
   164      * @param other the object being compared with this one.
       
   165      */
       
   166     public boolean equals(Object other) {
       
   167         if (other instanceof BigInt)
       
   168             return equals((BigInt) other);
       
   169         return false;
       
   170     }
       
   171 
       
   172     /**
       
   173      * Returns true iff the parameter is numerically equivalent.
       
   174      *
       
   175      * @param other the BigInt being compared with this one.
       
   176      */
       
   177     public boolean equals(BigInt other) {
       
   178         if (this == other)
       
   179             return true;
       
   180 
       
   181         byte[] otherPlaces = other.toByteArray();
       
   182         if (places.length != otherPlaces.length)
       
   183             return false;
       
   184         for (int i = 0; i < places.length; i++)
       
   185             if (places[i] != otherPlaces[i])
       
   186                 return false;
       
   187         return true;
       
   188     }
       
   189 
       
   190     /**
       
   191      * Returns a hashcode for this BigInt.
       
   192      *
       
   193      * @return a hashcode for this BigInt.
       
   194      */
       
   195     public int hashCode() {
       
   196         return hexify().hashCode();
       
   197     }
       
   198 }