OpenSSL ECC algorithm

Source: Internet
Author: User
Tags openssl

The ECC algorithm implemented by OpenSSL includes three parts: ECC algorithm (CRYPTO/EC), Elliptic Curve Digital Signature Algorithm ECDSA (CRYPTO/ECDSA) and Elliptic curve key exchange algorithm ECDH (CRYPTO/DH). Key data Structure

The key data structure is defined in the Openssl-1.1.0c\crypto\ec\ec_lcl.h file.

struct Ec_key_st {
    const ec_key_method *meth;
    ENGINE *engine;
    int version;
    Ec_group *group; Key parameters
    Ec_point *pub_key;
    Bignum *priv_key;
    unsigned int enc_flag;
    point_conversion_form_t Conv_form;
    int references;
    int flags;
    Crypto_ex_data Ex_data;
    Crypto_rwlock *lock;
};
Key Generation

The key generation of elliptic curves is implemented in CRYTPO/EC/EC_KEY.C. In OpenSSL, when the elliptic curve key is generated, the user first needs to select an elliptic curve (67 kinds of built-in CRYPTO/EC/EC_CURVE.C are implemented in OpenSSL, call ec_get_builtin_curves to get the list), Then, according to the selected elliptic Curve calculation key generation parameter group, and finally according to the key parameter group next to the public private key. Signature Value data structure

As with DSA signature values, the signature result of ECDSA is expressed as two items. The ECDSA signature result data structure is defined in the crypto\ec\ec_lcl.h.

struct Ecdsa_sig_st {
    bignum *r;
    Bignum *s;
};
Signature and verification

CRYPTO/EC/ECDSA_SIGN.C implements the signature algorithm,
The CRYPTO/EC/ECDSA_VRF.C realizes the key exchange of the verification sign

Crypto/ec/ec DH_OSSL.C implements the key exchange algorithm. main Functions

1) ec_get_builtin_curves
Gets the list of elliptic curves.

size_t ec_get_builtin_curves (Ec_builtin_curve *r, size_t nitems)
{
    size_t i, min;

    if (r = = NULL | | nitems = = 0)
        return curve_list_length;

    Min = Nitems < curve_list_length? Nitems:curve_list_length;

    for (i = 0; i < min; i++) {
        R[i].nid = Curve_list[i].nid;
        R[i].comment = curve_list[i].comment;
    }

    return curve_list_length;
}

2) Ec_group_new_by_curve_name
Generates a key parameter based on the specified ellipse curve.

Ec_group *ec_group_new_by_curve_name (int. nid)
{
    size_t i;
    Ec_group *ret = NULL;

    if (Nid <= 0)
        return NULL;

    for (i = 0; i < curve_list_length; i++)
        if (Curve_list[i].nid = = nid) {
            ret = Ec_group_new_from_data (curve_list [i]);
            break;
        }

    if (ret = = NULL) {
        ecerr (ec_f_ec_group_new_by_curve_name, ec_r_unknown_group);
        return NULL;
    }

    Ec_group_set_curve_name (ret, nid);

    return ret;
}

3) int Ec_key_generate_key
The ECC public private key is generated according to the key parameter.

int Ec_key_generate_key (Ec_key *eckey)
{
    if (Eckey = = NULL | | eckey->group = NULL) {
        Ecerr (ec_f_ec_ Key_generate_key, err_r_passed_null_parameter);
        return 0;
    }
    if (Eckey->meth->keygen! = NULL)
        return Eckey->meth->keygen (Eckey);
    Ecerr (Ec_f_ec_key_generate_key, ec_r_operation_not_supported);
    return 0;
}

4) int Ec_key_check_key
Check the ECC key.

int Ec_key_check_key (const ec_key *eckey)
{
    if (Eckey = = NULL | | eckey->group = NULL | | eckey->pub_key = = N ULL) {
        ecerr (Ec_f_ec_key_check_key, err_r_passed_null_parameter);
        return 0;
    }

    if (Eckey->group->meth->keycheck = = NULL) {
        ecerr (Ec_f_ec_key_check_key, Err_r_should_not_have_been_ called);
        return 0;
    }

    Return Eckey->group->meth->keycheck (Eckey);
}

5) int Ecdsa_size
Gets the number of ECC key size bytes.

