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 } |
|