Introduction to large numbers of OpenSSL and RSA Functions

Source: Internet
Author: User
Tags random seed

This section describes the RSA functions of OpenSSL, which are helpful for learning and implementing RSA Algorithms.

Basic Structure of RSA
struct

 

     {

 

      int pad;

 

      long version;

 

      const RSA_METHOD *meth;

 

      ENGINE *engine;

 

      BIGNUM *n;         n=p*q

 

Bignum * E; public encryption index, usually 65537 (ox10001)

 

Bignum * D; Private Key

 

Bignum * P; big prime number P

 

Bignum * q; q

 

      BIGNUM *dmp1;      d mod (p-1)

 

      BIGNUM *dmq1;      d mod (q-1)

 

      BIGNUM *iqmp;      (inverse of q) mod p

 

      int references;

 

      int flags;

 

        // ...

 

      }RSA;

 

2. initialize the Function
RSA * rsa_new (void); Initialize an RSA Structure

 

Void rsa_free (RSA * RSA); releases an RSA Structure

 

3. RSA private key generation function
RSA * rsa_generate_key (INT num, unsigned long e, void (* callback) (INT, Int, void *), void * cb_arg); generates a key pair modeled as num, E is the public encryption index, generally 65537 (ox10001). If the last two parameters are not null, some calls will be made. Before generating a key pair, you must specify a random seed.

 

4. Number of digits judgment Function
Int rsa_size (const RSA * RSA); returns the number of digits of the RSA modulo, which is used to determine the size of the space to be allocated to the encryption value.

 

Int rsa_check_key (RSA * RSA); tests whether p and q are prime numbers, n = p * Q,D * E = 1 Mod (P1 * q-1), DMP1, dmq1, and iqmp are all set correctly.

 

5. rsa_method function of RSA
To understand the operation of RSA, you must understand rsa_method. Let's first look at the structure of rsa_method.

 

typedef struct rsa_meth_st

 

        {

 

        const char *name;

 

        int (*rsa_pub_enc)(int flen,const unsigned char *from,

 

            unsigned char *to,RSA *rsa,int padding);

 

        int (*rsa_pub_dec)(int flen,const unsigned char *from,

 

             unsigned char *to,RSA *rsa,int padding);

 

        int (*rsa_priv_enc)(int flen,const unsigned char *from,

 

                unsigned char *to, RSA *rsa,int padding);

 

        int (*rsa_priv_dec)(int flen,const unsigned char *from,

 

                unsigned char *to,RSA *rsa,int padding);

 

        int (*rsa_mod_exp)(BIGNUM *r0,const BIGNUM *I,RSA *rsa);        int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,

 

                const BIGNUM *m, BN_CTX *ctx,BN_MONT_CTX *m_ctx);

 

        int (*init)(RSA *rsa);          /* called at new */

 

        int (*finish)(RSA *rsa);        /* called at free */

 

        int flags;              /* RSA_METHOD_FLAG_* things */

 

        char *app_data;                  /* may be needed! */

 

        int (*rsa_sign)(int type,const unsigned char *m, unsigned int m_length,unsigned char *sigret, unsigned int *siglen, const RSA *rsa);

 

        int (*rsa_verify)(int dtype,const unsigned char *m, unsigned int m_length,unsigned char *sigbuf, unsigned int siglen, const RSA *rsa);

 

        } RSA_METHOD;

 

const RSA_METHOD *RSA_PKCS1_SSLeay(void);

 

const RSA_METHOD *RSA_null_method(void);

 

There are mainly the above two functions. The second function is called only when rsa_null is defined. In fact, this function cannot be called in the future, but it only outputs error information. The first method is commonly used. Let's take a look at its definition.

 

 const RSA_METHOD *RSA_PKCS1_SSLeay(void)

 

        {

 

        return(&rsa_pkcs1_eay_meth);

 

        }

 

static RSA_METHOD rsa_pkcs1_eay_meth={

 

        "Eric Young's PKCS#1 RSA",

 

        RSA_eay_public_encrypt,

 

        RSA_eay_public_decrypt, /* signature verification */

 

        RSA_eay_private_encrypt, /* signing */

 

        RSA_eay_private_decrypt,

 

        RSA_eay_mod_exp,

 

        BN_mod_exp_mont,

 

        RSA_eay_init,

 

        RSA_eay_finish,

 

        0, /* flags */

 

        NULL,

 

        0, /* rsa_sign */

 

        0  /* rsa_verify */

 

        };

 

