⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpi.cpp

📁 RSA加密解密的算法例程
💻 CPP
📖 第 1 页 / 共 4 页
字号:

    mpi_init( &TA, &TB, NULL );

    if( X == A ) { CHK( mpi_copy( &TA, A ) ); A = &TA; }
    if( X == B ) { CHK( mpi_copy( &TB, B ) ); B = &TB; }

    for( i = A->n - 1; i >= 0; i-- )
        if( A->p[i] != 0 )
            break;

    for( j = B->n - 1; j >= 0; j-- )
        if( B->p[j] != 0 )
            break;

    CHK( mpi_grow( X, i + j + 2 ) );
    CHK( mpi_lset( X, 0 ) );

    for( i++; j >= 0; j-- )
        MULADDC( i, A->p, X->p + j, B->p[j] );

    X->s = A->s * B->s;

cleanup:

    mpi_free( &TB, &TA, NULL );
    return( ret );
}

/*
 * Baseline multiplication: X = A * b
 *
 * Returns 0 if successful
 *         1 if memory allocation failed
 */
int mpi_mul_int( mpi *X, mpi *A, t_int b )
{
    mpi _B;
    t_int p[1];

    _B.s = 1;
    _B.n = 1;
    _B.p = p;
    p[0] = b;

    return( mpi_mul_mpi( X, A, &_B ) );
}

/*
 * Division by mpi: A = Q * B + R  (HAC 14.20)
 *
 * Returns 0 if successful
 *         1 if memory allocation failed
 *         ERR_MPI_DIVISION_BY_ZERO if B == 0
 */
int mpi_div_mpi( mpi *Q, mpi *R, mpi *A, mpi *B )
{
    int ret, i, n, t, k;
    mpi X, Y, Z, T1, T2;
    t_int q0, q1, r0, r1;
    t_int d0, d1, d, m;

    if( mpi_cmp_int( B, 0 ) == 0 )
        return( ERR_MPI_DIVISION_BY_ZERO );

    mpi_init( &X, &Y, &Z, &T1, &T2, NULL );

    if( mpi_cmp_abs( A, B ) < 0 )
    {
        if( Q != NULL ) CHK( mpi_lset( Q, 0 ) );
        if( R != NULL ) CHK( mpi_copy( R, A ) );
        return( 0 );
    }

    CHK( mpi_copy( &X, A ) );
    CHK( mpi_copy( &Y, B ) );
    X.s = Y.s = 1;

    CHK( mpi_grow( &Z, A->n + 2 ) );
    CHK( mpi_lset( &Z,  0 ) );
    CHK( mpi_grow( &T1, 2 ) );
    CHK( mpi_grow( &T2, 3 ) );

    k = mpi_size( &Y ) % biL;
    if( k < (int) biL - 1 )
    {
        k = biL - 1 - k;
        CHK( mpi_shift_l( &X, k ) );
        CHK( mpi_shift_l( &Y, k ) );
    }
    else k = 0;

    n = X.n - 1;
    t = Y.n - 1;
    mpi_shift_l( &Y, biL * (n - t) );
    while( mpi_cmp_mpi( &X, &Y ) >= 0 )
    {
        Z.p[n - t]++;
        mpi_sub_mpi( &X, &X, &Y );
    }
    mpi_shift_r( &Y, biL * (n - t) );

    for( i = n; i > t ; i-- )
    {
        if( X.p[i] >= Y.p[t] )
            Z.p[i - t - 1] = ~0;
        else
        {
            /*
             * __udiv_qrnnd_c, from GMP/longlong.h
             */
            d  = Y.p[t];
            d0 = ( d << biH ) >> biH;
            d1 = ( d >> biH );

            q1 = X.p[i] / d1;
            r1 = X.p[i] - d1 * q1;
            r1 <<= biH;
            r1 |= ( X.p[i - 1] >> biH );

            m = q1 * d0;
            if( r1 < m )
            {
                q1--, r1 += d;
                while( r1 >= d && r1 < m )
                    q1--, r1 += d;
            }
            r1 -= m;

            q0 = r1 / d1;
            r0 = r1 - d1 * q0;
            r0 <<= biH;
            r0 |= ( X.p[i - 1] << biH ) >> biH;

            m = q0 * d0;
            if( r0 < m )
            {
                q0--, r0 += d;
                while( r0 >= d && r0 < m )
                    q0--, r0 += d;
            }
            r0 -= m;

            Z.p[i - t - 1] = ( q1 << biH ) | q0;
        }

        Z.p[i - t - 1]++;
        do
        {
            Z.p[i - t - 1]--;

            CHK( mpi_lset( &T1, 0 ) );
            T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
            T1.p[1] = Y.p[t];
            CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );

            CHK( mpi_lset( &T2, 0 ) );
            T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
            T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
            T2.p[2] = X.p[i];
        }
        while( mpi_cmp_mpi( &T1, &T2 ) > 0 );

        CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
        CHK( mpi_shift_l( &T1,  biL * (i - t - 1) ) );
        CHK( mpi_sub_mpi( &X, &X, &T1 ) );

        if( mpi_cmp_int( &X, 0 ) < 0 )
        {
            CHK( mpi_copy( &T1, &Y ) );
            CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
            CHK( mpi_add_mpi( &X, &X, &T1 ) );
            Z.p[i - t - 1]--;
        }
    }

    if( Q != NULL )
    {
        mpi_copy( Q, &Z );
        Q->s = A->s * B->s;
    }

    if( R != NULL )
    {
        mpi_shift_r( &X, k );
        mpi_copy( R, &X );

        R->s = A->s;
        if( mpi_cmp_int( R, 0 ) == 0 )
            R->s = 1;
    }

