【转帖】mircal学习讨论

来源:互联网 发布:apache friends xampp 编辑:程序博客网 时间:2024/06/05 11:17

今天开始学习mircal,知道武汉大学的椭圆曲线密码研究很牛,去论坛看了一下,有个好帖子,冒昧的copy过来,共大家看看。
http://www.mathmagic.cn/bbs/read.php?tid=7050
【数缘原创】密码学C语言函数库——Miracl库快速上手中文指南(VC)

一、简介

密码学学习、研究人员往往着重于理论研究,难以与实践直接挂钩,今天介绍一下国外著名密码学C语言函数库——Miracl库的使用方法。

Miracl库的官方网站是http://www.shamus.ie/,完全开源,任何人可以去免费下载使用。由于国外网速有限,本站提供下载地址:http://www.mathmagic.cn/bbs/read.php?boardID=16&tid=5153(版本略旧,但不会影响使用,我一直用这个版本)。

该库针对公钥密码学和椭圆曲线密码学的实现,写了很多函数,在这方面可以说是所有国外的库中功能最强大的了。但分组密码等方面的函数相对较少。

二、VC6中调用Miracl库的方法

一般我们采用VC 6.0来使用Miracl库,本站提供VC6的下载地址:http://www.mathmagic.cn/bbs/read.php?boardID=18&tid=5772

下面我详细讲述一下使用方法。

1、VC中新建一个project,选择“win32 console application”,起名为123,建立一个空的project。

2、找到该工程保存的文件夹,把miracl/lib/ms32.lib,miracl/include/mirdef.h,miracl/include/miracl.h三个文件拷贝到123文件夹下。

3、在VC中左边的“workspace”列表中,选“fileview”选项卡,对着123 files单击右键,add files t o project,将ms32.lib加进来(注意:看不到ms32.lib的,把“文件类型”设置为“所有类型”)。

4、右键单击Source Files,添加文件,命名为123.c,写入下列程序:


#include "miracl.h"
main()
{
big a, b, c;
miracl *mip = mirsys(5000, 16);
a=mirvar(8);
b=mirvar(7);
c=mirvar(0);
add(a, b, c);
cotnum(c, stdout);
}

注1: “miracl *mip = mirsys(5000, 16);”该行程序是每个含有miracl语句的程序都必须有的语句,必须放在变量声明后面、其他程序前面。意思是我定义的这些变量最大长度都是5000 位(这个位是后面进制的位数),输入、输出、运算用的进制都是16进制。

注2:每个big型变量都必须赋初始值,否则出错!

注3:有可能会出现警告:LINK : warning LNK4098: defaultlib "LIBC" conflicts with use of other libs; use /NODEFAULTLIB:library。当它不存在好了,没事。

注4:输入函数有cinnum和innum,输出函数有cotnum和otnum,用的时候尽量用前者,我用后者老是出错,文档里有说明,我暂时没时间仔细研究为什么出错。据说跟进制有关,高手可以跟帖解释一下。

注5:使用cinnum函数之前加上“mip->IOBASE = 16;”,见我下面的例子。否则出错。

5、运行即可输出“F”。绝对不会出错。如果程序运行有错误的,返回上面第一步,仔细看看自己哪个地方弄错了。

至此,你已经学会了如何在VC中调用用miracl库的函数了。具体每个函数怎么用,你可以看看文档(MIRACL Reference Manual),写的非常清楚。在文档中可以查到某个函数的源代码在哪个文件里,找到该文件后,进去找找,每个函数的前面都有说明,说明该函数中的算法出自哪里。对于研究算法和实现的人也是很有帮助的。

三、学习与提高

Miracl提供两个说明文档,一个是函数查询手册(MIRACL Reference Manual),另一个是使用说明(User’s Manual)。

你也可以把文档User’s Manual中的程序拿过来用用试试。逐渐熟悉一下一些常见的函数的使用方法。

下面是我自己写的一个实现1024比特RSA解密的时间测试程序:


#include "miracl.h"
#include <time.h>
main()
{
int i;
big x, e, m, y;
FILE *fp;
clock_t tBegin, tEnd;
miracl *mip = mirsys(1000, 16);
x = mirvar(0);
e = mirvar(0);
m = mirvar(0);
y = mirvar(0);
fp = fopen("data.txt", "r+");
mip->IOBASE = 16;
cinnum(x, fp);
cinnum(e, fp);
cinnum(m, fp);
fclose(fp);
tBegin = clock();
for (i = 0; i < 100; i ++)
powmod(x, e, m, y);
tEnd = clock();
cotnum(x, stdout);
cotnum(e, stdout);
cotnum(m, stdout);
cotnum(y, stdout);
printf("/n/n进行100次1024比特的模指数运算所消耗的时间为:%ld ms/n/n", tEnd - tBegin);
}