From this we can see that generally, RSA-> meth-> rsa_pub_enc corresponds to rsa_eay_public_encrypt. When I first started to look at OpenSSL, the most rare thing was the pointer to the function, I don't know where RSA-> meth-> rsa_pub_enc corresponds. There are many such pointers in OpenSSL, which can be seen later. The following are some functions that can be easily understood when you set meth.

 

void RSA_set_default_method(const RSA_METHOD *meth);

 

 const RSA_METHOD *RSA_get_default_method(void);

 

 int RSA_set_method(RSA *rsa, const RSA_METHOD *meth);

 

 const RSA_METHOD *RSA_get_method(const RSA *rsa);

 

 int RSA_flags(const RSA *rsa);

 

 RSA *RSA_new_method(ENGINE *engine);

 

6. encryption and decryption functions
int RSA_public_encrypt(int flen, unsigned char *from,

 

    unsigned char *to, RSA *rsa, int padding);

 

 int RSA_private_decrypt(int flen, unsigned char *from,

 

    unsigned char *to, RSA *rsa, int padding);

 

 int RSA_private_encrypt(int flen, unsigned char *from,

 

    unsigned char *to, RSA *rsa,int padding);

 

 int RSA_public_decrypt(int flen, unsigned char *from,

 

unsigned char *to, RSA *rsa,int padding);

 

With section 4th, it is easy to understand these encryption and decryption functions.

 

Rsa_set_method (RSA, rsa_pkcs1_ssleay (), then rsa_public_encrypt corresponds to rsa_eay_public_encrypt, so that we can debug the public key encryption process. FLEN is the length of the information to be encrypted, from is the information to be encrypted, to is the encrypted information, generally to at least apply for bn_num_bytes (RSA-> N. Padding is a encryption/Decryption solution. PKCS #1 mainly provides two kinds of encryption scheme, RSAEX-OAEP and PSAES-PKCS1-v1_5 (anyway, there are two kinds of encryption process, a bit complex, it is mainly first to the first encryption of the data to be encrypted, such as RSAES-OAEP using EME-OAEP encoding, and then encrypted or decrypted ). Encoding functions have been compiled in OpenSSL:

 

case RSA_PKCS1_PADDING:

 

    i=RSA_padding_add_PKCS1_type_2(buf,num,from,flen);

 

#ifndef OPENSSL_NO_SHA

 

case RSA_PKCS1_OAEP_PADDING:        i=RSA_padding_add_PKCS1_OAEP(buf,num,from,flen,NULL,0);

 

#endif

 

case RSA_SSLV23_PADDING:

 

    i=RSA_padding_add_SSLv23(buf,num,from,flen);

 

 case RSA_NO_PADDING:

 

    i=RSA_padding_add_none(buf,num,from,flen);

 

After the code is compiled above, bn_mod_exp_mont is called to perform the modulo power. The final value is obtained, which is the specific encryption and decryption process. We can also find that there are two methods to input RSA during encryption: p, q ,... is null, only RSA-> D, and RSA-> N are not empty, so that the modulo power is calculated directly using RSA-> D and RSA-> N. If P, Q ..... if it is not empty, he will call the Chinese Remainder Theorem for encryption.

 

7. Signature Functions
int RSA_sign(int type, unsigned char *m, unsigned int m_len,

 

    unsigned char *sigret, unsigned int *siglen, RSA *rsa);

 

int RSA_verify(int type, unsigned char *m, unsigned int m_len,

 

    unsigned char *sigbuf, unsigned int siglen, RSA *rsa);

 

In fact, the signature is similar to encryption with the private key. Therefore, the signature function calls the private key encryption function. In OpenSSL, this signature function is rarely used separately, it is called for evp_signfinal. Therefore, if RSA is used for signature, rsa_private_encrypt and bn_mod_exp_mont are the most basic and all of them need to be called, the difference is that the signature information needs to be processed (the digest of the signature information is generally worth m)

 

8. File Writing Function
 int RSA_print(BIO *bp, RSA *x, int offset);

 

Int rsa_print_fp (File * FP, RSA * X, int offset); offset is used to adjust the output format. You can set a random number (for example, 2, 12, 16 ..)

 

9. Others
int RSA_blinding_on(RSA *rsa, BN_CTX *ctx);

 

void RSA_blinding_off(RSA *rsa);

 

To prevent time attacks, OpenSSL also generates a random factor during signature and attaches it to the private key.

 

  int RSA_sign_ASN1_OCTET_STRING(int dummy, unsigned char *m,unsigned int m_len, unsigned char *sigret, unsigned int *siglen,RSA *rsa);

 

  int RSA_verify_ASN1_OCTET_STRING(int dummy, unsigned char *m,unsigned int m_len, unsigned char *sigbuf, unsigned int siglen,RSA *rsa);

 

Use the private key to sign the eight-element string in the same principle as rsa_sign.
 
OpenSSL --

This article mainly introduces the big number calculation functions in OpenSSL, which will be of great value for future RSA Research and Implementation.

1. initialize the Function

 

Bignum * bn_new (void); generates a bignum structure.

 

Void bn_free (bignum * A); release a bignum structure. After the release, a = NULL;

 

Void bn_init (bignum *); Initialization of all items is 0, generally bn _ Init (& C)

 

Void bn_clear (bignum * A); all items in a are assigned 0, but the memory is not released.

 

Void bn_clear_free (bignum * A); It is equivalent to combining bn_free and bn_clear. Do not assign 0 values, or release space.

 

2. Context context function, which stores the intermediate process bn_ctx * bn_ctx_new (void) in calculation; apply for a new context structure

 

Void bn_ctx_init (bn_ctx * C); assign all items to 0. Generally, bn_ctx_init (& C)

 

Void bn_ctx_free (bn_ctx * C); release the context structure. After the release, c = NULL;

 

3. Copy and exchange functions
Bignum * bn_copy (bignum * a, const bignum * B); copy B to A, return a correctly, and return NULL if an error occurs.

 

Bignum * bn_dup (const bignum * A); creates a bignum structure, copies a to the new structure, and returns a null error.

 

Bignum * bn_swap (bignum * a, bignum * B); exchange a, B

 

4. bitwise Functions

 

Int bn_num_bytes (const bignum * A); returns the number of digits of A, which is widely used.

 

 int BN_num_bits(const BIGNUM *a);

 

Int bn_num_bits_word (bn_ulong W); it returns the number of meaningful bits, for example, 0x00000432 is 11.

 

5. basic computing functions

 

 int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);r=a+b

 

 int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);r=a-b

 

 int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx);r=a*b

 

