blob: 159c917f1d0e75ffc92d884c564af4cde179f3f3 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1996-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.security.util;
27
28import 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 */
44public 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}