int ecdsa_size (const ec_key *r)
{
    int ret, I;
    Asn1_integer BS;
    unsigned char buf[4];
    Const Ec_group *group;

    if (r = = NULL)
        return 0;
    Group = Ec_key_get0_group (r);
    if (group = = NULL)
        return 0;

    i = Ec_group_order_bits (GROUP);
    if (i = = 0)
        return 0;
    Bs.length = (i + 7)/8;
    Bs.data = buf;
    Bs.type = V_asn1_integer;
    /* If The top bit is set the ASN1 encoding is 1 larger. */
    buf[0] = 0xFF;

    i = I2d_asn1_integer (&bs, NULL);
    i + = i;                     /* R and S *
    /ret = asn1_object_size (1, I, v_asn1_sequence);
    return (ret);
}

6) Ecdsa_sign
The signature, which returns 1, indicates success.

int ecdsa_sign (int type, const unsigned char *dgst, int dlen, unsigned char
               *sig, unsigned int *siglen, Ec_key *eckey)
{
    return ecdsa_sign_ex (Type, dgst, Dlen, SIG, Siglen, NULL, NULL, Eckey);
}

int ecdsa_sign_ex (int type, const unsigned char *dgst, int dlen,
                  unsigned char *sig, unsigned int *siglen, const BIGNU M *KINV,
                  const bignum *r, Ec_key *eckey)
{
    if (eckey->meth->sign! = NULL)
        return eckey->meth-& Gt;sign (Type, dgst, Dlen, Sig, Siglen, KINV, R, Eckey);
    Ecerr (EC_F_ECDSA_SIGN_EX, ec_r_operation_not_supported);
    return 0;
}

7) Ecdsa_verify
Check, return 1 is legal.

/*-
 * Returns
 *      1:correct Signature
 *      0:incorrect Signature
 *     -1:error
*/int ecdsa_verify (int type, const unsigned char *dgst, int dgst_len,
                 const unsigned char *sigbuf, int sig_len, Ec_key *ecke Y)
{
    if (eckey->meth->verify! = NULL)
        return eckey->meth->verify (Type, dgst, Dgst_len, Sigbuf, Sig_len,
                                   eckey);
    Ecerr (ec_f_ecdsa_verify, ec_r_operation_not_supported);
    return 0;
}

8) Ec_key_get0_public_key
Gets the public key.

Const Ec_point *ec_key_get0_public_key (const ec_key *key)
{
    return key->pub_key;
}

int Ec_key_set_public_key (Ec_key *key, const ec_point *pub_key)
{
    if (key->meth->set_public! = NULL
        && key->meth->set_public (key, pub_key) = = 0)
        return 0;
    Ec_point_free (Key->pub_key);
    Key->pub_key = Ec_point_dup (Pub_key, key->group);
    return (Key->pub_key = = NULL)? 0:1;
}

9) Ec_key_get0_private_key
Gets the private key.

Const Bignum *ec_key_get0_private_key (const ec_key *key)
{
    return key->priv_key;
}

