Big integers

This section explains the key concepts of big integer library.

Purpose of big integer

Some types of cryptography require the handling of finite arbitrary length integers. This big integer library attempts to provide support for that requirement.

It is capable of representing both negative and positive integers with an absolute value of less than 2^(237).

Using the big integer library

There are four categories of exposed APIs:

  1. Creation of new integers given some other representation (descriptor, TUint, etc). RInteger::NewL()

  2. Creation of new integers given some criteria (range, bitcount, prime). RInteger::NewRandomL(), RInteger::NewPrimeL()

  3. Exporting of previously created integers to descriptors. TInteger::BufferLC()

  4. Querying attributes about the size of a previously created integer. TInteger::BitCount(), TInteger::ByteCount(), TInteger::WordCount().

The following code demonstrates how to create an RInteger from a bit string representation of a big integer.

//This creates an RInteger from the following binary hexadecimal (base 16)
//descriptor.  Note that the number is written overall in big endian (most
//significant digit is first, least significant digit (ones digit) is last).  
//P.S. The hexadecimal binary descriptor below is the base 16 representation
//of the base 10 number 123456789012345678901234567890.
RInteger integer = RInteger::NewL(_L8("18EE90FF6C373E0EE4E3F0AD2")); 

//This next line converts the number stored by an RInteger into a binary, big
//endian, hexadecimal descriptor.
HBufC8* descriptor = integer.BufferLC();
//descriptor is the same as the original _L8 input value now.

For more information on integers, including important memory management information and additional creation overloads, see RInteger in the Cryptography API Reference material.

Base classes and their derived classes

The following diagram shows the main classes used in bigint and which are implemented in cryptography.dll. The color of the boxes indicates the type of Symbian class, that is, M, C, R or T class.

Figure: The inheritance diagram for TInteger and RInteger classes.

RInteger class

RInteger is a TInteger derived class allowing the construction of variable length big integers.

This class follows standard R class rules. As a quick refresher, the following rules apply to RInteger s:

  • You can construct an empty RInteger.

    RInteger integer;

    This is a constructed, but uninitialized integer. It does not own memory and no operations can be performed on it. It is useful, mostly, to assign the result of another integer operation to. Push ing and then PopAndDestroy ing an empty RInteger works, although it's not needed.

  • RInteger s can be bitwised copied (the default assignment operator and copy constructor are valid), but you need to be careful you don't lose your original memory in the process. You should only use the assignment operator on a newly declared integer. To set an RInteger to another value without losing memory see TInteger::Set().

    RInteger a = anotherInteger; // OK -- you now have two integers that point to the same memory
    RInteger b = RInteger::NewL(aDesc); // OK 
    b = a; // NOT OK, b's original memory has been lost
  • You own any RInteger returned by value from a TInteger function.

    RInteger integer = a.MinusL(b); // We now own integer
  • You must call Close() on all RInteger s that own memory before they go out of scope. (The cleanup stack can do this for you as well, see further bullet points below).

    void foo(void)
        RInteger integer = a.TimesL(TInteger::Two);
        //< all sorts of non-leaving code here >
  • RInteger has a operator TCleanupItem() cast function that allows you to call CleanupStack::PushL(RInteger&). Use this in preference to CleanupClosePushL(RInteger&), which although it does the same thing, generates more code.

    RInteger integer = a.ModularExponentiateL(b, p);
    //< all sorts of leaving code here >
  • Be careful calling TInteger::Set(). After calling this, two RInteger s have a pointer to the same heap-based integer. Calling Close() on one, either explicitly or through the cleanup stack, leaves a dangling pointer to the other. You probably want to use code similar to the following:

    RInteger first = RInteger::NewL(298728);
    //< all sorts of leaving code here >
    RInteger second.Set(first);