学习学习

《openssl 编程》之 椭圆曲线

上一篇 / 下一篇  2007-11-15 10:26:40 / 个人分类:信息安全

第二十章  椭圆曲线

20.1 ECC介绍

椭圆曲线(ECC)算法是一种公钥算法,它比流行的RSA算法有很多优点:LUPA开源社区qN4L/du8iYaOR

1)安全性能更高  160ECC1024RSADSA有相同的安全强度。LUPA开源社区!T\*eS D4Xq

2)计算量小,处理速度快, 在私钥的处理速度上(解密和签名),ECCRSADSA快得多。

Z8N}^ {TK0

3)存储空间占用小  ECC的密钥尺寸和系统参数与RSADSA相比要小得多, 所以占用的存储空间小得多。

uIw*k-\[%J:Y0

4)带宽要求低。LUPA开源社区)JE7x2D3r3o zQr

20.2 opensslECC实现

      Openssl实现了ECC算法。ECC算法系列包括三部分:ECC算法(crypto/ec)、椭圆曲线数字签名算法ECDSA (crypto/ecdsa)以及椭圆曲线密钥交换算法ECDH(crypto/dh)LUPA开源社区8nV`k ?b

      研究椭圆曲线需要注意的有:

c1K0YKYe%b-Bd0

1)  密钥数据结构LUPA开源社区b5EI}"Ji&CC-EGb

主要是公钥和私钥数据结构。椭圆曲线密钥数据结构如下,定义在crypto/ec_lcl.h中,对用户是透明的。LUPA开源社区A4JE ktDy9}Yd

             struct ec_key_stLUPA开源社区8^;v DS9~2i5P

{

,e @'b7tS0

                  int               version;LUPA开源社区)Io F1H ]5C+s/K

                   EC_GROUP *group;

.W8b,p/O/wCU)y0b8Z0

                   EC_POINT  *pub_key;LUPA开源社区(zL^] }

                   BIGNUM*priv_key;LUPA开源社区2]J!Fp%O

                    /*其他*/LUPA开源社区(s d9?N9Bn

}

[#W m*Kt FxY|(p0

2)  密钥生成

4Yv2M _l0

对照公钥和私钥的表示方法,非对称算法不同有各自的密钥生成过程。椭圆曲线的密钥生成实现在crytpo/ec/ec_key.c中。Openssl中,椭圆曲线密钥生成时,首先用户需要选取一种椭圆曲线(opensslcrypto/ec_curve.c中内置实现了67种,调用EC_get_builtin_curves获取该列表),然后根据选择的椭圆曲线计算密钥生成参数group,最后根据密钥参数group来生公私钥。LUPA开源社区QEQ0|$Ul}$wZ

3签名值数据结构LUPA开源社区;F6jg:|%Xxl&C

非对称算法不同,签名的结果表示也不一样。与DSA签名值一样,ECDSA的签名结果表示为两项。ECDSA的签名结果数据结构定义在crypto/ecdsa/ecdsa.h中,如下:

%|.U L6US0

      typedef struct ECDSA_SIG_stLUPA开源社区aI5b/V s v]

{

;C'X {~V!p0

            BIGNUM *r;LUPA开源社区Y Pu3^'V p/e,mOGw

            BIGNUM *s;

f(dS(PTW0

} ECDSA_SIG;

bF'F"vr,}0

4)   签名与验签

n\9BM9sk4o0

对照签名结果,研究其是如何生成的。crypto/ecdsa/ ecs_sign.c实现了签名算法,crypto/ecdsa/ ecs_vrf.c实现了验签。LUPA开源社区DB8`us!n

      5 密钥交换

8Z?!e%y"k.mv$j%k \0

             研究其密钥交换是如何进行的;crypto/ecdh/ech_ossl.c实现了密钥交换算法。

2VBsfM"V#e"z)p|0

20.3 主要函数

      1 EC_get_builtin_curves

