001: /*
002: * @(#)BigInt.java 1.36 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package sun.security.util;
029:
030: import java.math.BigInteger;
031:
032: /**
033: * A low-overhead arbitrary-precision <em>unsigned</em> integer.
034: * This is intended for use with ASN.1 parsing, and printing of
035: * such parsed values. Convert to "BigInteger" if you need to do
036: * arbitrary precision arithmetic, rather than just represent
037: * the number as a wrapped array of bytes.
038: *
039: * <P><em><b>NOTE:</b> This class may eventually disappear, to
040: * be supplanted by big-endian byte arrays which hold both signed
041: * and unsigned arbitrary-precision integers.
042: *
043: * @version 1.28
044: * @author David Brownell
045: */
046: public final class BigInt {
047:
048: // Big endian -- MSB first.
049: private byte[] places;
050:
051: /**
052: * Constructs a "Big" integer from a set of (big-endian) bytes.
053: * Leading zeroes should be stripped off.
054: *
055: * @param data a sequence of bytes, most significant bytes/digits
056: * first. CONSUMED.
057: */
058: public BigInt(byte[] data) {
059: places = (byte[]) data.clone();
060: }
061:
062: /**
063: * Constructs a "Big" integer from a "BigInteger", which must be
064: * positive (or zero) in value.
065: */
066: public BigInt(BigInteger i) {
067: byte[] temp = i.toByteArray();
068:
069: if ((temp[0] & 0x80) != 0)
070: throw new IllegalArgumentException("negative BigInteger");
071:
072: // we assume exactly _one_ sign byte is used...
073:
074: if (temp[0] != 0)
075: places = temp;
076: else {
077: places = new byte[temp.length - 1];
078: for (int j = 1; j < temp.length; j++)
079: places[j - 1] = temp[j];
080: }
081: }
082:
083: /**
084: * Constructs a "Big" integer from a normal Java integer.
085: *
086: * @param i the java primitive integer
087: */
088: public BigInt(int i) {
089: if (i < (1 << 8)) {
090: places = new byte[1];
091: places[0] = (byte) i;
092: } else if (i < (1 << 16)) {
093: places = new byte[2];
094: places[0] = (byte) (i >> 8);
095: places[1] = (byte) i;
096: } else if (i < (1 << 24)) {
097: places = new byte[3];
098: places[0] = (byte) (i >> 16);
099: places[1] = (byte) (i >> 8);
100: places[2] = (byte) i;
101: } else {
102: places = new byte[4];
103: places[0] = (byte) (i >> 24);
104: places[1] = (byte) (i >> 16);
105: places[2] = (byte) (i >> 8);
106: places[3] = (byte) i;
107: }
108: }
109:
110: /**
111: * Converts the "big" integer to a java primitive integer.
112: *
113: * @excpet NumberFormatException if 32 bits is insufficient.
114: */
115: public int toInt() {
116: if (places.length > 4)
117: throw new NumberFormatException("BigInt.toLong, too big");
118: int retval = 0, i = 0;
119: for (; i < places.length; i++)
120: retval = (retval << 8) + ((int) places[i] & 0xff);
121: return retval;
122: }
123:
124: /**
125: * Returns a hexadecimal printed representation. The value is
126: * formatted to fit on lines of at least 75 characters, with
127: * embedded newlines. Words are separated for readability,
128: * with eight words (32 bytes) per line.
129: */
130: public String toString() {
131: return hexify();
132: }
133:
134: /**
135: * Returns a BigInteger value which supports many arithmetic
136: * operations. Assumes negative values will never occur.
137: */
138: public BigInteger toBigInteger() {
139: return new BigInteger(1, places);
140: }
141:
142: /**
143: * Returns the data as a byte array. The most significant bit
144: * of the array is bit zero (as in <code>java.math.BigInteger</code>).
145: */
146: public byte[] toByteArray() {
147: return (byte[]) places.clone();
148: }
149:
150: private static final String digits = "0123456789abcdef";
151:
152: private String hexify() {
153: if (places.length == 0)
154: return " 0 ";
155:
156: StringBuffer buf = new StringBuffer(places.length * 2);
157: buf.append(" "); // four spaces
158: for (int i = 0; i < places.length; i++) {
159: buf.append(digits.charAt((places[i] >> 4) & 0x0f));
160: buf.append(digits.charAt(places[i] & 0x0f));
161: if (((i + 1) % 32) == 0) {
162: if ((i + 1) != places.length)
163: buf.append("\n "); // line after four words
164: } else if (((i + 1) % 4) == 0)
165: buf.append(' '); // space between words
166: }
167: return buf.toString();
168: }
169:
170: /**
171: * Returns true iff the parameter is a numerically equivalent
172: * BigInt.
173: *
174: * @param other the object being compared with this one.
175: */
176: public boolean equals(Object other) {
177: if (other instanceof BigInt)
178: return equals((BigInt) other);
179: return false;
180: }
181:
182: /**
183: * Returns true iff the parameter is numerically equivalent.
184: *
185: * @param other the BigInt being compared with this one.
186: */
187: public boolean equals(BigInt other) {
188: if (this == other)
189: return true;
190:
191: byte[] otherPlaces = other.toByteArray();
192: if (places.length != otherPlaces.length)
193: return false;
194: for (int i = 0; i < places.length; i++)
195: if (places[i] != otherPlaces[i])
196: return false;
197: return true;
198: }
199:
200: /**
201: * Returns a hashcode for this BigInt.
202: *
203: * @return a hashcode for this BigInt.
204: */
205: public int hashCode() {
206: return hexify().hashCode();
207: }
208: }
|