首页  编辑  

RSA算法和共享软件注册码

Tags: /超级猛料/Shareware.共享软件开发/   Date Created:

RSA算法和软件注册

Kingron, 2006

共享软件有一个很重要的部分就是注册码算法,如果注册算法简单,可逆,那么就很容易被破解,生成注册机!因此大家都采用公钥算法来进行注册,例如RSA和ECC(椭圆曲线算法),ECC对抗注册机是非常好的,附件中是FGINT实现的RSA算法,有可以用用,但强度没有ECC好。由于网络上C/C++的算法和库很多,但Delphi/Pascal的非常少,因此就在这里讨论一下RSA在注册码中的应用。

RSA算法具体内容请自己查阅相关资料,这里不做讨论。

下面给出附件单元的使用方法:

首先你需要作一个注册机,自己用。但在注册前,你需要查找一些大素数,并求出公钥和私钥。

利用下面的函数,你可以生成公钥和私钥的Delphi定义:

{

 uses FGIntRSA, FGInt;

 用法: RSAGetDefines('42789535304218630318941267842', 'qwaayafgehuio79361hfh;$%@!FKSJr22L:A^*OHFAHJL:A', '65537');

 它将返回 e, d, n的一些定义。请记录下它的定义。

}

function RSAGetDefines(const Key1, Key2, Key3: string): string;

const

 CSSign : array[TSign] of string = ('negative', 'positive');

var

 one, two, gcd, d, n, p, q, phi, e, nilGint: TFGInt;

 i : Integer;

begin

 Base10StringToFGInt(Key1  , p);

 PrimeSearch(p);

 Base256StringToFGInt(Key2, q);

 PrimeSearch(q);

 FGIntMul(p, q, n);

 p.Number[1] := p.Number[1] - 1;

 q.Number[1] := q.Number[1] - 1;

 FGIntMul(p, q, phi);  // Compute phi(n)

 Base10StringToFGInt(Key3, e); // just an odd starting point

 Base10StringToFGInt('1', one);

 Base10StringToFGInt('2', two);

 FGIntGCD(phi, e, gcd);

 While FGIntCompareAbs(gcd, one) <> Eq Do

 Begin

   FGIntadd(e, two, nilGint);

   FGIntCopy(nilGint, e);

   FGIntGCD(phi, e, gcd);

 End;

 FGIntModInv(e, phi, d);

 FGIntDestroy(nilgint);

 Result := Format('e.Sign := %s;'#13#10'SetLength(e.Number, %d);'#13#10,

                  [CSSign[e.Sign], Length(e.Number)]);

 for i := Low(e.Number) to High(e.Number) do

   Result := Result + Format('e.Number[%d] := $%x;'#13#10, [i, e.Number[i]]);

 Result := Result + #13#10 + Format('d.Sign := %s;'#13#10'SetLength(d.Number, %d);'#13#10,

                  [CSSign[d.Sign], Length(d.Number)]);

 for i := Low(d.Number) to High(d.Number) do

   Result := Result + Format('d.Number[%d] := $%x;'#13#10, [i, d.Number[i]]);

 Result := Result + #13#10 + Format('n.Sign := %s;'#13#10'SetLength(n.Number, %d);'#13#10,

                  [CSSign[n.Sign], Length(n.Number)]);

 for i := Low(n.Number) to High(n.Number) do

   Result := Result + Format('n.Number[%d] := $%x;'#13#10, [i, n.Number[i]]);

end;

有了定义之后,就可以使用RSA算法进行签名和验证了,下面是签名算法,你可以用在自己的注册机中,例如可以使用用户明作为Name输入,生成一个字符串返回给用户作为注册码SerialKey:

function RSASignatureName(const Name: string): string;

var

 KeyData : string;

 d, n, nilGint: TFGInt;

begin

 if Name = '' then Exit;

 /// 清在这里把前面记录下的 d 的定义代码粘贴到这里

 /// 请在这里把前面记录下的 n 的定义代码粘贴到这里

 nilGint.Number := nil;

 RSASign(Name, d, n, nilGint, nilGint, nilGint, nilGint, KeyData);

 /// EncodeSerialKey 为一个把RSA签名数据转换成可读的ASCII的函数,你可以用Base64编码器代替

 Result := EncodeSerialKey(KeyData);  

 FGIntDestroy(d);

 FGIntDestroy(n);

end;

注册机作完了,那么你的共享软件中当然需要验证一下用户的注册码对不对,用下面的函数在你的软件中进行验证即可,如果匹配,返回True,否则返回False,其中Name就是用户给你来注册的用户名,Code就是程序中接收到的用户输入的序列号:

function RSAVerityName(const Name, Code: string): Boolean;

var

 desData: string;

 e, n: TFGInt;

begin

 Result := False;

 if Code = '' then Exit;

 

 /// 请在这里把前面记录下的 e 的定义代码粘贴到这里

 /// 请在这里把前面记录下的 n 的定义代码粘贴到这里

 /// DecodeSerialKey为把可读ASCII数据转换成二进制的函数,你可以用Base64的解码器代替

 desData := DecodeSerialKey(Code);

 RSAVerify(Name, desData, e, n, Result);

end;

RSA_FGINT.zip (22.1KB)