C!v0OgC2t)bb;J0

             获取椭圆曲线列表。LUPA开源社区&L+~Tdv@b lb

      2 EC_GROUP_new_by_curve_nameLUPA开源社区&^t+q _w a(A~

             根据指定的椭圆曲线来生成密钥参数。LUPA开源社区1RAyc I

      3 int EC_KEY_generate_key

$`Xf-IkJ/t ]J0

             根据密钥参数生成ECC公私钥。

1F]] ]*V-XI2d-ld0

      4 int EC_KEY_check_keyLUPA开源社区p*j/j&K!wO8K W/W r

             检查ECC密钥。LUPA开源社区U$F[4Aj8a&Y3o1l

      5 int    ECDSA_sizeLUPA开源社区^.IM$e;O)eO6I'H

             获取ECC密钥大小字节数。LUPA开源社区.huLjxa u$DB$M

      6 ECDSA_sign

;j-R ]:dw0

             签名,返回1表示成功。LUPA开源社区/rda?N6o [([M|

      7 ECDSA_verify

XZ9L+F5i4S ZM0

             验签,返回1表示合法。

2l Q8_5v6]%E#Z*fG/d0

      8 EC_KEY_get0_public_key

n? ZUQk0

             获取公钥。

I{#b/Tsp2^Z#_0

      9 EC_KEY_get0_private_keyLUPA开源社区`/R$j4P4b;?P3as

             获取私钥。LUPA开源社区h"C5q+xmh"e S

10ECDH_compute_key

rJ%|!EY/d vI0

             生成共享密钥

k FzMg0

20.4 编程示例

下面的例子生成两对ECC密钥,并用它做签名和验签,并生成共享密钥。

|9x;U'J?J-rAd9O0

#include <string.h>LUPA开源社区p:V P,_%r0G{

#include <stdio.h>LUPA开源社区;Gu?&o"c(RNaWZ

#include <openssl/ec.h>LUPA开源社区@U2N;hy"M2j

#include <openssl/ecdsa.h>LUPA开源社区f V!iy$Tu$LK

#include <openssl/objects.h>

qyIQ8bi0

#include <openssl/err.h>LUPA开源社区9}h CX\ G:s

 LUPA开源社区!Cb"j[:Y3N3x[d

int   main()LUPA开源社区O*}-Y v#O4[SD8V| D

