This section explains the key concepts of big integer library.
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).
There are four categories of exposed APIs:
Creation of
new integers given some other representation (descriptor, TUint, etc). RInteger::NewL()
Creation of
new integers given some criteria (range, bitcount, prime). RInteger::NewRandomL()
, RInteger::NewPrimeL()
Exporting of
previously created integers to descriptors. TInteger::BufferLC()
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")); CleanupStack::PushL(integer); //This next line converts the number stored by an RInteger into a binary, big //endian, hexadecimal descriptor. HBufC8* descriptor = integer.BufferLC(); CleanupStack::Pop(descriptor); CleanupStack::PopAndDestroy(integer); //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.
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
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 CleanupStack::PushL(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 > integer.Close(); }
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); CleanupStack::PushL(integer); //< all sorts of leaving code here > CleanupStack::PopAndDestroy(&integer);
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); CleanupStack::PushL(first); //< all sorts of leaving code here > RInteger second.Set(first); CleanupStack::Pop(first); CleanupStack::PushL(second);