运行该程序时候,还需要在文件夹中建立一个data.txt文件,用于存放数据:
F05085869EF4BA2514D08635E180E138DCD2AAAF1B04C69A4C3A9B612A6FAF9784393B5B49026FEA2F0E244D84506A7A1D44B8745CE4B9B0C83668FD83BADEFC2A6EEC3D80BA5A3CEB1CB538C25199B05E3E3535F3276020F53C8E9D2B518465BD2F6322C1751A00C6EF5186614D9EC955841B2CCFD59882853E4131233BC2E3
D98E5FC36267464CE6947FEEE0EC8BC7AA611AD15D68F234BAC62C18C9DEF38BA135550D54EBCD179EA40F377A01066B13E61FF8C9639B2D3A19EC7B8CC58877F7266FDDDC776C563D277DB0204C9CE7213D87E76750478531E3B09685629B1B9FEB06E118A5F3E978F8AED1D0C202A5728021831A5012D43DE53C9CAFFF4E1D
B5AEB6D01F4A09AE231CA573868A2B7F16E3F90AFA2417ADA94816CC8488D04F249132DB235A71BCD956D3E648F54FBA0A48F46626D113D3345E1415B727DAE37F0886DE3078FAD6FFBADC8DF22E4ADB88317A7E6BF7144306D06977EF54B061A87C236C4B4BF28006ED7D02F7F9C9BB87F7EC3CF4F623A183A7EB0B95654073

(三个数据用回车隔开,最后一行后面必须有回车!)

运行可知:用Miracl库实现1024比特的RSA解密,平均一次只需要14毫秒,以前很多人都不知道这个数据吧?嘿嘿,实践出真知啊。(我的运行环境是P4 3.0,1G内存)。

四、尾声