Int bn_sqr (bignum * r, bignum * a, bn_ctx * CTX); r = A * a, the efficiency is higher than bn_mul (R, A,)

 

 int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *a, const BIGNUM *d,

 

         BN_CTX *ctx);d=a/b,r=a%b

 

 int BN_mod(BIGNUM *rem, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);r=a%b

 

 int BN_nnmod(BIGNUM *rem, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);r=abs(a%b)

 

 int BN_mod_add(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m,

 

         BN_CTX *ctx);r=abs((a+b)%m))

 

 int BN_mod_sub(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m,

 

         BN_CTX *ctx); r=abs((a-b)%m))

 

 int BN_mod_mul(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m,

 

         BN_CTX *ctx); r=abs((a*b)%m))

 

 int BN_mod_sqr(BIGNUM *ret, BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); r=abs((a*a)%m))

 

 int BN_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BN_CTX *ctx);r=pow(a,p)

 

 int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p,

 

         const BIGNUM *m, BN_CTX *ctx); r=pow(a,p)%M

 

Int bn_gcd (bignum * r, bignum * a, bignum * B, bn_ctx * CTX); r = A, B max common approx.

 

 int BN_add_word(BIGNUM *a, BN_ULONG w);

 

 int BN_sub_word(BIGNUM *a, BN_ULONG w);

 

 int BN_mul_word(BIGNUM *a, BN_ULONG w);

 

 BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w);

 

 BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w);

 

 BIGNUM *BN_mod_inverse(BIGNUM *r, BIGNUM *a, const BIGNUM *n,

 

Bn_ctx * CTX); modulo inverse, (A * r) % N = 1 ).

 

 

 

6. comparison functions
 int BN_cmp(BIGNUM *a, BIGNUM *b);   -1 if a < b, 0 if a == b and 1 if a > b.

 

Int bn_ucmp (bignum * a, bignum * B); compare the values of A and B, and the returned values are the same as those of the above.

 

 int BN_is_zero(BIGNUM *a);

 

 int BN_is_one(BIGNUM *a);

 

 int BN_is_word(BIGNUM *a, BN_ULONG w);

 

Int bn_is_odd (bignum * A); the preceding four return 1. If the condition is true, 0 is returned.

 

7. Set Functions
Int bn_zero (bignum * A); set a to 0

 

Int bn_one (bignum * A); set a to 1

 

Const bignum * bn_value_one (void); returns a large value of 1.

 

Int bn_set_word (bignum * a, unsigned long w); set a to W

 

Unsigned long bn_get_word (bignum * A); If a can be expressed as long, a long number is returned.

 

