《openssl 编程》之 椭圆曲线
上一篇 / 下一篇 2007-11-15 10:26:40 / 个人分类:信息安全
第二十章 椭圆曲线
20.1 ECC介绍
椭圆曲线(ECC)算法是一种公钥算法,它比流行的RSA算法有很多优点:LUPA开源社区qN4L/du8iYaOR
1)安全性能更高 , 如160位ECC与1024位RSA、DSA有相同的安全强度。LUPA开源社区!T\*eS D4Xq
2)计算量小,处理速度快, 在私钥的处理速度上(解密和签名),ECC比RSA、DSA快得多。
Z8N}^{TK03)存储空间占用小 ECC的密钥尺寸和系统参数与RSA、DSA相比要小得多, 所以占用的存储空间小得多。
uIw*k-\[%J:Y04)带宽要求低。LUPA开源社区)JE7x2D3r3o zQr
20.2 openssl的ECC实现
Openssl实现了ECC算法。ECC算法系列包括三部分:ECC算法(crypto/ec)、椭圆曲线数字签名算法ECDSA (crypto/ecdsa)以及椭圆曲线密钥交换算法ECDH(crypto/dh)。LUPA开源社区8nV`k?b
研究椭圆曲线需要注意的有:
c1K0YKYe%b-B d01) 密钥数据结构LUPA开源社区 b5E I}"J i&CC-EGb
主要是公钥和私钥数据结构。椭圆曲线密钥数据结构如下,定义在crypto/ec_lcl.h中,对用户是透明的。LUPA开源社区A4JE ktDy9}Yd
struct ec_key_stLUPA开源社区8^;v DS9~2i5P
{
,e @'b7tS0int version;LUPA开源社区)Io F1H ]5C+s/K
EC_GROUP *group;
.W8b,p/O/wC U)y0b8Z0EC_POINT *pub_key;LUPA开源社区(z L^] }
BIGNUM*priv_key;LUPA开源社区2]J!Fp%O
/*其他项*/LUPA开源社区(s d9?N9Bn
}
[#Wm*Kt FxY|(p02) 密钥生成
4Yv2M_ l0对照公钥和私钥的表示方法,非对称算法不同有各自的密钥生成过程。椭圆曲线的密钥生成实现在crytpo/ec/ec_key.c中。Openssl中,椭圆曲线密钥生成时,首先用户需要选取一种椭圆曲线(openssl的crypto/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中,如下:
%|.UL6US0typedef struct ECDSA_SIG_stLUPA开源社区aI5b/V s v]
{
;C'X{~V!p0BIGNUM *r;LUPA开源社区Y Pu3^'V p/e,mOGw
BIGNUM *s;
f(dS(PTW0} ECDSA_SIG;
bF'F"vr,}04) 签名与验签
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实现了密钥交换算法。
2VB sfM"V#e"z)p|020.3 主要函数
1) EC_get_builtin_curves
C!v0OgC2t)bb;J0获取椭圆曲线列表。LUPA开源社区&L+~Tdv@blb
2) EC_GROUP_new_by_curve_nameLUPA开源社区&^t+q _wa(A~
根据指定的椭圆曲线来生成密钥参数。LUPA开源社区1RAyc I
3) int EC_KEY_generate_key
$`Xf-IkJ/t ]J0根据密钥参数生成ECC公私钥。
1F]]]*V-XI2d-ld04) int EC_KEY_check_keyLUPA开源社区p*j/j&K!wO8K W/Wr
检查ECC密钥。LUPA开源社区U$F[4Aj8a&Y3o1l
5) int ECDSA_sizeLUPA开源社区^.IM$e;O)eO6I'H
获取ECC密钥大小字节数。LUPA开源社区.huLjxau$DB$M
6) ECDSA_sign
;j-R ]:dw0签名,返回1表示成功。LUPA开源社区/rda?N6o [([M|
7) ECDSA_verify
XZ9L+F5i4SZM0验签,返回1表示合法。
2lQ8_5v6]%E#Z*fG/d08) EC_KEY_get0_public_key
n?ZUQk0获取公钥。
I{#b/Tsp2^Z#_09) EC_KEY_get0_private_keyLUPA开源社区`/R$j4P4b;?P3as
获取私钥。LUPA开源社区h"C5q+xmh"e S
10)ECDH_compute_key
rJ%|!EY/dvI0生成共享密钥
k FzMg020.4 编程示例
下面的例子生成两对ECC密钥,并用它做签名和验签,并生成共享密钥。
|9x;U'J?J-rAd9O0#include <string.h>LUPA开源社区p:VP,_%r0G{
#include <stdio.h>LUPA开源社区;Gu?&o"c(RNaWZ
#include <openssl/ec.h>LUPA开源社区@U2N;hy"M2j
#include <openssl/ecdsa.h>LUPA开源社区f V!i y$Tu$LK
#include <openssl/objects.h>
qyIQ8bi0#include <openssl/err.h>LUPA开源社区9}h CX\ G:s
int main()LUPA开源社区 O*}-Y v#O4[SD8V|D
{
%mQ-C$kOz`+`0EC_KEY *key1,*key2;LUPA开源社区+{zP#J8g
EC_POINT *pubkey1,*pubkey2;
"Ic#k!_;s,jU&A0EC_GROUP *group1,*group2;
!D#u&x(}t)EH0int ret,nid,size,i,sig_len;LUPA开源社区9J'r1?p'xL
unsigned char*signature,digest[20];
-f!`$W7m$HEo0BIO *berr;
(|6s"|!whV8N0EC_builtin_curve *curves;LUPA开源社区,PmZa:EZ*S
int crv_len;
d,]Z1F2Z{*|ayN0char shareKey1[128],shareKey2[128];LUPA开源社区Q9]!mEgj"]
int len1,len2;
pPEO#s.NB!Q_R0/*构造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开源社区3Ewg{?-q u
printf("EC_KEY_new err!\n");
`}:SE;ZCWo)i0return -1;
4uJ-l NB.H7u'D']b0}LUPA开源社区,sopXr1j*\!V.RL
key2=EC_KEY_new();
wF"^$r$k0if(key2==NULL)
Q!~:`,gk%NC0{
7i;z SZNJk6A9my0Z9eg0printf("EC_KEY_new err!\n");
M-][.gG!o0return -1;
,NN2o6N]bjN1VA0}
0x,b`lmz1?P0/*获取实现的椭圆曲线个数*/
?,aw)yMB&p0crv_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'w0EC_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)p0nid=curves[25].nid;
s b}4M_ Ap)O(D[ Yj%Y0/*根据选择的椭圆曲线生成密钥参数group */