国外著名密码学函数库还有:GMP、NTL、Crypto++、LibTomCrypt(LibTomMath)、OpenSSL等,本站密码算法快速实现版块有一些简介(http://www.mathmagic.cn/bbs/index.asp?boardid=25)。欢迎对密码算法快速实现有兴趣的各位有志之士前来讨论

 

 

在加一部分

 

 

快速地识别MIRACL库函数

 

从bLaCk-eye的网站上down到的,觉得挺有用的。网址是http://www.secretashell.com/cryptocrk/,这里东西不少,推荐去看看。

MIARCL是当前使用比较广泛的基于公钥加密算法保护实现的大数库之一,特别在各种算法Crackme中。目前为止还没有发现使用该库的商业软件,因为MIRACL用于商业目的的话需要交纳一笔昂贵的授权费——1000$。所以这里介绍的这个技巧只能对你破解各种算法Crackme起到一点帮助。

 

这个技巧是怎么来的呢?

 

我们知道,MIRACL有一个十分有用的特性:它可以让你十分方便的定位程序运行过程中出错的函数,MIRACL的文档是这样说的:

 

”初始化函数mirsys运行的同时也会初始化集成在MIRACL库中的错误跟踪系统。这样,无论何时只要函数调用序列中的任何一个函数发生错误都会被检测到,包括错误本身。一个典型的错误信息如下:

 

MIRACL error from routine powltr
called from isprime
called from your program
Raising integer to a negative power

这些错误报告在开发过程中对我们调试有很大的帮助。与之相关的一个常量是TRACER,默认是OFF,如果将它改为ON,程序运行过程中将会把错误信息打印到电脑屏幕上。”

 

上面这些信息对我们有什么帮助呢?

 

MIRACL能确切知道哪个函数出错是因为它对每个函数定义了一个特定的常量作为标识符,这些信息是从MIRACL源代码里发现的。下面是MrArth3.c里的一段代码:

 

void power(_MIPD_ big x,long n,big z,big w)
{ /* raise big number to int power w=x^n *
* (mod z if z and w distinct) */
mr_small norm;
#ifdef MR_OS_THREADS
miracl *mr_mip=get_mip();
#endif
copy(x,mr_mip->w5);
zero(w);
if(mr_mip->ERNUM || size(mr_mip->w5)==0) return;
convert(_MIPP_ 1,w);
if (n==0L) return;

 

MR_IN(17)

 

if (n<0L)
{
mr_berror(_MIPP_ MR_ERR_NEG_POWER);
MR_OUT
return;
}

//rest of the code from file
}

注意粗体字显示的那段代码。我们可以看到,这条代码不在任何一个条件编译代码段内,这就意味着无论你用何种选项编译MIRACL,MR_IN(17)都会在最终生成库文件里面。

 

将这段代码反汇编的结果是:

 

mov dword ptr [esi+eax*4+20h], 11h

11h的十进制正是17。

现在你明白如何去识别MIRACL库的函数了吧:调试时跟进有疑问的CALL,搜索下面形式的指令:

 

mov dword ptr [esi+eax*4+20h], XXh

在你自己的函数特征值表中查找XX,或者直接对照我在后面列出的那个表。

有了这个所有函数特征值对应表后我们就可以十分轻松的识别MIRACL里的所有函数。这个方法的优点就是每个函数对应的特征值一般不会由于库版本的升级而发生变化,因此可以比较放心的使用。缺点呢就是你必须自己动手去一个一个函数地去识别。对于这点一个好的解决办法就是编写一个IDA的脚本,自动搜索那些的指令并根据特征值修改函数名。



附表:

MIRACL MAGIC NUMBERS TABLE:
by bLaCk-eye
from an original ideea by bF!^k23

 

NUMBER OF FUNCTIONS: 08Eh

 

Innum equ 01h

 

Otnum equ 02h

 

Jack equ 03h

 

normalise equ 04h

 

multiply equ 05h

 

divide equ 06h

 

incr equ 07h

 

decr equ 08h

 

premult equ 09h

 

subdiv equ 0Ah

 

fdsize equ 0Bh

 

egcd equ 0Ch

 

cbase equ 0Dh

 

cinnum equ 0Eh

 

cotnum equ 0Fh

 

nroot equ 10h

 

power equ 11h

 

powmod equ 12h

 

bigdig equ 13h

 

bigrand equ 14h

 

nxprime equ 15h

 

isprime equ 16h

 

mirvar equ 17h

 

mad equ 18h

 

multi_inverse equ 19h

 

putdig equ 1Ah

 

add equ 1Bh

 

subtract equ 1Ch

 

mirsys equ 1Dh

 

xgcd equ 1Eh

 

fpack equ 1Fh

 

dconv equ 20h

 

mr_shift equ 21h

 

mround equ 22h

 

fmul equ 23h

 

fdiv equ 24h

 

fadd equ 25h

 

fsub equ 26h

 

fcomp equ 27h

 

fconv equ 28h

 

frecip equ 29h

 

fpmul equ 2Ah

 

fincr equ 2Bh

 

;null entry

 

ftrunc equ 2Dh

 

frand equ 2Eh

 

sftbit equ 2Fh

 

build equ 30h

 

logb2 equ 31h

 

expint equ 32h

 

fpower equ 33h

 

froot equ 34h

 

fpi equ 35h

 

fexp equ 36h

 

flog equ 37h

 

fpowf equ 38h

 

ftan equ 39h

 

fatan equ 3Ah

 

fsin equ 3Bh

 

fasin equ 3Ch

 

fcos equ 3Dh

 

facos equ 3Eh

 

ftanh equ 3Fh

 

fatanh equ 40h

 

fsinh equ 41h

 

fasinh equ 42h

 

fcosh equ 43h

 

facosh equ 44h

 

flop equ 45h

 

gprime equ 46h

 

powltr equ 47h

 

fft_mult equ 48h

 

crt_init equ 49h

 

crt equ 4Ah

 

otstr equ 4Bh

 

instr equ 4Ch

 

cotstr equ 4Dh

 

cinstr equ 4Eh

 

powmod2 equ 4Fh

 

prepare_monty equ 50h

 

nres equ 51h

 

redc equ 52h

 

nres_modmult equ 53h

 

nres_powmod equ 54h

 

nres_moddiv equ 55h

 

nres_powltr equ 56h

 

divisible equ 57h

 

remain equ 58h

 

fmodulo equ 59h

 

nres_modadd equ 5Ah

 

nres_modsub equ 5Bh

 

nres_negate equ 5Ch

 

ecurve_init equ 5Dh

 

ecurve_add equ 5Eh

 

ecurve_mult equ 5Fh

 

epoint_init