cleanup:

    mpi_free( &X, &Y, &Z, &T1, &T2, NULL );
    return( ret );
}

/*
 * Division by int: A = Q * b + R
 *
 * Returns 0 if successful
 *         1 if memory allocation failed
 *         ERR_MPI_DIVISION_BY_ZERO if b == 0
 */
int mpi_div_int( mpi *Q, mpi *R, mpi *A, int b )
{
    mpi _B;
    t_int p[1];

    p[0] = ( b < 0 ) ? -b : b;
    _B.s = ( b < 0 ) ? -1 : 1;
    _B.n = 1;
    _B.p = p;

    return( mpi_div_mpi( Q, R, A, &_B ) );
}

/*
 * Modulo: X = A mod N
 *
 * Returns 0 if successful
 *         1 if memory allocation failed
 *         ERR_MPI_DIVISION_BY_ZERO if N == 0
 */
int mpi_mod_mpi( mpi *R, mpi *A, mpi *B )
{
    int ret;

    CHK( mpi_div_mpi( NULL, R, A, B ) );

    while( mpi_cmp_int( R, 0 ) < 0 )
      CHK( mpi_add_mpi( R, R, B ) );

    while( mpi_cmp_mpi( R, B ) >= 0 )
      CHK( mpi_sub_mpi( R, R, B ) );

cleanup:

    return( ret );
}

/*
 * Modulo: r = A mod b
 *
 * Returns 0 if successful
 *         1 if memory allocation failed
 *         ERR_MPI_DIVISION_BY_ZERO if b == 0
 *         ERR_MPI_INVALID_PARAMETER if |sign| != 1
 */
int mpi_mod_int( t_int *r, mpi *A, int b )
{
    int i;
    t_int x, y, z;

    if( b == 0 )
        return( ERR_MPI_DIVISION_BY_ZERO );

    if( b < 0 )
        b = -b;

    /*
     * handle trivial cases
     */
    if( b == 1 ) { *r = 0;           return( 0 ); }
    if( b == 2 ) { *r = A->p[0] & 1; return( 0 ); }

    /*
     * general case
     */
    for( i = A->n - 1, y = 0; i >= 0; i-- )
    {
        x  = A->p[i];
        y  = ( y << biH ) | ( x >> biH );
        z  = y / b;
        y -= z * b;

        x <<= biH;
        y  = ( y << biH ) | ( x >> biH );
        z  = y / b;
        y -= z * b;
    }

    *r = y;

    return( 0 );
}

/* 
 * Fast Montgomery initialization (thanks to Tom St Denis)
 */
void mpi_montg_init( t_int *mm, mpi *N )
{
    t_int x, m0 = N->p[0];

    x  = m0;
    x += ((m0 + 2) & 4) << 1;
    x *= (2 - (m0 * x));

    if( biL >= 16 ) x *= (2 - (m0 * x));
    if( biL >= 32 ) x *= (2 - (m0 * x));
    if( biL >= 64 ) x *= (2 - (m0 * x));

    *mm = ~x + 1;
}

/* 
 * Montgomery multiplication: X = A * B * R^-1 mod N  (HAC 14.36)
 * (Z is a decoy used to prevent timing attacks)
 *
 * Returns 0 if successful
 *         1 if memory allocation failed
 */
