Tag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
/* LibTomMath, multiple-precision integer library -- Tom St Denis
*
* LibTomMath is library that provides for multiple-precision
* integer arithmetic as well as number theoretic functionality.
*
* The library is designed directly after the MPI library by
* Michael Fromberger but has been written from scratch with
* additional optimizations in place.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
*/
#include <tommath.h>
/* chars used in radix conversions */
static const char *s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
/* read a string [ASCII] in a given radix */
int
mp_read_radix (mp_int * a, char *str, int radix)
{
int y, res, neg;
char ch;
if (radix < 2 || radix > 64) {
return MP_VAL;
}
if (*str == '-') {
++str;
neg = MP_NEG;
} else {
neg = MP_ZPOS;
}
mp_zero (a);
while (*str) {
ch = (char) ((radix < 36) ? toupper (*str) : *str);
for (y = 0; y < 64; y++) {
if (ch == s_rmap[y]) {
break;
}
}
if (y < radix) {
if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
return res;
}
if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
return res;
}
} else {
break;
}
++str;
}
a->sign = neg;
return MP_OKAY;
}
/* stores a bignum as a ASCII string in a given radix (2..64) */
int
mp_toradix (mp_int * a, char *str, int radix)
{
int res, digs;
mp_int t;
mp_digit d;
char *_s = str;
if (radix < 2 || radix > 64) {
return MP_VAL;
}
if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
return res;
}
if (t.sign == MP_NEG) {
++_s;
*str++ = '-';
t.sign = MP_ZPOS;
}
digs = 0;
while (mp_iszero (&t) == 0) {
if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
mp_clear (&t);
return res;
}
*str++ = s_rmap[d];
++digs;
}
bn_reverse ((unsigned char *) _s, digs);
*str++ = '\0';
mp_clear (&t);
return MP_OKAY;
}
/* returns size of ASCII reprensentation */
int
mp_radix_size (mp_int * a, int radix)
{
int res, digs;
mp_int t;
mp_digit d;
/* special case for binary */
if (radix == 2) {
return mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
}
if (radix < 2 || radix > 64) {
return 0;
}
if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
return 0;
}
digs = 0;
if (t.sign == MP_NEG) {
++digs;
t.sign = MP_ZPOS;
}
while (mp_iszero (&t) == 0) {
if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
mp_clear (&t);
return 0;
}
++digs;
}
mp_clear (&t);
return digs + 1;
}