Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | ***** BEGIN LICENSE BLOCK ***** |
michael@0 | 2 | Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
michael@0 | 3 | |
michael@0 | 4 | The contents of this file are subject to the Mozilla Public License Version |
michael@0 | 5 | 1.1 (the "License"); you may not use this file except in compliance with |
michael@0 | 6 | the License. You may obtain a copy of the License at |
michael@0 | 7 | http://www.mozilla.org/MPL/ |
michael@0 | 8 | |
michael@0 | 9 | Software distributed under the License is distributed on an "AS IS" basis, |
michael@0 | 10 | WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
michael@0 | 11 | for the specific language governing rights and limitations under the |
michael@0 | 12 | License. |
michael@0 | 13 | |
michael@0 | 14 | The Original Code is the MPI Arbitrary Precision Integer Arithmetic |
michael@0 | 15 | library. |
michael@0 | 16 | |
michael@0 | 17 | The Initial Developer of the Original Code is |
michael@0 | 18 | Michael J. Fromberger <sting@linguist.dartmouth.edu> |
michael@0 | 19 | Portions created by the Initial Developer are Copyright (C) 1997-2000 |
michael@0 | 20 | the Initial Developer. All Rights Reserved. |
michael@0 | 21 | |
michael@0 | 22 | Contributor(s): |
michael@0 | 23 | |
michael@0 | 24 | Alternatively, the contents of this file may be used under the terms of |
michael@0 | 25 | either the GNU General Public License Version 2 or later (the "GPL"), or |
michael@0 | 26 | the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
michael@0 | 27 | in which case the provisions of the GPL or the LGPL are applicable instead |
michael@0 | 28 | of those above. If you wish to allow use of your version of this file only |
michael@0 | 29 | under the terms of either the GPL or the LGPL, and not to allow others to |
michael@0 | 30 | use your version of this file under the terms of the MPL, indicate your |
michael@0 | 31 | decision by deleting the provisions above and replace them with the notice |
michael@0 | 32 | and other provisions required by the GPL or the LGPL. If you do not delete |
michael@0 | 33 | the provisions above, a recipient may use your version of this file under |
michael@0 | 34 | the terms of any one of the MPL, the GPL or the LGPL. |
michael@0 | 35 | |
michael@0 | 36 | ***** END LICENSE BLOCK ***** |
michael@0 | 37 | |
michael@0 | 38 | About the MPI Library |
michael@0 | 39 | --------------------- |
michael@0 | 40 | |
michael@0 | 41 | The files 'mpi.h' and 'mpi.c' define a simple, arbitrary precision |
michael@0 | 42 | signed integer arithmetic package. The implementation is not the most |
michael@0 | 43 | efficient possible, but the code is small and should be fairly easily |
michael@0 | 44 | portable to just about any machine that supports an ANSI C compiler, |
michael@0 | 45 | as long as it is capable of at least 16-bit arithmetic (but also see |
michael@0 | 46 | below for more on this). |
michael@0 | 47 | |
michael@0 | 48 | This library was written with an eye to cryptographic applications; |
michael@0 | 49 | thus, some care is taken to make sure that temporary values are not |
michael@0 | 50 | left lying around in memory when they are no longer in use. This adds |
michael@0 | 51 | some overhead for zeroing buffers before they are released back into |
michael@0 | 52 | the free pool; however, it gives you the assurance that there is only |
michael@0 | 53 | one copy of your important values residing in your process's address |
michael@0 | 54 | space at a time. Obviously, it is difficult to guarantee anything, in |
michael@0 | 55 | a pre-emptive multitasking environment, but this at least helps you |
michael@0 | 56 | keep a lid on the more obvious ways your data can get spread around in |
michael@0 | 57 | memory. |
michael@0 | 58 | |
michael@0 | 59 | |
michael@0 | 60 | Using the Library |
michael@0 | 61 | ----------------- |
michael@0 | 62 | |
michael@0 | 63 | To use the MPI library in your program, you must include the header: |
michael@0 | 64 | |
michael@0 | 65 | #include "mpi.h" |
michael@0 | 66 | |
michael@0 | 67 | This header provides all the type and function declarations you'll |
michael@0 | 68 | need to use the library. Almost all the names defined by the library |
michael@0 | 69 | begin with the prefix 'mp_', so it should be easy to keep them from |
michael@0 | 70 | clashing with your program's namespace (he says, glibly, knowing full |
michael@0 | 71 | well there are always pathological cases). |
michael@0 | 72 | |
michael@0 | 73 | There are a few things you may want to configure about the library. |
michael@0 | 74 | By default, the MPI library uses an unsigned short for its digit type, |
michael@0 | 75 | and an unsigned int for its word type. The word type must be big |
michael@0 | 76 | enough to contain at least two digits, for the primitive arithmetic to |
michael@0 | 77 | work out. On my machine, a short is 2 bytes and an int is 4 bytes -- |
michael@0 | 78 | but if you have 64-bit ints, you might want to use a 4-byte digit and |
michael@0 | 79 | an 8-byte word. I have tested the library using 1-byte digits and |
michael@0 | 80 | 2-byte words, as well. Whatever you choose to do, the things you need |
michael@0 | 81 | to change are: |
michael@0 | 82 | |
michael@0 | 83 | (1) The type definitions for mp_digit and mp_word. |
michael@0 | 84 | |
michael@0 | 85 | (2) The macro DIGIT_FMT which tells mp_print() how to display a |
michael@0 | 86 | single digit. This is just a printf() format string, so you |
michael@0 | 87 | can adjust it appropriately. |
michael@0 | 88 | |
michael@0 | 89 | (3) The macros DIGIT_MAX and MP_WORD_MAX, which specify the |
michael@0 | 90 | largest value expressible in an mp_digit and an mp_word, |
michael@0 | 91 | respectively. |
michael@0 | 92 | |
michael@0 | 93 | Both the mp_digit and mp_word should be UNSIGNED integer types. The |
michael@0 | 94 | code relies on having the full positive precision of the type used for |
michael@0 | 95 | digits and words. |
michael@0 | 96 | |
michael@0 | 97 | The remaining type definitions should be left alone, for the most |
michael@0 | 98 | part. The code in the library does not make any significant |
michael@0 | 99 | assumptions about the sizes of things, but there is little if any |
michael@0 | 100 | reason to change the other parameters, so I would recommend you leave |
michael@0 | 101 | them as you found them. |
michael@0 | 102 | |
michael@0 | 103 | The library comes with a Perl script, 'types.pl', which will scan your |
michael@0 | 104 | current Makefile settings, and attempt to find good definitions for |
michael@0 | 105 | these types. It relies on a Unix sort of build environment, so it |
michael@0 | 106 | probably won't work under MacOS or Windows, but it can be convenient |
michael@0 | 107 | if you're porting to a new flavour of Unix. Just run 'types.pl' at |
michael@0 | 108 | the command line, and it will spit out its results to the standard |
michael@0 | 109 | output. |
michael@0 | 110 | |
michael@0 | 111 | |
michael@0 | 112 | Conventions |
michael@0 | 113 | ----------- |
michael@0 | 114 | |
michael@0 | 115 | Most functions in the library return a value of type mp_err. This |
michael@0 | 116 | permits the library to communicate success or various kinds of failure |
michael@0 | 117 | to the calling program. The return values currently defined are: |
michael@0 | 118 | |
michael@0 | 119 | MP_OKAY - okay, operation succeeded, all's well |
michael@0 | 120 | MP_YES - okay, the answer is yes (same as MP_OKAY) |
michael@0 | 121 | MP_NO - okay, but answer is no (not MP_OKAY) |
michael@0 | 122 | MP_MEM - operation ran out of memory |
michael@0 | 123 | MP_RANGE - input parameter was out of range |
michael@0 | 124 | MP_BADARG - an invalid input parameter was provided |
michael@0 | 125 | MP_UNDEF - no output value is defined for this input |
michael@0 | 126 | |
michael@0 | 127 | The only function which currently uses MP_UNDEF is mp_invmod(). |
michael@0 | 128 | Division by zero is undefined, but the division functions will return |
michael@0 | 129 | MP_RANGE for a zero divisor. MP_BADARG usually means you passed a |
michael@0 | 130 | bogus mp_int structure to the function. MP_YES and MP_NO are not used |
michael@0 | 131 | by the library itself; they're defined so you can use them in your own |
michael@0 | 132 | extensions. |
michael@0 | 133 | |
michael@0 | 134 | If you need a readable interpretation of these error codes in your |
michael@0 | 135 | program, you may also use the mp_strerror() function. This function |
michael@0 | 136 | takes an mp_err as input, and returns a pointer to a human-readable |
michael@0 | 137 | string describing the meaning of the error. These strings are stored |
michael@0 | 138 | as constants within the library, so the caller should not attempt to |
michael@0 | 139 | modify or free the memory associated with these strings. |
michael@0 | 140 | |
michael@0 | 141 | The library represents values in signed-magnitude format. Values |
michael@0 | 142 | strictly less than zero are negative, all others are considered |
michael@0 | 143 | positive (zero is positive by fiat). You can access the 'sign' member |
michael@0 | 144 | of the mp_int structure directly, but better is to use the mp_cmp_z() |
michael@0 | 145 | function, to find out which side of zero the value lies on. |
michael@0 | 146 | |
michael@0 | 147 | Most arithmetic functions have a single-digit variant, as well as the |
michael@0 | 148 | full arbitrary-precision. An mp_digit is an unsigned value between 0 |
michael@0 | 149 | and DIGIT_MAX inclusive. The radix is available as RADIX. The number |
michael@0 | 150 | of bits in a given digit is given as DIGIT_BIT. |
michael@0 | 151 | |
michael@0 | 152 | Generally, input parameters are given before output parameters. |
michael@0 | 153 | Unless otherwise specified, any input parameter can be re-used as an |
michael@0 | 154 | output parameter, without confusing anything. |
michael@0 | 155 | |
michael@0 | 156 | The basic numeric type defined by the library is an mp_int. Virtually |
michael@0 | 157 | all the functions in the library take a pointer to an mp_int as one of |
michael@0 | 158 | their parameters. An explanation of how to create and use these |
michael@0 | 159 | structures follows. And so, without further ado... |
michael@0 | 160 | |
michael@0 | 161 | |
michael@0 | 162 | Initialization and Cleanup |
michael@0 | 163 | -------------------------- |
michael@0 | 164 | |
michael@0 | 165 | The basic numeric type defined by the library is an 'mp_int'. |
michael@0 | 166 | However, it is not sufficient to simply declare a variable of type |
michael@0 | 167 | mp_int in your program. These variables also need to be initialized |
michael@0 | 168 | before they can be used, to allocate the internal storage they require |
michael@0 | 169 | for computation. |
michael@0 | 170 | |
michael@0 | 171 | This is done using one of the following functions: |
michael@0 | 172 | |
michael@0 | 173 | mp_init(mp_int *mp); |
michael@0 | 174 | mp_init_copy(mp_int *mp, mp_int *from); |
michael@0 | 175 | mp_init_size(mp_int *mp, mp_size p); |
michael@0 | 176 | |
michael@0 | 177 | Each of these requires a pointer to a structure of type mp_int. The |
michael@0 | 178 | basic mp_init() simply initializes the mp_int to a default size, and |
michael@0 | 179 | sets its value to zero. If you would like to initialize a copy of an |
michael@0 | 180 | existing mp_int, use mp_init_copy(), where the 'from' parameter is the |
michael@0 | 181 | mp_int you'd like to make a copy of. The third function, |
michael@0 | 182 | mp_init_size(), permits you to specify how many digits of precision |
michael@0 | 183 | should be preallocated for your mp_int. This can help the library |
michael@0 | 184 | avoid unnecessary re-allocations later on. |
michael@0 | 185 | |
michael@0 | 186 | The default precision used by mp_init() can be retrieved using: |
michael@0 | 187 | |
michael@0 | 188 | precision = mp_get_prec(); |
michael@0 | 189 | |
michael@0 | 190 | This returns the number of digits that will be allocated. You can |
michael@0 | 191 | change this value by using: |
michael@0 | 192 | |
michael@0 | 193 | mp_set_prec(unsigned int prec); |
michael@0 | 194 | |
michael@0 | 195 | Any positive value is acceptable -- if you pass zero, the default |
michael@0 | 196 | precision will be re-set to the compiled-in library default (this is |
michael@0 | 197 | specified in the header file 'mpi-config.h', and typically defaults to |
michael@0 | 198 | 8 or 16). |
michael@0 | 199 | |
michael@0 | 200 | Just as you must allocate an mp_int before you can use it, you must |
michael@0 | 201 | clean up the structure when you are done with it. This is performed |
michael@0 | 202 | using the mp_clear() function. Remember that any mp_int that you |
michael@0 | 203 | create as a local variable in a function must be mp_clear()'d before |
michael@0 | 204 | that function exits, or else the memory allocated to that mp_int will |
michael@0 | 205 | be orphaned and unrecoverable. |
michael@0 | 206 | |
michael@0 | 207 | To set an mp_int to a given value, the following functions are given: |
michael@0 | 208 | |
michael@0 | 209 | mp_set(mp_int *mp, mp_digit d); |
michael@0 | 210 | mp_set_int(mp_int *mp, long z); |
michael@0 | 211 | |
michael@0 | 212 | The mp_set() function sets the mp_int to a single digit value, while |
michael@0 | 213 | mp_set_int() sets the mp_int to a signed long integer value. |
michael@0 | 214 | |
michael@0 | 215 | To set an mp_int to zero, use: |
michael@0 | 216 | |
michael@0 | 217 | mp_zero(mp_int *mp); |
michael@0 | 218 | |
michael@0 | 219 | |
michael@0 | 220 | Copying and Moving |
michael@0 | 221 | ------------------ |
michael@0 | 222 | |
michael@0 | 223 | If you have two initialized mp_int's, and you want to copy the value |
michael@0 | 224 | of one into the other, use: |
michael@0 | 225 | |
michael@0 | 226 | mp_copy(from, to) |
michael@0 | 227 | |
michael@0 | 228 | This takes care of clearing the old value of 'to', and copies the new |
michael@0 | 229 | value into it. If 'to' is not yet initialized, use mp_init_copy() |
michael@0 | 230 | instead (see above). |
michael@0 | 231 | |
michael@0 | 232 | Note: The library tries, whenever possible, to avoid allocating |
michael@0 | 233 | ---- new memory. Thus, mp_copy() tries first to satisfy the needs |
michael@0 | 234 | of the copy by re-using the memory already allocated to 'to'. |
michael@0 | 235 | Only if this proves insufficient will mp_copy() actually |
michael@0 | 236 | allocate new memory. |
michael@0 | 237 | |
michael@0 | 238 | For this reason, if you know a priori that 'to' has enough |
michael@0 | 239 | available space to hold 'from', you don't need to check the |
michael@0 | 240 | return value of mp_copy() for memory failure. The USED() |
michael@0 | 241 | macro tells you how many digits are used by an mp_int, and |
michael@0 | 242 | the ALLOC() macro tells you how many are allocated. |
michael@0 | 243 | |
michael@0 | 244 | If you have two initialized mp_int's, and you want to exchange their |
michael@0 | 245 | values, use: |
michael@0 | 246 | |
michael@0 | 247 | mp_exch(a, b) |
michael@0 | 248 | |
michael@0 | 249 | This is better than using mp_copy() with a temporary, since it will |
michael@0 | 250 | not (ever) touch the memory allocator -- it just swaps the exact |
michael@0 | 251 | contents of the two structures. The mp_exch() function cannot fail; |
michael@0 | 252 | if you pass it an invalid structure, it just ignores it, and does |
michael@0 | 253 | nothing. |
michael@0 | 254 | |
michael@0 | 255 | |
michael@0 | 256 | Basic Arithmetic |
michael@0 | 257 | ---------------- |
michael@0 | 258 | |
michael@0 | 259 | Once you have initialized your integers, you can operate on them. The |
michael@0 | 260 | basic arithmetic functions on full mp_int values are: |
michael@0 | 261 | |
michael@0 | 262 | mp_add(a, b, c) - computes c = a + b |
michael@0 | 263 | mp_sub(a, b, c) - computes c = a - b |
michael@0 | 264 | mp_mul(a, b, c) - computes c = a * b |
michael@0 | 265 | mp_sqr(a, b) - computes b = a * a |
michael@0 | 266 | mp_div(a, b, q, r) - computes q, r such that a = bq + r |
michael@0 | 267 | mp_div_2d(a, d, q, r) - computes q = a / 2^d, r = a % 2^d |
michael@0 | 268 | mp_expt(a, b, c) - computes c = a ** b |
michael@0 | 269 | mp_2expt(a, k) - computes a = 2^k |
michael@0 | 270 | mp_sqrt(a, c) - computes c = floor(sqrt(a)) |
michael@0 | 271 | |
michael@0 | 272 | The mp_div_2d() function efficiently computes division by powers of |
michael@0 | 273 | two. Either the q or r parameter may be NULL, in which case that |
michael@0 | 274 | portion of the computation will be discarded. |
michael@0 | 275 | |
michael@0 | 276 | The algorithms used for some of the computations here are described in |
michael@0 | 277 | the following files which are included with this distribution: |
michael@0 | 278 | |
michael@0 | 279 | mul.txt Describes the multiplication algorithm |
michael@0 | 280 | div.txt Describes the division algorithm |
michael@0 | 281 | expt.txt Describes the exponentiation algorithm |
michael@0 | 282 | sqrt.txt Describes the square-root algorithm |
michael@0 | 283 | square.txt Describes the squaring algorithm |
michael@0 | 284 | |
michael@0 | 285 | There are single-digit versions of most of these routines, as well. |
michael@0 | 286 | In the following prototypes, 'd' is a single mp_digit: |
michael@0 | 287 | |
michael@0 | 288 | mp_add_d(a, d, c) - computes c = a + d |
michael@0 | 289 | mp_sub_d(a, d, c) - computes c = a - d |
michael@0 | 290 | mp_mul_d(a, d, c) - computes c = a * d |
michael@0 | 291 | mp_mul_2(a, c) - computes c = a * 2 |
michael@0 | 292 | mp_div_d(a, d, q, r) - computes q, r such that a = bq + r |
michael@0 | 293 | mp_div_2(a, c) - computes c = a / 2 |
michael@0 | 294 | mp_expt_d(a, d, c) - computes c = a ** d |
michael@0 | 295 | |
michael@0 | 296 | The mp_mul_2() and mp_div_2() functions take advantage of the internal |
michael@0 | 297 | representation of an mp_int to do multiplication by two more quickly |
michael@0 | 298 | than mp_mul_d() would. Other basic functions of an arithmetic variety |
michael@0 | 299 | include: |
michael@0 | 300 | |
michael@0 | 301 | mp_zero(a) - assign 0 to a |
michael@0 | 302 | mp_neg(a, c) - negate a: c = -a |
michael@0 | 303 | mp_abs(a, c) - absolute value: c = |a| |
michael@0 | 304 | |
michael@0 | 305 | |
michael@0 | 306 | Comparisons |
michael@0 | 307 | ----------- |
michael@0 | 308 | |
michael@0 | 309 | Several comparison functions are provided. Each of these, unless |
michael@0 | 310 | otherwise specified, returns zero if the comparands are equal, < 0 if |
michael@0 | 311 | the first is less than the second, and > 0 if the first is greater |
michael@0 | 312 | than the second: |
michael@0 | 313 | |
michael@0 | 314 | mp_cmp_z(a) - compare a <=> 0 |
michael@0 | 315 | mp_cmp_d(a, d) - compare a <=> d, d is a single digit |
michael@0 | 316 | mp_cmp(a, b) - compare a <=> b |
michael@0 | 317 | mp_cmp_mag(a, b) - compare |a| <=> |b| |
michael@0 | 318 | mp_cmp_int(a, z) - compare a <=> z, z is a signed long integer |
michael@0 | 319 | mp_isodd(a) - return nonzero if odd, zero otherwise |
michael@0 | 320 | mp_iseven(a) - return nonzero if even, zero otherwise |
michael@0 | 321 | |
michael@0 | 322 | |
michael@0 | 323 | Modular Arithmetic |
michael@0 | 324 | ------------------ |
michael@0 | 325 | |
michael@0 | 326 | Modular variations of the basic arithmetic functions are also |
michael@0 | 327 | supported. These are available if the MP_MODARITH parameter in |
michael@0 | 328 | mpi-config.h is turned on (it is by default). The modular arithmetic |
michael@0 | 329 | functions are: |
michael@0 | 330 | |
michael@0 | 331 | mp_mod(a, m, c) - compute c = a (mod m), 0 <= c < m |
michael@0 | 332 | mp_mod_d(a, d, c) - compute c = a (mod d), 0 <= c < d (see below) |
michael@0 | 333 | mp_addmod(a, b, m, c) - compute c = (a + b) mod m |
michael@0 | 334 | mp_submod(a, b, m, c) - compute c = (a - b) mod m |
michael@0 | 335 | mp_mulmod(a, b, m, c) - compute c = (a * b) mod m |
michael@0 | 336 | mp_sqrmod(a, m, c) - compute c = (a * a) mod m |
michael@0 | 337 | mp_exptmod(a, b, m, c) - compute c = (a ** b) mod m |
michael@0 | 338 | mp_exptmod_d(a, d, m, c)- compute c = (a ** d) mod m |
michael@0 | 339 | |
michael@0 | 340 | The mp_sqr() function squares its input argument. A call to mp_sqr(a, |
michael@0 | 341 | c) is identical in meaning to mp_mul(a, a, c); however, if the |
michael@0 | 342 | MP_SQUARE variable is set true in mpi-config.h (see below), then it |
michael@0 | 343 | will be implemented with a different algorithm, that is supposed to |
michael@0 | 344 | take advantage of the redundant computation that takes place during |
michael@0 | 345 | squaring. Unfortunately, some compilers result in worse performance |
michael@0 | 346 | on this code, so you can change the behaviour at will. There is a |
michael@0 | 347 | utility program "mulsqr.c" that lets you test which does better on |
michael@0 | 348 | your system. |
michael@0 | 349 | |
michael@0 | 350 | The mp_sqrmod() function is analogous to the mp_sqr() function; it |
michael@0 | 351 | uses the mp_sqr() function rather than mp_mul(), and then performs the |
michael@0 | 352 | modular reduction. This probably won't help much unless you are doing |
michael@0 | 353 | a lot of them. |
michael@0 | 354 | |
michael@0 | 355 | See the file 'square.txt' for a synopsis of the algorithm used. |
michael@0 | 356 | |
michael@0 | 357 | Note: The mp_mod_d() function computes a modular reduction around |
michael@0 | 358 | ---- a single digit d. The result is a single digit c. |
michael@0 | 359 | |
michael@0 | 360 | Because an inverse is defined for a (mod m) if and only if (a, m) = 1 |
michael@0 | 361 | (that is, if a and m are relatively prime), mp_invmod() may not be |
michael@0 | 362 | able to compute an inverse for the arguments. In this case, it |
michael@0 | 363 | returns the value MP_UNDEF, and does not modify c. If an inverse is |
michael@0 | 364 | defined, however, it returns MP_OKAY, and sets c to the value of the |
michael@0 | 365 | inverse (mod m). |
michael@0 | 366 | |
michael@0 | 367 | See the file 'redux.txt' for a description of the modular reduction |
michael@0 | 368 | algorithm used by mp_exptmod(). |
michael@0 | 369 | |
michael@0 | 370 | |
michael@0 | 371 | Greatest Common Divisor |
michael@0 | 372 | ----------------------- |
michael@0 | 373 | |
michael@0 | 374 | If The greates common divisor of two values can be found using one of the |
michael@0 | 375 | following functions: |
michael@0 | 376 | |
michael@0 | 377 | mp_gcd(a, b, c) - compute c = (a, b) using binary algorithm |
michael@0 | 378 | mp_lcm(a, b, c) - compute c = [a, b] = ab / (a, b) |
michael@0 | 379 | mp_xgcd(a, b, g, x, y) - compute g, x, y so that ax + by = g = (a, b) |
michael@0 | 380 | |
michael@0 | 381 | Also provided is a function to compute modular inverses, if they |
michael@0 | 382 | exist: |
michael@0 | 383 | |
michael@0 | 384 | mp_invmod(a, m, c) - compute c = a^-1 (mod m), if it exists |
michael@0 | 385 | |
michael@0 | 386 | The function mp_xgcd() computes the greatest common divisor, and also |
michael@0 | 387 | returns values of x and y satisfying Bezout's identity. This is used |
michael@0 | 388 | by mp_invmod() to find modular inverses. However, if you do not need |
michael@0 | 389 | these values, you will find that mp_gcd() is MUCH more efficient, |
michael@0 | 390 | since it doesn't need all the intermediate values that mp_xgcd() |
michael@0 | 391 | requires in order to compute x and y. |
michael@0 | 392 | |
michael@0 | 393 | The mp_gcd() (and mp_xgcd()) functions use the binary (extended) GCD |
michael@0 | 394 | algorithm due to Josef Stein. |
michael@0 | 395 | |
michael@0 | 396 | |
michael@0 | 397 | Input & Output Functions |
michael@0 | 398 | ------------------------ |
michael@0 | 399 | |
michael@0 | 400 | The following basic I/O routines are provided. These are present at |
michael@0 | 401 | all times: |
michael@0 | 402 | |
michael@0 | 403 | mp_read_radix(mp, str, r) - convert a string in radix r to an mp_int |
michael@0 | 404 | mp_read_raw(mp, s, len) - convert a string of bytes to an mp_int |
michael@0 | 405 | mp_radix_size(mp, r) - return length of buffer needed by mp_toradix() |
michael@0 | 406 | mp_raw_size(mp) - return length of buffer needed by mp_toraw() |
michael@0 | 407 | mp_toradix(mp, str, r) - convert an mp_int to a string of radix r |
michael@0 | 408 | digits |
michael@0 | 409 | mp_toraw(mp, str) - convert an mp_int to a string of bytes |
michael@0 | 410 | mp_tovalue(ch, r) - convert ch to its value when taken as |
michael@0 | 411 | a radix r digit, or -1 if invalid |
michael@0 | 412 | mp_strerror(err) - get a string describing mp_err value 'err' |
michael@0 | 413 | |
michael@0 | 414 | If you compile the MPI library with MP_IOFUNC defined, you will also |
michael@0 | 415 | have access to the following additional I/O function: |
michael@0 | 416 | |
michael@0 | 417 | mp_print(mp, ofp) - print an mp_int as text to output stream ofp |
michael@0 | 418 | |
michael@0 | 419 | Note that mp_radix_size() returns a size in bytes guaranteed to be AT |
michael@0 | 420 | LEAST big enough for the digits output by mp_toradix(). Because it |
michael@0 | 421 | uses an approximation technique to figure out how many digits will be |
michael@0 | 422 | needed, it may return a figure which is larger than necessary. Thus, |
michael@0 | 423 | the caller should not rely on the value to determine how many bytes |
michael@0 | 424 | will actually be written by mp_toradix(). The string mp_toradix() |
michael@0 | 425 | creates will be NUL terminated, so the standard C library function |
michael@0 | 426 | strlen() should be able to ascertain this for you, if you need it. |
michael@0 | 427 | |
michael@0 | 428 | The mp_read_radix() and mp_toradix() functions support bases from 2 to |
michael@0 | 429 | 64 inclusive. If you require more general radix conversion facilities |
michael@0 | 430 | than this, you will need to write them yourself (that's why mp_div_d() |
michael@0 | 431 | is provided, after all). |
michael@0 | 432 | |
michael@0 | 433 | Note: mp_read_radix() will accept as digits either capital or |
michael@0 | 434 | ---- lower-case letters. However, the current implementation of |
michael@0 | 435 | mp_toradix() only outputs upper-case letters, when writing |
michael@0 | 436 | bases betwee 10 and 36. The underlying code supports using |
michael@0 | 437 | lower-case letters, but the interface stub does not have a |
michael@0 | 438 | selector for it. You can add one yourself if you think it |
michael@0 | 439 | is worthwhile -- I do not. Bases from 36 to 64 use lower- |
michael@0 | 440 | case letters as distinct from upper-case. Bases 63 and |
michael@0 | 441 | 64 use the characters '+' and '/' as digits. |
michael@0 | 442 | |
michael@0 | 443 | Note also that compiling with MP_IOFUNC defined will cause |
michael@0 | 444 | inclusion of <stdio.h>, so if you are trying to write code |
michael@0 | 445 | which does not depend on the standard C library, you will |
michael@0 | 446 | probably want to avoid this option. This is needed because |
michael@0 | 447 | the mp_print() function takes a standard library FILE * as |
michael@0 | 448 | one of its parameters, and uses the fprintf() function. |
michael@0 | 449 | |
michael@0 | 450 | The mp_toraw() function converts the integer to a sequence of bytes, |
michael@0 | 451 | in big-endian ordering (most-significant byte first). Assuming your |
michael@0 | 452 | bytes are 8 bits wide, this corresponds to base 256. The sign is |
michael@0 | 453 | encoded as a single leading byte, whose value is 0 for zero or |
michael@0 | 454 | positive values, or 1 for negative values. The mp_read_raw() function |
michael@0 | 455 | reverses this process -- it takes a buffer of bytes, interprets the |
michael@0 | 456 | first as a sign indicator (0 = zero/positive, nonzero = negative), and |
michael@0 | 457 | the rest as a sequence of 1-byte digits in big-endian ordering. |
michael@0 | 458 | |
michael@0 | 459 | The mp_raw_size() function returns the exact number of bytes required |
michael@0 | 460 | to store the given integer in "raw" format (as described in the |
michael@0 | 461 | previous paragraph). Zero is returned in case of error; a valid |
michael@0 | 462 | integer will require at least three bytes of storage. |
michael@0 | 463 | |
michael@0 | 464 | In previous versions of the MPI library, an "external representation |
michael@0 | 465 | format" was supported. This was removed, however, because I found I |
michael@0 | 466 | was never using it, it was not as portable as I would have liked, and |
michael@0 | 467 | I decided it was a waste of space. |
michael@0 | 468 | |
michael@0 | 469 | |
michael@0 | 470 | Other Functions |
michael@0 | 471 | --------------- |
michael@0 | 472 | |
michael@0 | 473 | The files 'mpprime.h' and 'mpprime.c' define some routines which are |
michael@0 | 474 | useful for divisibility testing and probabilistic primality testing. |
michael@0 | 475 | The routines defined are: |
michael@0 | 476 | |
michael@0 | 477 | mpp_divis(a, b) - is a divisible by b? |
michael@0 | 478 | mpp_divis_d(a, d) - is a divisible by digit d? |
michael@0 | 479 | mpp_random(a) - set a to random value at current precision |
michael@0 | 480 | mpp_random_size(a, prec) - set a to random value at given precision |
michael@0 | 481 | |
michael@0 | 482 | Note: The mpp_random() and mpp_random_size() functions use the C |
michael@0 | 483 | ---- library's rand() function to generate random values. It is |
michael@0 | 484 | up to the caller to seed this generator before it is called. |
michael@0 | 485 | These functions are not suitable for generating quantities |
michael@0 | 486 | requiring cryptographic-quality randomness; they are intended |
michael@0 | 487 | primarily for use in primality testing. |
michael@0 | 488 | |
michael@0 | 489 | Note too that the MPI library does not call srand(), so your |
michael@0 | 490 | application should do this, if you ever want the sequence |
michael@0 | 491 | to change. |
michael@0 | 492 | |
michael@0 | 493 | mpp_divis_vector(a, v, s, w) - is a divisible by any of the s digits |
michael@0 | 494 | in v? If so, let w be the index of |
michael@0 | 495 | that digit |
michael@0 | 496 | |
michael@0 | 497 | mpp_divis_primes(a, np) - is a divisible by any of the first np |
michael@0 | 498 | primes? If so, set np to the prime |
michael@0 | 499 | which divided a. |
michael@0 | 500 | |
michael@0 | 501 | mpp_fermat(a, d) - test if w^a = w (mod a). If so, |
michael@0 | 502 | returns MP_YES, otherwise MP_NO. |
michael@0 | 503 | |
michael@0 | 504 | mpp_pprime(a, nt) - perform nt iterations of the Rabin- |
michael@0 | 505 | Miller probabilistic primality test |
michael@0 | 506 | on a. Returns MP_YES if all tests |
michael@0 | 507 | passed, or MP_NO if any test fails. |
michael@0 | 508 | |
michael@0 | 509 | The mpp_fermat() function works based on Fermat's little theorem, a |
michael@0 | 510 | consequence of which is that if p is a prime, and (w, p) = 1, then: |
michael@0 | 511 | |
michael@0 | 512 | w^p = w (mod p) |
michael@0 | 513 | |
michael@0 | 514 | Put another way, if w^p != w (mod p), then p is not prime. The test |
michael@0 | 515 | is expensive to compute, but it helps to quickly eliminate an enormous |
michael@0 | 516 | class of composite numbers prior to Rabin-Miller testing. |
michael@0 | 517 | |
michael@0 | 518 | Building the Library |
michael@0 | 519 | -------------------- |
michael@0 | 520 | |
michael@0 | 521 | The MPI library is designed to be as self-contained as possible. You |
michael@0 | 522 | should be able to compile it with your favourite ANSI C compiler, and |
michael@0 | 523 | link it into your program directly. If you are on a Unix system using |
michael@0 | 524 | the GNU C compiler (gcc), the following should work: |
michael@0 | 525 | |
michael@0 | 526 | % gcc -ansi -pedantic -Wall -O2 -c mpi.c |
michael@0 | 527 | |
michael@0 | 528 | The file 'mpi-config.h' defines several configurable parameters for |
michael@0 | 529 | the library, which you can adjust to suit your application. At the |
michael@0 | 530 | time of this writing, the available options are: |
michael@0 | 531 | |
michael@0 | 532 | MP_IOFUNC - Define true to include the mp_print() function, |
michael@0 | 533 | which is moderately useful for debugging. This |
michael@0 | 534 | implicitly includes <stdio.h>. |
michael@0 | 535 | |
michael@0 | 536 | MP_MODARITH - Define true to include the modular arithmetic |
michael@0 | 537 | functions. If you don't need modular arithmetic |
michael@0 | 538 | in your application, you can set this to zero to |
michael@0 | 539 | leave out all the modular routines. |
michael@0 | 540 | |
michael@0 | 541 | MP_NUMTH - Define true to include number theoretic functions |
michael@0 | 542 | such as mp_gcd(), mp_lcm(), and mp_invmod(). |
michael@0 | 543 | |
michael@0 | 544 | MP_LOGTAB - If true, the file "logtab.h" is included, which |
michael@0 | 545 | is basically a static table of base 2 logarithms. |
michael@0 | 546 | These are used to compute how big the buffers for |
michael@0 | 547 | radix conversion need to be. If you set this false, |
michael@0 | 548 | the library includes <math.h> and uses log(). This |
michael@0 | 549 | typically forces you to link against math libraries. |
michael@0 | 550 | |
michael@0 | 551 | MP_MEMSET - If true, use memset() to zero buffers. If you run |
michael@0 | 552 | into weird alignment related bugs, set this to zero |
michael@0 | 553 | and an explicit loop will be used. |
michael@0 | 554 | |
michael@0 | 555 | MP_MEMCPY - If true, use memcpy() to copy buffers. If you run |
michael@0 | 556 | into weird alignment bugs, set this to zero and an |
michael@0 | 557 | explicit loop will be used. |
michael@0 | 558 | |
michael@0 | 559 | MP_CRYPTO - If true, whenever arrays of digits are free'd, they |
michael@0 | 560 | are zeroed first. This is useful if you're using |
michael@0 | 561 | the library in a cryptographic environment; however, |
michael@0 | 562 | it does add overhead to each free operation. For |
michael@0 | 563 | performance, if you don't care about zeroing your |
michael@0 | 564 | buffers, set this to false. |
michael@0 | 565 | |
michael@0 | 566 | MP_ARGCHK - Set to 0, 1, or 2. This defines how the argument |
michael@0 | 567 | checking macro, ARGCHK(), gets expanded. If this |
michael@0 | 568 | is set to zero, ARGCHK() expands to nothing; no |
michael@0 | 569 | argument checks are performed. If this is 1, the |
michael@0 | 570 | ARGCHK() macro expands to code that returns MP_BADARG |
michael@0 | 571 | or similar at runtime. If it is 2, ARGCHK() expands |
michael@0 | 572 | to an assert() call that aborts the program on a |
michael@0 | 573 | bad input. |
michael@0 | 574 | |
michael@0 | 575 | MP_DEBUG - Turns on debugging output. This is probably not at |
michael@0 | 576 | all useful unless you are debugging the library. It |
michael@0 | 577 | tends to spit out a LOT of output. |
michael@0 | 578 | |
michael@0 | 579 | MP_DEFPREC - The default precision of a newly-created mp_int, in |
michael@0 | 580 | digits. The precision can be changed at runtime by |
michael@0 | 581 | the mp_set_prec() function, but this is its initial |
michael@0 | 582 | value. |
michael@0 | 583 | |
michael@0 | 584 | MP_SQUARE - If this is set to a nonzero value, the mp_sqr() |
michael@0 | 585 | function will use an alternate algorithm that takes |
michael@0 | 586 | advantage of the redundant inner product computation |
michael@0 | 587 | when both multiplicands are identical. Unfortunately, |
michael@0 | 588 | with some compilers this is actually SLOWER than just |
michael@0 | 589 | calling mp_mul() with the same argument twice. So |
michael@0 | 590 | if you set MP_SQUARE to zero, mp_sqr() will be expan- |
michael@0 | 591 | ded into a call to mp_mul(). This applies to all |
michael@0 | 592 | the uses of mp_sqr(), including mp_sqrmod() and the |
michael@0 | 593 | internal calls to s_mp_sqr() inside mpi.c |
michael@0 | 594 | |
michael@0 | 595 | The program 'mulsqr' (mulsqr.c) can be used to test |
michael@0 | 596 | which works best for your configuration. Set up the |
michael@0 | 597 | CC and CFLAGS variables in the Makefile, then type: |
michael@0 | 598 | |
michael@0 | 599 | make mulsqr |
michael@0 | 600 | |
michael@0 | 601 | Invoke it with arguments similar to the following: |
michael@0 | 602 | |
michael@0 | 603 | mulsqr 25000 1024 |
michael@0 | 604 | |
michael@0 | 605 | That is, 25000 products computed on 1024-bit values. |
michael@0 | 606 | The output will compare the two timings, and recommend |
michael@0 | 607 | a setting for MP_SQUARE. It is off by default. |
michael@0 | 608 | |
michael@0 | 609 | If you would like to use the mp_print() function (see above), be sure |
michael@0 | 610 | to define MP_IOFUNC in mpi-config.h. Many of the test drivers in the |
michael@0 | 611 | 'tests' subdirectory expect this to be defined (although the test |
michael@0 | 612 | driver 'mpi-test' doesn't need it) |
michael@0 | 613 | |
michael@0 | 614 | The Makefile which comes with the library should take care of building |
michael@0 | 615 | the library for you, if you have set the CC and CFLAGS variables at |
michael@0 | 616 | the top of the file appropriately. By default, they are set up to |
michael@0 | 617 | use the GNU C compiler: |
michael@0 | 618 | |
michael@0 | 619 | CC=gcc |
michael@0 | 620 | CFLAGS=-ansi -pedantic -Wall -O2 |
michael@0 | 621 | |
michael@0 | 622 | If all goes well, the library should compile without warnings using |
michael@0 | 623 | this combination. You should, of course, make whatever adjustments |
michael@0 | 624 | you find necessary. |
michael@0 | 625 | |
michael@0 | 626 | The MPI library distribution comes with several additional programs |
michael@0 | 627 | which are intended to demonstrate the use of the library, and provide |
michael@0 | 628 | a framework for testing it. There are a handful of test driver |
michael@0 | 629 | programs, in the files named 'mptest-X.c', where X is a digit. Also, |
michael@0 | 630 | there are some simple command-line utilities (in the 'utils' |
michael@0 | 631 | directory) for manipulating large numbers. These include: |
michael@0 | 632 | |
michael@0 | 633 | basecvt.c A radix-conversion program, supporting bases from |
michael@0 | 634 | 2 to 64 inclusive. |
michael@0 | 635 | |
michael@0 | 636 | bbsrand.c A BBS (quadratic residue) pseudo-random number |
michael@0 | 637 | generator. The file 'bbsrand.c' is just the driver |
michael@0 | 638 | for the program; the real code lives in the files |
michael@0 | 639 | 'bbs_rand.h' and 'bbs_rand.c' |
michael@0 | 640 | |
michael@0 | 641 | dec2hex.c Converts decimal to hexadecimal |
michael@0 | 642 | |
michael@0 | 643 | gcd.c Computes the greatest common divisor of two values. |
michael@0 | 644 | If invoked as 'xgcd', also computes constants x and |
michael@0 | 645 | y such that (a, b) = ax + by, in accordance with |
michael@0 | 646 | Bezout's identity. |
michael@0 | 647 | |
michael@0 | 648 | hex2dec.c Converts hexadecimal to decimal |
michael@0 | 649 | |
michael@0 | 650 | invmod.c Computes modular inverses |
michael@0 | 651 | |
michael@0 | 652 | isprime.c Performs the Rabin-Miller probabilistic primality |
michael@0 | 653 | test on a number. Values which fail this test are |
michael@0 | 654 | definitely composite, and those which pass are very |
michael@0 | 655 | likely to be prime (although there are no guarantees) |
michael@0 | 656 | |
michael@0 | 657 | lap.c Computes the order (least annihilating power) of |
michael@0 | 658 | a value v modulo m. Very dumb algorithm. |
michael@0 | 659 | |
michael@0 | 660 | primegen.c Generates large (probable) primes. |
michael@0 | 661 | |
michael@0 | 662 | prng.c A pseudo-random number generator based on the |
michael@0 | 663 | BBS generator code in 'bbs_rand.c' |
michael@0 | 664 | |
michael@0 | 665 | sieve.c Implements the Sieve of Eratosthenes, using a big |
michael@0 | 666 | bitmap, to generate a list of prime numbers. |
michael@0 | 667 | |
michael@0 | 668 | fact.c Computes the factorial of an arbitrary precision |
michael@0 | 669 | integer (iterative). |
michael@0 | 670 | |
michael@0 | 671 | exptmod.c Computes arbitrary precision modular exponentiation |
michael@0 | 672 | from the command line (exptmod a b m -> a^b (mod m)) |
michael@0 | 673 | |
michael@0 | 674 | Most of these can be built from the Makefile that comes with the |
michael@0 | 675 | library. Try 'make tools', if your environment supports it. |
michael@0 | 676 | |
michael@0 | 677 | |
michael@0 | 678 | Testing the Library |
michael@0 | 679 | ------------------- |
michael@0 | 680 | |
michael@0 | 681 | Automatic test vectors are included, in the form of a program called |
michael@0 | 682 | 'mpi-test'. To build this program and run all the tests, simply |
michael@0 | 683 | invoke the shell script 'all-tests'. If all the tests pass, you |
michael@0 | 684 | should see a message: |
michael@0 | 685 | |
michael@0 | 686 | All tests passed |
michael@0 | 687 | |
michael@0 | 688 | If something went wrong, you'll get: |
michael@0 | 689 | |
michael@0 | 690 | One or more tests failed. |
michael@0 | 691 | |
michael@0 | 692 | If this happens, scan back through the preceding lines, to see which |
michael@0 | 693 | test failed. Any failure indicates a bug in the library, which needs |
michael@0 | 694 | to be fixed before it will give accurate results. If you get any such |
michael@0 | 695 | thing, please let me know, and I'll try to fix it. Please let me know |
michael@0 | 696 | what platform and compiler you were using, as well as which test |
michael@0 | 697 | failed. If a reason for failure was given, please send me that text |
michael@0 | 698 | as well. |
michael@0 | 699 | |
michael@0 | 700 | If you're on a system where the standard Unix build tools don't work, |
michael@0 | 701 | you can build the 'mpi-test' program manually, and run it by hand. |
michael@0 | 702 | This is tedious and obnoxious, sorry. |
michael@0 | 703 | |
michael@0 | 704 | Further manual testing can be performed by building the manual testing |
michael@0 | 705 | programs, whose source is found in the 'tests' subdirectory. Each |
michael@0 | 706 | test is in a source file called 'mptest-X.c'. The Makefile contains a |
michael@0 | 707 | target to build all of them at once: |
michael@0 | 708 | |
michael@0 | 709 | make tests |
michael@0 | 710 | |
michael@0 | 711 | Read the comments at the top of each source file to see what the |
michael@0 | 712 | driver is supposed to test. You probably don't need to do this; these |
michael@0 | 713 | programs were only written to help me as I was developing the library. |
michael@0 | 714 | |
michael@0 | 715 | The relevant files are: |
michael@0 | 716 | |
michael@0 | 717 | mpi-test.c The source for the test driver |
michael@0 | 718 | |
michael@0 | 719 | make-test-arrays A Perl script to generate some of the internal |
michael@0 | 720 | data structures used by mpi-test.c |
michael@0 | 721 | |
michael@0 | 722 | test-arrays.txt The source file for make-test-arrays |
michael@0 | 723 | |
michael@0 | 724 | all-tests A Bourne shell script which runs all the |
michael@0 | 725 | tests in the mpi-test suite |
michael@0 | 726 | |
michael@0 | 727 | Running 'make mpi-test' should build the mpi-test program. If you |
michael@0 | 728 | cannot use make, here is what needs to be done: |
michael@0 | 729 | |
michael@0 | 730 | (1) Use 'make-test-arrays' to generate the file 'test-info.c' from |
michael@0 | 731 | the 'test-arrays.txt' file. Since Perl can be found everywhere, |
michael@0 | 732 | this should be no trouble. Under Unix, this looks like: |
michael@0 | 733 | |
michael@0 | 734 | make-test-arrays test-arrays.txt > test-info.c |
michael@0 | 735 | |
michael@0 | 736 | (2) Build the MPI library: |
michael@0 | 737 | |
michael@0 | 738 | gcc -ansi -pedantic -Wall -c mpi.c |
michael@0 | 739 | |
michael@0 | 740 | (3) Build the mpi-test program: |
michael@0 | 741 | |
michael@0 | 742 | gcc -ansi -pedantic -Wall -o mpi-test mpi.o mpi-test.c |
michael@0 | 743 | |
michael@0 | 744 | When you've got mpi-test, you can use 'all-tests' to run all the tests |
michael@0 | 745 | made available by mpi-test. If any of them fail, there should be a |
michael@0 | 746 | diagnostic indicating what went wrong. These are fairly high-level |
michael@0 | 747 | diagnostics, and won't really help you debug the problem; they're |
michael@0 | 748 | simply intended to help you isolate which function caused the problem. |
michael@0 | 749 | If you encounter a problem of this sort, feel free to e-mail me, and I |
michael@0 | 750 | will certainly attempt to help you debug it. |
michael@0 | 751 | |
michael@0 | 752 | Note: Several of the tests hard-wired into 'mpi-test' operate under |
michael@0 | 753 | ---- the assumption that you are using at least a 16-bit mp_digit |
michael@0 | 754 | type. If that is not true, several tests might fail, because |
michael@0 | 755 | of range problems with the maximum digit value. |
michael@0 | 756 | |
michael@0 | 757 | If you are using an 8-bit digit, you will also need to |
michael@0 | 758 | modify the code for mp_read_raw(), which assumes that |
michael@0 | 759 | multiplication by 256 can be done with mp_mul_d(), a |
michael@0 | 760 | fact that fails when DIGIT_MAX is 255. You can replace |
michael@0 | 761 | the call with s_mp_lshd(), which will give you the same |
michael@0 | 762 | effect, and without doing as much work. :) |
michael@0 | 763 | |
michael@0 | 764 | Acknowledgements: |
michael@0 | 765 | ---------------- |
michael@0 | 766 | |
michael@0 | 767 | The algorithms used in this library were drawn primarily from Volume |
michael@0 | 768 | 2 of Donald Knuth's magnum opus, _The Art of Computer Programming_, |
michael@0 | 769 | "Semi-Numerical Methods". Barrett's algorithm for modular reduction |
michael@0 | 770 | came from Menezes, Oorschot, and Vanstone's _Handbook of Applied |
michael@0 | 771 | Cryptography_, Chapter 14. |
michael@0 | 772 | |
michael@0 | 773 | Thanks are due to Tom St. Denis, for finding an obnoxious sign-related |
michael@0 | 774 | bug in mp_read_raw() that made things break on platforms which use |
michael@0 | 775 | signed chars. |
michael@0 | 776 | |
michael@0 | 777 | About the Author |
michael@0 | 778 | ---------------- |
michael@0 | 779 | |
michael@0 | 780 | This software was written by Michael J. Fromberger. You can contact |
michael@0 | 781 | the author as follows: |
michael@0 | 782 | |
michael@0 | 783 | E-mail: <sting@linguist.dartmouth.edu> |
michael@0 | 784 | |
michael@0 | 785 | Postal: 8000 Cummings Hall, Thayer School of Engineering |
michael@0 | 786 | Dartmouth College, Hanover, New Hampshire, USA |
michael@0 | 787 | |
michael@0 | 788 | PGP key: http://linguist.dartmouth.edu/~sting/keys/mjf.html |
michael@0 | 789 | 9736 188B 5AFA 23D6 D6AA BE0D 5856 4525 289D 9907 |
michael@0 | 790 | |
michael@0 | 791 | Last updated: 16-Jan-2000 |