Symbian 下大数计算

来源:互联网 发布:知与行杂志马克思 编辑:程序博客网 时间:2024/06/17 20:41

在开发过程中,凡涉及注册、登录、身份验证,常常会需要引入大数算法,通过大数算法和哈希相结合,用于密钥生成等。

一般平台,可以使用开源的mpir算法库。任何能够使用标准C的平台都可以方便的使用mpir库进行大数运算。

详细信息可以查阅www.mpir.org。

但是,因为SymbianOS提供的STD C/C++库并不能完整的支持标准C,因此使用gcc或者armv5编译mpir库时,会遇到很多问题,从而导致编译无法通过。我在最近的项目中尝试在Symbian环境中编译mpir-2.3.0-lite版本。在经过了大量修改和函数重写之后,gcc编译勉强通过,但是armv5版本始终无法通过编译。而大家应该能够想想,gcc版本的mpir库有多大,放在产品中显然不合适。因此,只能另找方法解决这个问题。

幸运的是,Nokia提供了一套大数运算库。这套库在Symbian^3中已经包含在SDK中,S60 v3/v5开发时,则需要在Forum nokia下载:

http://wiki.forum.nokia.com/index.php/Symbian_Cryptography_APIs

在应用程序部署时,S60 v5/Symbian^3手机都已经带有相关的lib库,可以不必考虑相关库的打包问题。

 

不幸的是,这套库虽然提供了所谓的API帮助文档,但是与万恶的SymbianOS文档一样,几乎没有提供任何有价值的信息。幸亏有从symbian fundation下载的源代码,一一对照才知道该如何使用。

 

常用的操作包括:

1,生成128位随机数:

RInteger Rs = RInteger::NewRandomL(128);

2, 用指定数据构造大数:

TUint8 _n[128] = {0xEE,  0xC0 , …… , 0x06, 0xE3 };   

TBuf8<128> n;
n.Append(_n, 128);
RInteger N = RInteger::NewL(n);

3, 基本运算:

RInteger r1 = RN.TimesL(Rx);   //r1 = RN * Rx

RInteger r2 = Ra.PlusL(r1); //r2 = Ra + r1;

RInteger r3 = RB.MinusL(r2);  //r3 = RB – r2;

4,使用RInteger中的Buffer数据:

TPtr8 RBPtr = RB.BufferLC()->Des();

……

CleanupStack::PopAndDestroy(1); //delete buffer.

 

4, ModPow运算:

ModPow运算是做大数运算中很常用的算法: g^a%N

也就是对g做指数为a的指数运算,然后用N取余。

ModPow的基本算法是:

static int ModPow(int x, int n, int m)

{

int z = 1;

for (int i = 0; i < n; i++) z = (z * x) % m;

return z;

}

更高效的算法是:

static int ModPow(int x, int n, int m)

{

int z = 1;

for (int p = x; n > 0; n >>= 1, p = (p * p) % m) if ((n & 1) != 0) z = (z * p) % m;

return z;

}

如果使用Symbian的RInteger,可以使用:

RInteger RS;
TRAPD(err, RS = left.ModularExponentiateL(g, a, N)); //g^a%N
if(err) //err
    {
    __LOG1("RS created failed with=%d", err);

    }

 

必须要注意的是:

如果采用这样的写法进行ModPow运算:

g.ExponentiateL(a).ModuloL(N);

则一般情况下肯定会出问题,理由并不难想象:指数运算的数据量是恐怖的,因此并不需要太大的a值,就可以让上面的指数运算ExponentiateL()抛出内存不足的错误。经过实践,如果保持缺省的栈内存和堆内存,如果底数g为16字节(128位),则只是4个字节(32位)的指数a,就会抛出内存不足。

因此先做指数运算再取模和直接使用ModPow算法调用ModularExponentiateL()绝对是不一样的。

 

另一件值得一提的事情是。对于取模运算,如果能够注意到模运算的分配率,可以大大的提高大数运算的效率,因为取模可以有效地降低数据的位数。例如:

(46 * 72)

等于((46 % 17) * (72 % 17)) % 17 
即等于(12 * 4) % 17 
= 48 % 17 
= 14

 

最后附上使用CSHA1实现哈希的代码:

 

void GetMsgDigestBySHA1L( TDes8 &aDest, const TDesC8 &aSrc )
    {
    aDest.Zero();
    CSHA1* sha1 = CSHA1::NewL();
    CleanupStack ::PushL(sha1);   
    TPtrC8 ptrHash = sha1->Hash( aSrc );

    aDest.Append(ptrHash);
    CleanupStack::PopAndDestroy(sha1);
    }

原创粉丝点击