int Ec_key_set_private_key (Ec_key *key, const bignum *priv_key)
{
    if (Key->group = = NULL | | key->group- >meth = = NULL)
        return 0;
    if (key->group->meth->set_private! = NULL
        && key->group->meth->set_private (Key, Priv_ key) = = 0)
        return 0;
    if (key->meth->set_private! = NULL
        && key->meth->set_private (key, priv_key) = = 0)
        return 0;
    Bn_clear_free (Key->priv_key);
    Key->priv_key = Bn_dup (Priv_key);
    return (Key->priv_key = = NULL)? 0:1;
}
Ecdh_compute_key
Generate a shared secret
int Ecdh_compute_key (void *out, size_t outlen, const ec_point *pub_key,
                     const ec_key *eckey,
                     void * (*KDF) (const V OID *in, size_t inlen, void *out,
                                   size_t *outlen))
{
    unsigned char *sec = NULL;
    size_t Seclen;
    if (Eckey->meth->compute_key = = NULL) {
        ecerr (Ec_f_ecdh_compute_key, ec_r_operation_not_supported);
        return 0;
    }
    if (Outlen > Int_max) {
        ecerr (Ec_f_ecdh_compute_key, ec_r_invalid_output_length);
        return 0;
    }
    if (!eckey->meth->compute_key (&sec, &seclen, Pub_key, Eckey))
        return 0;
    if (KDF = NULL) {
        kdf (sec, Seclen, out, &outlen);
    } else {
        if (Outlen > Seclen)
            outlen = secle n;
        memcpy (out, sec, Outlen);
    }
    Openssl_clear_free (sec, Seclen);
    return outlen;
}
Programming Examples
#include <string.h> #include <stdio.h> #include <openssl/ec.h> #include <openssl/ecdh.h> # Include <openssl/ecdsa.h> #include <openssl/objects.h> #include <openssl/err.h> int main () {Ec_key
    *key1,*key2;
    Const Ec_point *pubkey1,*pubkey2;
    Ec_group *group1,*group2;
    unsigned int ret,nid,size,i,sig_len;
    unsigned char *signature,digest[20];
    BIO *berr;
    Ec_builtin_curve *curves;
    int Crv_len;
    Char sharekey1[128],sharekey2[128];
    int len1,len2;
    /* Construct EC_KEY data structure */key1=ec_key_new ();
        if (key1==null) {printf ("ec_key_new err!\n");
    return-1;
    } key2=ec_key_new ();
        if (key2==null) {printf ("ec_key_new err!\n");
    return-1;
    }/* Gets the number of elliptic curves implemented */Crv_len = ec_get_builtin_curves (NULL, 0);
    Curves = (Ec_builtin_curve *) malloc (sizeof (ec_builtin_curve) * Crv_len);
    /* Get elliptic curve list */ec_get_builtin_curves (curves, Crv_len); /* NID=CURVES[0].NID; There will be an error because the key is too short */* Select an elliptic curve */Nid=curves[25].nid;
    /* Generate key parameters from selected elliptic curves Group */group1=ec_group_new_by_curve_name (NID);
        if (group1==null) {printf ("Ec_group_new_by_curve_name err!\n");
    return-1;
    } group2=ec_group_new_by_curve_name (NID);
        if (group1==null) {printf ("Ec_group_new_by_curve_name err!\n");
    return-1;
    }/* Set key parameters */Ret=ec_key_set_group (KEY1,GROUP1);
        if (ret!=1) {printf ("Ec_key_set_group err.\n");
    return-1;
    } ret=ec_key_set_group (KEY2,GROUP2);
        if (ret!=1) {printf ("Ec_key_set_group err.\n");
    return-1;
    }/* Generate key */Ret=ec_key_generate_key (key1);
        if (ret!=1) {printf ("Ec_key_generate_key err.\n");
    return-1;
    } ret=ec_key_generate_key (Key2);
        if (ret!=1) {printf ("Ec_key_generate_key err.\n");
    return-1;
    }/* Check the key */Ret=ec_key_check_key (key1);
if (ret!=1)    {printf ("Check key err.\n");
    return-1;
    }/* Gets the key size */size=ecdsa_size (key1);
    printf ("Size%d \ n", size);
    for (i=0;i<20;i++) memset (&digest[i],i+1,1);
    signature= (unsigned char*) malloc (size);
    Err_load_crypto_strings ();
    Berr=bio_new (Bio_s_file ());
    BIO_SET_FP (Berr,stdout,bio_noclose);
    /* Signature data, this example does not make a summary, the data in digest can be considered as SHA1 summary results */ret=ecdsa_sign (0,digest,20,signature,&sig_len,key1);
        if (ret!=1) {err_print_errors (BERR);
        printf ("sign err!\n");
    return-1;
    }/* Verify signature */Ret=ecdsa_verify (0,digest,20,signature,sig_len,key1);
        if (ret!=1) {err_print_errors (BERR);
        printf ("Ecdsa_verify err!\n");
    return-1;
    }/* Get the other public key, cannot directly reference */Pubkey2 = Ec_key_get0_public_key (Key2);
    /* Generate a shared key for one party */len1= Ecdh_compute_key (ShareKey1, Pubkey2, Key1, NULL);
    Pubkey1 = Ec_key_get0_public_key (Key1); /* Generate another party shared key */len2= Ecdh_coMpute_key (ShareKey2, N, Pubkey1, Key2, NULL);
    if (len1!=len2) {printf ("err\n");
        } else {ret=memcmp (SHAREKEY1,SHAREKEY2,LEN1);
        if (ret==0) printf ("Generate shared key succeeded \ n");
    else printf ("Generate shared key failed \ n");
    } printf ("Test ok!\n");
    Bio_free (BERR);
    Ec_key_free (Key1);
    Ec_key_free (Key2);
    Free (signature);
    Free (curves);
return 0; }

Run Result:

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.