{

%mQ-C$kOz`+`0

      EC_KEY               *key1,*key2;LUPA开源社区+{zP#J8g

      EC_POINT           *pubkey1,*pubkey2;

"Ic#k!_;s,jU&A0

      EC_GROUP          *group1,*group2;

!D#u&x(}t)EH0

      int                        ret,nid,size,i,sig_len;LUPA开源社区9J'r1?p'xL

      unsigned char*signature,digest[20];

-f!`$W7m$HEo0

      BIO                     *berr;

(|6s"|!whV8N0

      EC_builtin_curve   *curves;LUPA开源社区,P mZa:EZ*S

      int                               crv_len;

d,]Z1F2Z{*|ayN0

      char              shareKey1[128],shareKey2[128];LUPA开源社区Q9]!mEgj"]

      int                        len1,len2;

p PEO#s.NB!Q_R0

 

Gb^G9}FEwQ_0

      /*构造EC_KEY数据结构*/LUPA开源社区B(\;Yv0ILRe

      key1=EC_KEY_new();LUPA开源社区nE"E:R/h0M;s

      if(key1==NULL)LUPA开源社区N7DE3`V"e"H/iT4b,G

      {LUPA开源社区3E wg{ ?-q u

             printf("EC_KEY_new err!\n");

`}:SE;ZCWo)i0

             return -1;

4uJ-lNB.H7u'D']b0

      }LUPA开源社区,sopX r1j*\!V.RL

      key2=EC_KEY_new();

wF"^$r$k0

      if(key2==NULL)

Q!~:`,gk%NC0

      {

7i;z SZNJk6A9my0Z9eg0

             printf("EC_KEY_new err!\n");

M-][.g G!o0

             return -1;

,NN2o6N ]bjN1VA0

      }

0x,b`lmz1?P0

      /*获取实现的椭圆曲线个数*/

?,aw)yM B&p0

      crv_len = EC_get_builtin_curves(NULL, 0);LUPA开源社区&JT#pu-wOG

      curves = (EC_builtin_curve *)malloc(sizeof(EC_builtin_curve) * crv_len);

2F,`|{`OsQ7|1B0

      /*获取椭圆曲线列表*/

7aU`%[.]A Oy'w0

      EC_get_builtin_curves(curves, crv_len);LUPA开源社区"g-r$F6x(?C.?c

      /*LUPA开源社区3O$FUQ:jD0X

      nid=curves[0].nid;会有错误,原因是密钥太短

\6BVmd'oT;Q0

      */LUPA开源社区(hhG"WC7lW

      /*选取一种椭圆曲线*/

O1kh,x,m'o8@f9e)p0

      nid=curves[25].nid;

s b}4M_ Ap)O(D[ Y j%Y0

      /*根据选择的椭圆曲线生成密钥参数group */

M'v6_f;]\4T:E|0

      group1=EC_GROUP_new_by_curve_name(nid);LUPA开源社区R Vs `Z*^3jPZ

      if(group1==NULL)LUPA开源社区!NpI5o wcH'uTyZ

      {

M(B"f?7E$EI^0

             printf("EC_GROUP_new_by_curve_name err!\n");

H D7~g3pD ^:e0

             return -1;LUPA开源社区zXY#pb"B&zS E,G6jrT

      }LUPA开源社区 G yC3xBUc @)J

      group2=EC_GROUP_new_by_curve_name(nid);

-l+w/ju n0

      if(group1==NULL)

%L#c'l&UoT j?0

      {LUPA开源社区W1_1DfWA

             printf("EC_GROUP_new_by_curve_name err!\n");

j*GY\!M:s2f0

             return -1;LUPA开源社区DCy/I/LaXP

      }

Z a'F1^F*W)y,azw0

      /*设置密钥参数*/

1S {*K+C0d'V8H8f0O0

      ret=EC_KEY_set_group(key1,group1);LUPA开源社区/bqp {2N8RW

      if(ret!=1)LUPA开源社区 ~/F5~'E#w

      {

%@(Ha.tA x:S _:OL0

             printf("EC_KEY_set_group err.\n");LUPA开源社区Tlg~o!m}'^

             return -1;

`p-CLq1s(d3y:_0

      }

d/CO+N@$R9W0

      ret=EC_KEY_set_group(key2,group2);

)\U;PEo~e_9y Z0

      if(ret!=1)

^E%w^N1t0

      {

NM0kn4rX9~0

             printf("EC_KEY_set_group err.\n");

A2?4R,i0w!l?c"R0

             return -1;

Hh |tvUG:Q0

      }

0i|7Y#]r4W6h&h0

      /*生成密钥*/

z2j](Z2El aE0

      ret=EC_KEY_generate_key(key1);

0~F Z0sn%K0

      if(ret!=1)LUPA开源社区V/YT,j8Ob\c.M

      {

Uj(v[N7f'G}0

             printf("EC_KEY_generate_key err.\n");

O6YW.g.k'cQf0

             return -1;LUPA开源社区 B%@!k7pS*rTHq

      }

_ c9P xX5cZ\0

      ret=EC_KEY_generate_key(key2);LUPA开源社区3Tz[1[7f-C$oI_ j5Uy

      if(ret!=1)

vx0T/b;jB0

      {LUPA开源社区Xn U[i~R

             printf("EC_KEY_generate_key err.\n");LUPA开源社区K_H8R)g7\ [

             return -1;LUPA开源社区0x.d^TL h8e

      }

/AJy)f8Y0

      /*检查密钥*/

O}^4b r0

      ret=EC_KEY_check_key(key1);LUPA开源社区T-C T8EP;Q$w z7g

      if(ret!=1)

'xK&XqW5C3q{0

      {LUPA开源社区c4I$Qv G3F-Fjt.C

             printf("check key err.\n");

)N.|f#gS'M:sD%TUA0

             return -1;LUPA开源社区]!YxLn~ IH _

      }

3h J$Mf?0

      /*获取密钥大小*/LUPA开源社区~#m s%NdK(Gf

      size=ECDSA_size(key1);LUPA开源社区i.YVKsq

      printf("size %d \n",size);

:U8o6VLox0F0

      for(i=0;i<20;i++)

*]%b m*e*M a3Y0

             memset(&digest[i],i+1,1);

};P/\1mA_9HUm0

      signature=malloc(size);LUPA开源社区9MJ O^9~9ch

      ERR_load_crypto_strings();

2z2`)}c B s0

      berr=BIO_new(BIO_s_file());

5Nur4LA0

      BIO_set_fp(berr,stdout,BIO_NOCLOSE);

0Q)DU t+mOx#{3s0

      /*签名数据,本例未做摘要,可将digest中的数据看作是sha1摘要结果*/

b"@:H\ s4f#Y0

      ret=ECDSA_sign(0,digest,20,signature,&sig_len,key1);LUPA开源社区KJ6g^ y|

      if(ret!=1)LUPA开源社区&VsB,[j

      {LUPA开源社区xP/e3W.[

             ERR_print_errors(berr);LUPA开源社区]1},Y"s[C'b:f.k

             printf("sign err!\n");

i$s{tBSxQ0

             return -1;LUPA开源社区1k Uyr Bo#H`Ub

      }

_f+[c*UI3@ j0

      /*验证签名*/LUPA开源社区(]4]0KF%R~ X N

      ret=ECDSA_verify(0,digest,20,signature,sig_len,key1);

t?%}MA!S,_0

      if(ret!=1)LUPA开源社区-Mh EqYditf

      {

nlyBu+oC5ZS0sA0

             ERR_print_errors(berr);

u2d x JUq}|0

             printf("ECDSA_verify err!\n");

PC0Ayb;q7L0

             return -1;LUPA开源社区B1[Huch4zt3k$Ln

      }LUPA开源社区4W'd#~3aG&V9fL {

      /*获取对方公钥,不能直接引用*/

u!c}W_P xK\ wp0

      pubkey2 = EC_KEY_get0_public_key(key2);

