zoukankan      html  css  js  c++  java
  • OPENSSL编程 第二十章 椭圆曲线

    20.1  ECC介绍

    椭圆曲线算法可以看作是定义在特殊集合下数的运算,满足一定的规则。椭圆曲线在如下两个域中定义:Fp域和F2m域。

           Fp域,素数域,p为素数;

           F2m域:特征为2的有限域,称之为二元域或者二进制扩展域。该域中,元素的个数为2m个。

    椭圆曲线标准文档如下:

    1)    X9.62

    Public Key Cryptography For The Financial Services Industry: The Elliptic Curve Digital Signature Algorithm (ECDSA);

    2)    SEC 1

    SEC 1:Elliptic Curve Cryptography;

    3)    SEC 2

    SEC 2: Recommended Elliptic Curve Domain Parameters;

    4)    NIST

    (U.S.) National Institute of Standards and Technology,美国国家标准。

    这些标准一般都描述了Fp域和F2m域、椭圆曲线参数、数据转换、密钥生成以及推荐了多种椭圆曲线。

    一些术语说明:

    1)    椭圆曲线的阶(order of a curve)

    椭圆曲线所有点的个数,包含无穷远点;

    2)    椭圆曲线上点的阶(order of a point)

    P为椭圆曲线上的点,nP=无穷远点,n取最小整数,既是P的阶;

    3)    基点(base point)

    椭圆曲线参数之一,用G表示,是椭圆曲线上都一个点;

    4)    余因子(cofactor)

    椭圆曲线的余因子,用h表示,为椭圆曲线点的个数/基点的阶

    5)    椭圆曲线参数:

    素数域:

    (p,a,b,G,n,h)

    其中,p为素数,确定Fp,a和b确定椭圆曲线方程,G为基点,n为G的阶,h为余因子。

    二进制扩展域:

    (m,f(x),a,b,G,n,h)

    其中,m确定F2m,f(x)为不可约多项式,a和b用于确定椭圆曲线方程,G为基点,n为G的阶,h为余因子。

    6)    椭圆曲线公钥和私钥

           椭圆曲线的私钥是一个随机整数,小于n;

           椭圆曲线的公钥是椭圆曲线上的一个点:Q=私钥*G。

    20.2  openssl的ECC实现

           Openssl实现了ECC算法。ECC算法系列包括三部分:ECC算法(crypto/ec)、椭圆曲线数字签名算法ECDSA (crypto/ecdsa)以及椭圆曲线密钥交换算法ECDH(crypto/ecdh)。

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

    1)      数据结构

    Ø  椭圆曲线数据结构:EC_GROUP,该结构不仅包含各个参数,还包含了各种算法;

    Ø  点的表示:EC_POINT,其中的大数X、Y和Z为雅克比投影坐标;

    Ø  EC_CURVE_DATA:用于内置椭圆曲线,包含了椭圆曲线的各个参数;

    Ø  密钥结构

    椭圆曲线密钥数据结构如下,定义在crypto/ec_lcl.h中,对用户是透明的。

              

    2)   密钥生成

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

    3)签名值数据结构

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

           typedef struct ECDSA_SIG_st

    {

                  BIGNUM *r;

                  BIGNUM *s;

    } ECDSA_SIG;

    4)    签名与验签

    对照签名结果,研究其是如何生成的。crypto/ecdsa/ ecs_sign.c实现了签名算法,crypto/ecdsa/ ecs_vrf.c实现了验签。

           5)  密钥交换

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

    文件说明:

    EC_METHOD实现

    ec2_smpl.c            F2m  二进制扩展域上的EC_METHOD实现;

    ecp_mont.c     Fp   素数域上的EC_METHOD实现,(Montgomery 蒙哥马利)

    ecp_smpl.c     Fp   素数域上的EC_METHOD实现;

    ecp_nist.c       Fp   素数域上的EC_METHOD实现;

    ec2_mult.c

           F2m上的乘法;

    ec2_smpt.c

           F2m上的压缩算法;

    ec_asn1.c

           asn1编解码;

    ec_check.c

           椭圆曲线检测;

    ec_curve.c

           内置的椭圆曲线,

           NID_X9_62_prime_field:X9.62的素数域;

           NID_X9_62_characteristic_two_field:X9.62的二进制扩展域;

           NIST:美国国家标准

    ec_cvt.c

           给定参数生成素数域和二进制扩展域上的椭圆曲线;

    ec_err.c

           错误处理;

    ec_key.c

           椭圆曲线密钥EC_KEY函数;

    ec_lib.c

           通用库实现,一般会调用底层的EC_METHOD方法;

    ec_mult.c

           This file implements the wNAF-based interleaving multi-exponentation method乘法;

    ec_print.c

    数据与椭圆曲线上点的相互转化;

    ectest.c

           测试源码,可以参考此源码学习椭圆曲线函数。

    ec.h

           对外头文件;

    ec_lcl.h

                                内部头文件,数据结构一般在此定义。

    20.3  主要函数

    20.3.1参数设置

    1)    int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,

            const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)

    说明:设置二进制域椭圆曲线上点point的几何坐标;

    2)    int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,

            const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)

    说明:设置素数域椭圆曲线上点point的几何坐标;

    3)   int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,const BIGNUM *x, int y_bit, BN_CTX *ctx)

    说明:二进制域椭圆曲线,给定压缩坐标x和y_bit参数,设置point的几何坐标;用于将Octet-String转化为椭圆曲线上的点;

    4)    int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,        const BIGNUM *x, int y_bit, BN_CTX *ctx)

    说明:素数域椭圆曲线,给定压缩坐标x和y_bit参数,设置point的几何坐标;用于将Octet-String转化为椭圆曲线上的点;

    5)    int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,

            const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)

    说明:素数域椭圆曲线group,设置点point的投影坐标系坐标x、y和z;

    6)    int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)

    说明:将点point设为无穷远点

    7)    int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)

    说明:设置二进制域椭圆曲线参数;

    8)    int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)

    说明:设置素数域椭圆曲线参数;

    9)    int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor)

    说明:设置椭圆曲线的基G;generator、order和cofactor为输入参数;

    10)  size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)

    说明:设置椭圆曲线随机数,用于生成a和b;

    11)  EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)

    说明:生成二进制域上的椭圆曲线,输入参数为p,a和b;

    12)  EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)

    说明:生成素数域上的椭圆曲线。

    20.3.2参数获取

    1)    const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)

    说明:获取椭圆曲线的基(G);

    2)    unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)

    说明:获取椭圆曲线参数的随机数,该随机数可选,用于生成椭圆曲线参数中的a和b;

    3)  int EC_GROUP_get_basis_type(const EC_GROUP *group)

    说明:获取二进制域多项式的类型;

    4)  int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx)

    说明:获取椭圆曲线的余因子。cofactor为X9.62中定义的h,值为椭圆曲线点的个数/基点的阶,即:cofactor = #E(Fq)/n。

    5)  int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)

    说明:获取二元域椭圆曲线的三个参数,其中p可表示多项式;

    6)    int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)

    说明:获取素数域椭圆曲线的三个参数;

    7)    int EC_GROUP_get_curve_name(const EC_GROUP *group)

    说明:获取椭圆曲线名称,返回其NID;

    8)    int EC_GROUP_get_degree(const EC_GROUP *group)

    说明:获取椭圆曲线密钥长度。对于素数域Fp来说,是大数p的长度;对二进制域F2m来说,等于m;

    9)    int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)

    说明:获取椭圆曲线的阶;

    10)  int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1,

           unsigned int *k2, unsigned int *k3)

    int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k)

    说明:获取多项式参数;

    11)   int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point,BIGNUM *x, BIGNUM *y, BN_CTX *ctx)

    说明:获取二进制域椭圆曲线上某个点的x和y的几何坐标;

    12)  int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,        BIGNUM *x, BIGNUM *y, BN_CTX *ctx)

    说明:获取素数域上椭圆曲线上某个点的x和y的几何坐标;

    13)  int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)

    说明:获取素数域椭圆曲线上某个点的x、y和z的投影坐标系坐标。

    20.3.3转化函数

    1)    EC_POINT *EC_POINT_bn2point(const EC_GROUP *group,                           const BIGNUM *bn,EC_POINT *point,BN_CTX *ctx)

    说明:将大数转化为椭圆曲线上的点;

    2)    EC_POINT *EC_POINT_hex2point(const EC_GROUP *group,                            const char *buf,EC_POINT *point,BN_CTX *ctx)

    说明:将buf中表示的十六进制数据转化为椭圆曲线上的点;

    3)    int BN_GF2m_poly2arr(const BIGNUM *a, unsigned int p[], int max)

    说明:将大数转化为多项式的各个项;

    4)    int BN_GF2m_arr2poly(const unsigned int p[], BIGNUM *a)

    说明:将多项式的各个项转化为大数;

    5)    int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)

    说明:将椭圆曲线group上点的point转化为几何坐标系;

    6)    int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,

            const unsigned char *buf, size_t len, BN_CTX *ctx)

    说明:将buf中点数据转化为椭圆曲线上的点,len为数据长度;

    7)    BIGNUM *EC_POINT_point2bn(const EC_GROUP *group,const EC_POINT *point,                          point_conversion_form_t form,BIGNUM *ret,BN_CTX *ctx)

    说明:将椭圆曲线上的点转化为大数,其中from为压缩方式,可以是POINT_CONVERSION_COMPRESSED、POINT_CONVERSION_UNCOMPRESSED或POINT_CONVERSION_HYBRID,可参考x9.62;

    8)    char *EC_POINT_point2hex(const EC_GROUP *group, const EC_POINT *point,                        point_conversion_form_t form,BN_CTX *ctx)

    说明:将椭圆曲线上的点转化为十六进制,并返回该结果;

    9)    size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,unsigned char *buf, size_t len, BN_CTX *ctx)

    说明:将椭圆曲线上的点转化为Octet-String,可分两次调用,用法见EC_POINT_point2bn的实现。

    20.3.4其他函数

    1)    size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems)

    文件:ec_curve.c

    说明:获取内置的椭圆曲线。当输入参数r为NULL或者nitems为0时,返回内置椭圆曲线的个数,否则将各个椭圆曲线信息存放在r中。

    示例:

    2)    const EC_METHOD *EC_GF2m_simple_method(void)

    说明:返回二进制域上的方法集EC_METHOD

    3)  const EC_METHOD *EC_GFp_mont_method(void)

    const EC_METHOD *EC_GFp_nist_method(void)

    const EC_METHOD *EC_GFp_simple_method(void)

    返回素数域上的方法集EC_METHOD

    4)  int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)

    说明:检查椭圆曲线,成功返回1。

    5)  int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)

    说明:检查椭圆曲线表达式。对于素数域的椭圆曲线来说,该函数会调用ec_GFp_simple_group_check_discriminant函数,主要检查4*a^3 + 27*b^2 != 0 (mod p)。而对于二进制域的椭圆曲线,会调用ec_GF2m_simple_group_check_discriminant, 检查y^2 + x*y = x^3 + a*x^2 + b 是否是一个椭圆曲线并且 b !=0。

    6)  int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)

    说明:通过比较各个参数来确定两个椭圆曲线是否相等;

    7)  int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)

    EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)

    说明:椭圆曲线拷贝函数;

    9)  EC_GROUP *EC_GROUP_new_by_curve_name(int nid)

    说明:根据NID获取内置的椭圆曲线;

    10)  int EC_KEY_check_key(const EC_KEY *eckey)

    说明:检查椭圆曲线密钥;

    11)  int EC_KEY_generate_key(EC_KEY *eckey)

    说明:生成椭圆曲线公私钥;

    12)  int EC_KEY_print(BIO *bp, const EC_KEY *x, int off)

    说明:将椭圆曲线密钥信息输出到bio中,off为缩进量;

    13)  int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)

    说明:椭圆曲线上点的加法;

    14)  int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)

    说明:求椭圆曲线上某点a的逆元,a既是输入参数,也是输出参数;

    15)  int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)

    说明:判断椭圆曲线上的点point是否是无穷远点;

    16)  int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)

    说明:判断一个点point是否在椭圆曲线上;

    17)  int     ECDSA_size

           说明:获取ECC密钥大小字节数。

    18)ECDSA_sign

           说明:签名,返回1表示成功。

    19)ECDSA_verify

           说明:验签,返回1表示合法。

    20)EC_KEY_get0_public_key

           说明:获取公钥。

    21)EC_KEY_get0_private_key

           说明:获取私钥。

    22)ECDH_compute_key

           说明:生成共享密钥

    23)EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)

           说明:DER解码将椭圆曲线密钥;

    24)int     i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)

           说明:将椭圆曲线密钥DER编码;

    20.4  编程示例

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

    更多底层函数的使用示例可参考ec/ectest.c,特别是用户自行定义椭圆曲线参数。

    转自:

    http://www.pengshuo.me/2014/04/22/openssl%E7%BC%96%E7%A8%8B-%E7%AC%AC%E4%BA%8C%E5%8D%81%E7%AB%A0-%E6%A4%AD%E5%9C%86%E6%9B%B2%E7%BA%BF/

  • 相关阅读:
    drf 三大认证详解
    管理表页面的创建
    电脑自动关机设置
    jwt 认证规则
    视图家族练习
    JQuery 数组获取和删除元素
    JQurey 添加和删除元素
    Java 占位符
    Redis
    线程
  • 原文地址:https://www.cnblogs.com/testlife007/p/6704435.html
Copyright © 2011-2022 走看看