UNPKG

6.93 kBJavaScriptView Raw
1/*! OpenPGP.js v5.0.0-1 - 2021-03-03 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */
2const globalThis = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
3
4import bn from './bn.mjs';
5import './openpgp.mjs';
6
7/**
8 * @fileoverview
9 * BigInteger implementation of basic operations
10 * Wrapper of bn.js library (wwww.github.com/indutny/bn.js)
11 * @module biginteger/bn
12 * @private
13 */
14
15/**
16 * @private
17 */
18class BigInteger {
19 /**
20 * Get a BigInteger (input must be big endian for strings and arrays)
21 * @param {Number|String|Uint8Array} n - Value to convert
22 * @throws {Error} on undefined input
23 */
24 constructor(n) {
25 if (n === undefined) {
26 throw new Error('Invalid BigInteger input');
27 }
28
29 this.value = new bn(n);
30 }
31
32 clone() {
33 const clone = new BigInteger(null);
34 this.value.copy(clone.value);
35 return clone;
36 }
37
38 /**
39 * BigInteger increment in place
40 */
41 iinc() {
42 this.value.iadd(new bn(1));
43 return this;
44 }
45
46 /**
47 * BigInteger increment
48 * @returns {BigInteger} this + 1.
49 */
50 inc() {
51 return this.clone().iinc();
52 }
53
54 /**
55 * BigInteger decrement in place
56 */
57 idec() {
58 this.value.isub(new bn(1));
59 return this;
60 }
61
62 /**
63 * BigInteger decrement
64 * @returns {BigInteger} this - 1.
65 */
66 dec() {
67 return this.clone().idec();
68 }
69
70
71 /**
72 * BigInteger addition in place
73 * @param {BigInteger} x - Value to add
74 */
75 iadd(x) {
76 this.value.iadd(x.value);
77 return this;
78 }
79
80 /**
81 * BigInteger addition
82 * @param {BigInteger} x - Value to add
83 * @returns {BigInteger} this + x.
84 */
85 add(x) {
86 return this.clone().iadd(x);
87 }
88
89 /**
90 * BigInteger subtraction in place
91 * @param {BigInteger} x - Value to subtract
92 */
93 isub(x) {
94 this.value.isub(x.value);
95 return this;
96 }
97
98 /**
99 * BigInteger subtraction
100 * @param {BigInteger} x - Value to subtract
101 * @returns {BigInteger} this - x.
102 */
103 sub(x) {
104 return this.clone().isub(x);
105 }
106
107 /**
108 * BigInteger multiplication in place
109 * @param {BigInteger} x - Value to multiply
110 */
111 imul(x) {
112 this.value.imul(x.value);
113 return this;
114 }
115
116 /**
117 * BigInteger multiplication
118 * @param {BigInteger} x - Value to multiply
119 * @returns {BigInteger} this * x.
120 */
121 mul(x) {
122 return this.clone().imul(x);
123 }
124
125 /**
126 * Compute value modulo m, in place
127 * @param {BigInteger} m - Modulo
128 */
129 imod(m) {
130 this.value = this.value.umod(m.value);
131 return this;
132 }
133
134 /**
135 * Compute value modulo m
136 * @param {BigInteger} m - Modulo
137 * @returns {BigInteger} this mod m.
138 */
139 mod(m) {
140 return this.clone().imod(m);
141 }
142
143 /**
144 * Compute modular exponentiation
145 * Much faster than this.exp(e).mod(n)
146 * @param {BigInteger} e - Exponent
147 * @param {BigInteger} n - Modulo
148 * @returns {BigInteger} this ** e mod n.
149 */
150 modExp(e, n) {
151 // We use either Montgomery or normal reduction context
152 // Montgomery requires coprime n and R (montogmery multiplier)
153 // bn.js picks R as power of 2, so n must be odd
154 const nred = n.isEven() ? bn.red(n.value) : bn.mont(n.value);
155 const x = this.clone();
156 x.value = x.value.toRed(nred).redPow(e.value).fromRed();
157 return x;
158 }
159
160 /**
161 * Compute the inverse of this value modulo n
162 * Note: this and and n must be relatively prime
163 * @param {BigInteger} n - Modulo
164 * @returns {BigInteger} x such that this*x = 1 mod n
165 * @throws {Error} if the inverse does not exist
166 */
167 modInv(n) {
168 // invm returns a wrong result if the inverse does not exist
169 if (!this.gcd(n).isOne()) {
170 throw new Error('Inverse does not exist');
171 }
172 return new BigInteger(this.value.invm(n.value));
173 }
174
175 /**
176 * Compute greatest common divisor between this and n
177 * @param {BigInteger} n - Operand
178 * @returns {BigInteger} gcd
179 */
180 gcd(n) {
181 return new BigInteger(this.value.gcd(n.value));
182 }
183
184 /**
185 * Shift this to the left by x, in place
186 * @param {BigInteger} x - Shift value
187 */
188 ileftShift(x) {
189 this.value.ishln(x.value.toNumber());
190 return this;
191 }
192
193 /**
194 * Shift this to the left by x
195 * @param {BigInteger} x - Shift value
196 * @returns {BigInteger} this << x.
197 */
198 leftShift(x) {
199 return this.clone().ileftShift(x);
200 }
201
202 /**
203 * Shift this to the right by x, in place
204 * @param {BigInteger} x - Shift value
205 */
206 irightShift(x) {
207 this.value.ishrn(x.value.toNumber());
208 return this;
209 }
210
211 /**
212 * Shift this to the right by x
213 * @param {BigInteger} x - Shift value
214 * @returns {BigInteger} this >> x.
215 */
216 rightShift(x) {
217 return this.clone().irightShift(x);
218 }
219
220 /**
221 * Whether this value is equal to x
222 * @param {BigInteger} x
223 * @returns {Boolean}
224 */
225 equal(x) {
226 return this.value.eq(x.value);
227 }
228
229 /**
230 * Whether this value is less than x
231 * @param {BigInteger} x
232 * @returns {Boolean}
233 */
234 lt(x) {
235 return this.value.lt(x.value);
236 }
237
238 /**
239 * Whether this value is less than or equal to x
240 * @param {BigInteger} x
241 * @returns {Boolean}
242 */
243 lte(x) {
244 return this.value.lte(x.value);
245 }
246
247 /**
248 * Whether this value is greater than x
249 * @param {BigInteger} x
250 * @returns {Boolean}
251 */
252 gt(x) {
253 return this.value.gt(x.value);
254 }
255
256 /**
257 * Whether this value is greater than or equal to x
258 * @param {BigInteger} x
259 * @returns {Boolean}
260 */
261 gte(x) {
262 return this.value.gte(x.value);
263 }
264
265 isZero() {
266 return this.value.isZero();
267 }
268
269 isOne() {
270 return this.value.eq(new bn(1));
271 }
272
273 isNegative() {
274 return this.value.isNeg();
275 }
276
277 isEven() {
278 return this.value.isEven();
279 }
280
281 abs() {
282 const res = this.clone();
283 res.value = res.value.abs();
284 return res;
285 }
286
287 /**
288 * Get this value as a string
289 * @returns {String} this value.
290 */
291 toString() {
292 return this.value.toString();
293 }
294
295 /**
296 * Get this value as an exact Number (max 53 bits)
297 * Fails if this value is too large
298 * @returns {Number}
299 */
300 toNumber() {
301 return this.value.toNumber();
302 }
303
304 /**
305 * Get value of i-th bit
306 * @param {Number} i - Bit index
307 * @returns {Number} Bit value.
308 */
309 getBit(i) {
310 return this.value.testn(i) ? 1 : 0;
311 }
312
313 /**
314 * Compute bit length
315 * @returns {Number} Bit length.
316 */
317 bitLength() {
318 return this.value.bitLength();
319 }
320
321 /**
322 * Compute byte length
323 * @returns {Number} Byte length.
324 */
325 byteLength() {
326 return this.value.byteLength();
327 }
328
329 /**
330 * Get Uint8Array representation of this number
331 * @param {String} endian - Endianess of output array (defaults to 'be')
332 * @param {Number} length - Of output array
333 * @returns {Uint8Array}
334 */
335 toUint8Array(endian = 'be', length) {
336 return this.value.toArrayLike(Uint8Array, endian, length);
337 }
338}
339
340export default BigInteger;