/D u-pq"R&KL6~ m0

      /*生成一方的共享密钥*/LUPA开源社区n;F S:q.k Qmr

      len1=ECDH_compute_key(shareKey1, 128, pubkey2, key1, NULL);

5I1m.W+@6~5V:b0

      pubkey1 = EC_KEY_get0_public_key(key1);LUPA开源社区3fe.f&]m"m]2s)E

      /*生成另一方共享密钥*/LUPA开源社区$t5mJ+Q`

      len2=ECDH_compute_key(shareKey2, 128, pubkey1, key2, NULL);LUPA开源社区9Nr9L'{?(F5{t

      if(len1!=len2)LUPA开源社区(q(K m~!o9V*w

      {LUPA开源社区LNbORc~t

             printf("err\n");LUPA开源社区$Eg,i4[3ZU

      }

J'rK[x1d i_0

      else

#M(`k&y GE6k0

      {LUPA开源社区 qroU\S"h

             ret=memcmp(shareKey1,shareKey2,len1);

:\*@4~+v o0

             if(ret==0)

j/V!B?&d\3~Q0

                    printf("生成共享密钥成功\n");

#FH!@x9D @!Q0

             elseLUPA开源社区DfPo"V(oVH5l4r

                    printf("生成共享密钥失败\n");LUPA开源社区)DS5Su"f.B

      }LUPA开源社区:sl-d4|p:[N~

      printf("test ok!\n");LUPA开源社区:o se-t/?q-?(vT

      BIO_free(berr);LUPA开源社区"\[,g a*`%|8~

      EC_KEY_free(key1);

-Hq,`&KO?OR0

      EC_KEY_free(key2);

,k}7Bjh ob0

      free(signature);LUPA开源社区4uAG/JN(^~4v4Z

      free(curves);

WD1A;Q };Fd0

      return 0;

S-xH4R+M_0

}

'R-g7Rzj Z4m-C0

TAG:

forxy 引用 删除 forxy   /   2008-06-24 11:05:29
椭圆曲线章节有更新,请从open_ssl@126.com收取。
 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

日历

« 2008-08-20  
     12
3456789
10111213141516
17181920212223
24252627282930
31      

数据统计

  • 访问量: 23024
  • 日志数: 54
  • 图片数: 1
  • 文件数: 1
  • 建立时间: 2006-05-07
  • 更新时间: 2008-08-06

RSS订阅

Open Toolbar