8. Random Number Function
Int bn_rand (bignum * RND, int bits, int top, int bottom); generate a pseudo random number of strong bits for encryption. If Top =-1, the maximum bit is 0, top = 0, the highest bit is 1,Top= 1, the highest bit and secondary high are 1, bottom is true, and the random number is an even number

 

Int bn_pseudo do_rand (bignum * RND, int bits, int top, int bottom); generates a pseudo-random number for some purposes.

 

Int bn_rand_range (bignum * RND, bignum * Range); 0 <RND <range

 

Int bn_pseudo do_rand_range (bignum * RND, bignum * Range); Same as above

 

9. Generate the prime number Function
BIGNUM *BN_generate_prime(BIGNUM *ret, int bits,int safe, BIGNUM *add,

 

Bignum * REM, void (* callback) (INT, Int, void *), void * cb_arg); generate a bits-bit prime number. All the following parameters can be null.

 

 int BN_is_prime(const BIGNUM *p, int nchecks,

 

         void (*callback)(int, int, void *), BN_CTX *ctx, void *cb_arg);

 

Returns 0 to determine if it is a prime number. 1 to indicate that the error probability is less than 0. 25,-1 indicates an error

 

10. Number of digits Function
Int bn_set_bit (bignum * a, int N); set the nth bit in a to 1. If a is less than N bits

 

Int bn_clear_bit (bignum * a, int N); Set nth in a to 0. If a is less than N bits, an error occurs.

 

Int bn_is_bit_set (const bignum * a, int N); test whether it has been set; 1 indicates that it has been set

 

Int bn_mask_bits (bignum * a, int N); truncates A to N bits. If a is less than N bits, an error occurs.

 

Int bn_lshift (bignum * r, const bignum * a, int N); A shifts left n places, and the result is stored in R

 

Int bn_lshift1 (bignum * r, bignum * A); A shifts 1 bit left, and the result is stored in R.

 

Int bn_rshift (bignum * r, bignum * a, int N); A shifts n places to the right, and the result is stored in R.

 

Int bn_rshift1 (bignum * r, bignum * A); A shifts 1 bit left, and the result is stored in R.

 

11. conversion functions with strings
Int bn_bn2bin (const bignum * a, unsigned char * to); Convert ABS (a) to a string and store it to. The space to must be greater than bn_num_bytes (A)

 

Bignum * bn_bin2bn (const unsigned char * s, int Len, bignum * RET); converts a positive integer of the Len bit in s to a large number.

 

Char * bn_bn2hex (const bignum * A); convert to hexadecimal string

 

Char * bn_bn2dec (const bignum * A); convert to a 10-digit string

 

Int bn_hex2bn (bignum ** A, const char * Str); Same as above

 

Int bn_dec2bn (bignum ** A, const char * Str); Same as above

 

Int bn_print (Bio * FP, const bignum * A); write large numbers in hexadecimal format into memory

 

Int bn_print_fp (File * FP, const bignum * A); write large numbers into files in hexadecimal format

 

 int BN_bn2mpi(const BIGNUM *a, unsigned char *to);

 

 BIGNUM *BN_mpi2bn(unsigned char *s, int len, BIGNUM *ret);

 

12. Other functions
The following functions can perform more efficient Modulo Multiplication and modulo division. If we duplicate the Modulo Multiplication and modulo division computing in the same modulo, calculate R = (A * B) % m used RECP = 1/m

 

BN_RECP_CTX *BN_RECP_CTX_new(void);

 

 void BN_RECP_CTX_init(BN_RECP_CTX *recp);

 

 void BN_RECP_CTX_free(BN_RECP_CTX *recp);

 

 int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *m, BN_CTX *ctx);

 

 int BN_mod_mul_reciprocal(BIGNUM *r, BIGNUM *a, BIGNUM *b,

 

 BN_RECP_CTX *recp, BN_CTX *ctx);

 

The following functions use the Montgomery Algorithm for modulo power calculation, which can improve efficiency. They are also mainly used for multiple power operations under the same model.

 

BN_MONT_CTX *BN_MONT_CTX_new(void);

 

 void BN_MONT_CTX_init(BN_MONT_CTX *ctx);

 

 void BN_MONT_CTX_free(BN_MONT_CTX *mont);

 

 int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *m, BN_CTX *ctx);

 

 BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from);

 

 int BN_mod_mul_montgomery(BIGNUM *r, BIGNUM *a, BIGNUM *b,

 

         BN_MONT_CTX *mont, BN_CTX *ctx);

 

 int BN_from_montgomery(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mont,

 

         BN_CTX *ctx);

 

 int BN_to_montgomery(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mont,

 

         BN_CTX *ctx);

Related Article

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.