int mpi_montgomery( mpi *X, mpi *A, mpi *B, mpi *N, mpi *Z, t_int mm )
{
    int ret, i, maxB;
    t_int j;
    t_int u0, *x0, z = 1;
    t_int u1, *x1;
    mpi U;

    U.s = U.n = 1; U.p = &z;

    if( A == NULL ) A = &U;
    if( B == NULL ) B = &U;

    CHK( mpi_grow( X, N->n + 2 ) );
    CHK( mpi_lset( X, 0 ) );

    maxB = ( B->n > N->n ) ? N->n : B->n;

    for( i = 0; i < N->n; i++ )
    {
        /*
         * X = X + u0*B + u1*M
         */
        u0 = ( i < A->n ) ? A->p[i] : 0;
        u1 = ( X->p[0] + u0 * B->p[0] ) * mm;

        MULADDC( maxB, B->p, X->p, u0 );
        MULADDC( N->n, N->p, X->p, u1 );

        /*
         * right-shift X by one limb
         */
        x0 = X->p;
        x1 = X->p + 1;

        for( j = X->n - 1; j > 0; j-- )
            *x0++ = *x1++;

        *x0 = 0;
    }

    CHK( mpi_copy( Z, N ) );

    if( mpi_cmp_abs( X, N ) >= 0 )
        { CHK( mpi_sub_abs( X, X, N ) ); }
    else
        { CHK( mpi_sub_abs( Z, Z, X ) ); }

cleanup:

    return( ret );
}

/*
 * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
 *
 * Returns 0 if successful
 *         1 if memory allocation failed
 *         ERR_MPI_INVALID_PARAMETER if N is negative or even
 */
int mpi_exp_mod( mpi *X, mpi *A, mpi *E, mpi *N )
{
    int ret, i, j, wsize, wbits, nbits;
    int bufsize, nblimbs, state;
    mpi R, S, T, W[64], Z;
    t_int mm, ei;

    if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
        return( ERR_MPI_INVALID_PARAMETER );

    mpi_init( &Z, &R, &S, &T, NULL );
    memset( W, 0, sizeof( W ) );

    /*
     * S = R mod N
     */
    CHK( mpi_lset( &R, 1 ) );
    CHK( mpi_shift_l( &R, N->n * biL ) );
    CHK( mpi_mod_mpi( &S, &R, N ) );

    /*
     * W[1] = A * R mod N
     */
    CHK( mpi_copy( &R, A ) );
    CHK( mpi_shift_l( &R, N->n * biL ) );
    CHK( mpi_mod_mpi( &W[1], &R, N ) );

    i = mpi_size( E );

    wsize = ( i > 671 ) ? 6 :
            ( i > 239 ) ? 5 :
            ( i >  79 ) ? 4 :
            ( i >  23 ) ? 3 : 2;

    mpi_montg_init( &mm, N );

    if( wsize > 1 )
    {
        /*
         * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
         */
        j =  1 << (wsize - 1);

        CHK( mpi_copy( &W[j], &W[1] ) );

        for( i = 0; i < wsize - 1; i++ )
        {
            CHK( mpi_montgomery( &T, &W[j], &W[j], N, &Z, mm ) );
            CHK( mpi_copy( &W[j], &T ) );
        }
    
        /*
         * W[i] = W[1] * W[i - 1]
         */
        for( i = j + 1; i < (1 << wsize); i++ )
        {
            CHK( mpi_montgomery( &T, &W[i - 1], &W[1], N, &Z, mm ) );
            CHK( mpi_copy( &W[i], &T ) );
        }
    }

    nblimbs = E->n;
    bufsize = 0;
    nbits   = 0;
    wbits   = 0;
    state   = 0;

    while( 1 )
    {
        if( bufsize == 0 )
        {
            if( nblimbs-- == 0 )
                break;

            bufsize = sizeof( t_int ) << 3;
        }

        bufsize--;

        ei = (E->p[nblimbs] >> bufsize) & 1;

        /*
         * skip leading 0s
         */
        if( ei == 0 && state == 0 )
            continue;

        if( ei == 0 && state == 1 )
        {
            /*
             * out of window, square S
             */
            CHK( mpi_montgomery( &T, &S, &S, N, &Z, mm ) );
            CHK( mpi_copy( &S, &T ) );
            continue;
        }

        /*
         * add ei to current window
         */
        state = 2;

        nbits++;
        wbits |= (ei << (wsize - nbits));

        if( nbits == wsize )
        {
            /*
             * S = S^wsize R^-1 mod N
             */
            for( i = 0; i < wsize; i++ )
            {
                CHK( mpi_montgomery( &T, &S, &S, N, &Z, mm ) );
                CHK( mpi_copy( &S, &T ) );
            }

            /*
             * S = S * W[wbits] R^-1 mod N
             */
            CHK( mpi_montgomery( &T, &S, &W[wbits], N, &Z, mm ) );
            CHK( mpi_copy( &S, &T ) );

            state--;
            nbits = 0;
            wbits = 0;
        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -