Library of Congress Cataloging-in-Publication Data ..... Libraries in 80x86 assembler (see Chapter 19) in directories fl
Cryptography in C and C++ MICHAEL WELSCHENBACH Translated by DAVID KRAMER
A press
TM
Cryptography in C and C++ c 2005 by Michael Welschenbach Copyright Translator and Compositor: David Kramer Editorial Board: Steve Anglin, Dan Appleman, Ewan Buckingham, Gary Cornell, Tony Davis, Jason Gilmore, Jonathan Hassell, Chris Mills, Dominic Shakeshaft, Jim Sumser Assistant Publisher: Grace Wong Copy Manager: Nicole LeClerc Production Manager: Kari Brooks-Copony Proofreader: Anne Friedman TEX Support: Fred Bartlett and Arthur Ogawa Manufacturing Manager: Tom Debolski Cover Designer: Kurt Krames Library of Congress Cataloging-in-Publication *=", 0, __LINE__); if (ln.(status == E_LINT_INV) panic (E_LINT_VAL, "*=", 1, __LINE__); if (&ln == this) error = sqr_l (n_l, n_l); else error = mul_l (n_l, ln.n_l, n_l); switch (error) { case 0: status = E_LINT_OK; break; case E_CLINT_OFL: status = E_LINT_OFL; break; default: panic (E_LINT_ERR, "*=", error, __LINE__); } return *this; }
As our last example of a LINT operator we shall describe the function “==”, which tests for the equality of two LINT objects: As result the value 1 is returned in the case of equality, and otherwise 0. The operator == also illustrates the implementation of other logical operators. const int operator == (const LINT& lm, const LINT& ln) { if (lm.(status == E_LINT_INV) LINT::panic (E_LINT_VAL, "==", 1, __LINE__); if (ln.(status == E_LINT_INV) LINT::panic (E_LINT_VAL, "==", 2, __LINE__); if (&ln == &lm) return 1; else return equ_l (lm.n_l, ln.n_l); }
335
CHAPTER 15
The LINT Public Interface: Members and Friends Please accept my resignation. I don’t want to belong to any club that will accept me as a member. —Groucho Marx Every time I paint a portrait I lose a friend —John Singer Sargent
IN ADDITION TO THE CONSTRUCTOR functions and operators already discussed, there exist further LINT functions that make the C functions developed in Part I available to LINT objects. In the following discussion we make a rough separation of the functions into the categories “arithmetic” and “number-theoretic.” The implementation of the functions will be discussed together with examples; otherwise, we shall restrict ourselves to a table of information needed for their proper use. We shall give more extensive treatment in the following sections to the functions for the formatted output of LINT objects, for which we shall make use of the properties of the stream classes contained in the C++ standard library. Possible applications, in particular for formatted output of objects of user-defined classes, are given rather short shrift in many C++ textbooks, and we are going to take the opportunity to explicate the construction of the functions needed to output our LINT objects.
15.1
Arithmetic
The following member functions implement the fundamental arithmetic operations as well as modular operations for calculation in residue class rings over the integers as accumulator operations: The object to which a called function belongs contains the function result as implicit argument after its termination. Accumulator functions are efficient, since they operate to the greatest extent 337
Chapter 15
without internal auxiliary objects and thus save unnecessary assignments and calls to constructors. For the cases in which a free assignment of the results of calculations is unavoidable, or in which the automatic overwriting of the implicit argument of the member functions with the result is not desired, the member functions were extended by means of like-named analogous friend functions together with additional friend functions. These are not discussed further here, but are recorded in Appendix B. The treatment of possible error situations in LINT functions that can arise from the use of CLINT functions will be discussed in full in Chapter 16. Before we list the public member functions, we consider first as an example of their implementation the functions LINT& LINT::mexp (const LINT& e, const LINT& m );
and LINT& LINT::mexp (USHORT e, const LINT& m);
for exponentiation, an operation for which C++, alas, offers no operator. The functions mexp() were constructed in such a way that the functions used are, according to the type of the operands, the C functions mexpk_l(), mexpkm_l(), umexp_l(), and umexpm_l(), optimized for this purpose (with the corresponding arithmetic friend functions we are likewise dealing with the exponentiation functions wmexp_l() and wmexpm_l() with USHORT base).
Function:
Modular exponentiation with automatic use of Montgomery exponentiation if the modulus is odd.
Syntax:
const LINT& LINT::mexp (const LINT& e, const LINT& m);
Input:
implicit argument (base) e (exponent) m (modulus)
Return:
pointer to the remainder
Example:
a.mexp (e, m);
const LINT& LINT::mexp (const LINT& e, const LINT& m) { int error; if (status == E_LINT_INV) panic (E_LINT_VAL, "mexp", 0, __LINE__);
338
The LINT Public Interface: Members and Friends if (status == E_LINT_INV) panic (E_LINT_VAL, "mexp", 1, __LINE__); if (status == E_LINT_INV) panic (E_LINT_VAL, "mexp", 2, __LINE__); err = mexp_l (n_l, e.n_l, n_l, m.n_l); /* mexp_l() uses mexpk_l() or mexpkm_l() */ switch (error) { case 0: status = E_LINT_OK; break; case E_CLINT_DBZ: panic (E_LINT_DBZ, "mexp", 2, __LINE__); break; default: panic (E_LINT_ERR, "mexp", error, __LINE__); } return *this; }
Function:
Modular exponentiation
Syntax:
const LINT& LINT::mexp (USHORT e, const LINT& m);
Example:
a.mexp (e, m);
const LINT& LINT::mexp (USHORT e, const LINT& m) { int err; if (status == E_LINT_INV) panic (E_LINT_VAL, "mexp", 0, __LINE__); if (status == E_LINT_INV) panic (E_LINT_VAL, "mexp", 1, __LINE__); err = umexp_l (n_l, e, n_l, m.n_l); switch (err) { // Code as above with mexp (const LINT& e, const LINT& m) } return *this; }
339
Chapter 15
We now present a collection of additional arithmetic and number-theoretic member functions.
340
Function:
addition
Syntax:
const LINT& LINT::add(const LINT& s);
Input:
implicit argument (summand) s (summand)
Return:
pointer to the sum
Example:
a.add (s); executes the operation a += s;
Function:
subtraction
Syntax:
const LINT& LINT::sub (const LINT& s);
Input:
implicit argument (minuend) s (subtrahend)
Return:
pointer to the difference
Example:
a.sub (s); executes the operation a -= s;
Function:
multiplication
Syntax:
const LINT& LINT::mul (const LINT& s);
Input:
implicit argument (factor) s (factor)
Return:
pointer to the product
Example:
a.mul (s); executes the operation a *= s;
The LINT Public Interface: Members and Friends
Function:
squaring
Syntax:
const LINT& LINT::sqr (void);
Input:
implicit argument (factor)
Return:
pointer to the implicit argument, which contains the square
Example:
a.sqr (); executes the operation a *= a;
Function:
division with remainder
Syntax:
const LINT& LINT::divr(const LINT& d, LINT& r);
Input:
implicit argument (dividend) d (divisor)
Output
r (remainder of the division modulo d)
Return:
pointer to the implicit argument, which contains the quotient
Example:
a.divr (d, r); executes the operation a /= d; r = a % d;
Function:
residue
Syntax:
const LINT& LINT::mod(const LINT& d);
Input:
implicit argument (dividend) d (divisor)
Return:
pointer to the implicit argument, which contains the remainder of the division modulo d
Example:
a.mod (d); executes the operation a %= d;
341
Chapter 15
342
Function:
residue modulo a power of 2
Syntax:
const LINT& LINT::mod2 (USHORT e)
Input:
implicit argument (dividend) e (exponent of the power of 2 divisor)
Return:
pointer to the implicit argument, which contains the remainder of the division modulo 2e
Example:
a.mod 2(e); executes the operation a %= d;, where d = 2e
Note:
mod2 cannot be created by overloading the previously presented function mod(), since mod() also accepts a USHORT argument, which is changed automatically into a LINT object by means of the appropriate constructor. Since it cannot be determined from the arguments which function is meant, mod2() is given its own name.
Function:
test for equality modulo m
Syntax:
int LINT::mequ (const LINT& b, const LINT& m);
Input:
implicit argument a second argument b modulus m
Return:
1 if a ≡ b mod m, 0 otherwise
Example:
if (a.mequ (b, m)) // . . .
The LINT Public Interface: Members and Friends
Function:
modular addition
Syntax:
const LINT& LINT::madd(const LINT& s, const LINT& m);
Input:
implicit argument (summand) s (summand) m (modulus)
Return:
pointer to the implicit argument, which contains the sum modulo m
Example:
a.madd (s, m);
Function:
modular subtraction
Syntax:
const LINT& LINT::msub(const LINT& s, const LINT& m);
Input:
implicit argument (minuend) s (subtrahend) m (modulus)
Return:
pointer to the implicit argument, which contains the difference modulo m
Example:
a.msub (s, m);
Function:
modular multiplication
Syntax:
const LINT& LINT::mmul (const LINT& s, const LINT& m);
Input:
implicit argument (factor) s (factor) m (modulus)
Return:
pointer to the implicit argument, which contains the product modulo m
Example:
a.mmul (s, m);
343
Chapter 15
344
Function:
modular squaring
Syntax:
const LINT& LINT::msqr (const LINT& m);
Input:
implicit argument (factor) m (modulus)
Return:
pointer to the implicit argument, which contains the square modulo m
Example:
a.msqr (m);
Function:
modular exponentiation with exponent a power of 2
Syntax:
const LINT& LINT::mexp2 (USHORT e, const LINT& m);
Input:
implicit argument (base) e (power to which 2 is to be raised) m (modulus)
Return:
pointer to the implicit argument, which contains the power modulo m
Example:
a.mexp2 (e, m);
Function:
modular exponentiation (2k -ary method, Montgomery reduction)
Syntax:
const LINT& LINT::mexpkm (const LINT& e, const LINT& m);
Input:
implicit argument (base) e (exponent) m (odd modulus)
Return:
pointer to the implicit argument, which contains the power modulo m
Example:
a.mexpkm (e, m);
The LINT Public Interface: Members and Friends
Function:
modular exponentiation (25 -ary method, Montgomery reduction)
Syntax:
const LINT& LINT::mexp5m (const LINT& e, const LINT& m);
Input:
implicit argument (base) e (exponent) m (odd modulus)
Return:
pointer to the implicit argument, which contains the power modulo m
Example:
a.mexp5m (e, m);
Function:
left/right shift
Syntax:
const LINT& LINT::shift (int noofbits);
Input:
implicit argument (multiplicand/dividend) (+/-) noofbits (number of bit positions to be shifted) pointer to the implicit argument, which contains the result of the shift operation
Return: Example:
a.shift (512); executes the operation a 2
Return:
square root of a if a is a quadratic residue modulo p otherwise 0 (Get_Warning_Status() == E_LINT_ERR indicates that a is not a quadratic residue modulo p)
Example:
c = a.root (p);
The LINT Public Interface: Members and Friends
Function:
calculation of the square root of a LINT object modulo a prime product p · q
Syntax:
LINT LINT::root (const LINT& p, const LINT& q);
Input:
implicit argument a prime modulus p > 2, prime modulus q > 2
Return:
square root of a if a is a quadratic residue modulo pq otherwise 0 (Get_Warning_Status() == E_LINT_ERR indicates that a is not a quadratic residue modulo p*q)
Example:
c = a.root (p, q);
Function:
test of whether a LINT object is a square
Syntax:
int LINT::issqr(void);,
Input:
test candidate a as implicit argument
Return:
square root of a if a is a square otherwise 0 if a == 0 or a not a square
Example:
if(0 == (r = a.issqr ())) // . . .
Function:
probabilistic primality test of a LINT object
Syntax:
int LINT::isprime (int nsp, int rnds);
Input:
test candidate p as implicit argument nsp (number of primes for the division test; default is 302) rnds (number of passes through test; default is zero for automatic optimization via the function prime_l())
Return:
1 if p is a “probable” prime 0 otherwise
Example:
if(p.isprime ()) // . . .
351
Chapter 15
15.3
Function:
calculate the two-part of a LINT object
Syntax:
int LINT::twofact (LINT& b);
Input:
implicit argument a
Output:
b (odd part of a)
Return:
exponent of the even part of a
Example:
e = a.twofact (b);
Stream I/O of LINT Objects
The classes contained in the C++ standard library such as istream and ostream are abstractions of input and output devices derived from the base class ios. The class iostream is in turn derived from istream and ostream, and it enables both writing and reading of its objects.1 Input and output take place with the help of the insert and extract operators “” (cf. [Teal], Chapter 8). These arise through overloading the shift operators, for example in the form ostream& ostream::operator> (int& i);
in which they enable output, respectively input, of integer values through expressions of the form cout > i;
As special objects of the classes ostream and istream, cout and cin represent the same abstract files as the objects stdout and stdin of the standard C library. The use of the stream operators “” for input and output makes it unnecessary to consider particular properties of the hardware in use. In and of itself this is nothing new, for the C function printf() behaves the same way: A printf() instruction should always, regardless of platform, lead to the same result. However, above and beyond the altered syntax, which is oriented to the metaphorical image of the insertion of objects into a stream, the advantages of the C++ implementation of streams lie in the strict type checking, which in the case of printf() is possible only to a limited degree, and in its extensibility. In particular, we make use of the latter property by overloading the insert and extract 1
352
We use this name of the stream classes as a synonym for the terms now used in the C++ standard library, with which the class names known up to now are prefixed with basic_. The justification for this comes from the standard library itself, where the class names known hitherto are provided with corresponding typedefs (cf. [KSch], Chapter 12).
The LINT Public Interface: Members and Friends
operators so that they support input and output of LINT objects. To this end the class LINT defines the following stream operators: friend ostream& operator> (ifstream& s, LINT& ln);
A simple formulation of the overloaded insert operators for the output of LINT objects might look something like the following: #include ostream& operator