mirror of
				https://github.com/cuberite/polarssl.git
				synced 2025-11-04 04:32:24 -05:00 
			
		
		
		
	Changed to jacobian coordinates everywhere
This commit is contained in:
		
							parent
							
								
									773ed546a2
								
							
						
					
					
						commit
						1c2782cc7c
					
				@ -37,15 +37,19 @@
 | 
			
		||||
#define POLARSSL_ERR_ECP_GENERIC    -0x007E  /**<  Generic ECP error */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief           ECP point structure (affine coordinates)
 | 
			
		||||
 * \brief           ECP point structure (jacobian coordinates)
 | 
			
		||||
 *
 | 
			
		||||
 * Note: if the point is zero, X and Y are irrelevant and should be freed.
 | 
			
		||||
 * \note            All functions expect and return points satisfying
 | 
			
		||||
 *                  the following condition: Z == 0 or Z == 1. (Other
 | 
			
		||||
 *                  values of Z are used by internal functions only.)
 | 
			
		||||
 *                  The point is zero, or "at infinity", if Z == 0.
 | 
			
		||||
 *                  Otherwise, X and Y are its standard (affine) coordinates.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    char is_zero;   /*!<  true if point at infinity */
 | 
			
		||||
    mpi X;          /*!<  the point's X coordinate  */
 | 
			
		||||
    mpi Y;          /*!<  the point's Y coordinate  */
 | 
			
		||||
    mpi Z;          /*!<  the point's Z coordinate  */
 | 
			
		||||
}
 | 
			
		||||
ecp_point;
 | 
			
		||||
 | 
			
		||||
@ -119,8 +123,11 @@ void ecp_group_free( ecp_group *grp );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief           Set a point to zero
 | 
			
		||||
 *
 | 
			
		||||
 * \return          0 if successful,
 | 
			
		||||
 *                  POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
 | 
			
		||||
 */
 | 
			
		||||
void ecp_set_zero( ecp_point *pt );
 | 
			
		||||
int ecp_set_zero( ecp_point *pt );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief           Copy the contents of point Q into P
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										182
									
								
								library/ecp.c
									
									
									
									
									
								
							
							
						
						
									
										182
									
								
								library/ecp.c
									
									
									
									
									
								
							@ -46,9 +46,9 @@ void ecp_point_init( ecp_point *pt )
 | 
			
		||||
    if( pt == NULL )
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    pt->is_zero = 1;
 | 
			
		||||
    mpi_init( &pt->X );
 | 
			
		||||
    mpi_init( &pt->Y );
 | 
			
		||||
    mpi_init( &pt->Z );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -78,9 +78,9 @@ void ecp_point_free( ecp_point *pt )
 | 
			
		||||
    if( pt == NULL )
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    pt->is_zero = 1;
 | 
			
		||||
    mpi_free( &( pt->X ) );
 | 
			
		||||
    mpi_free( &( pt->Y ) );
 | 
			
		||||
    mpi_free( &( pt->Z ) );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -100,11 +100,16 @@ void ecp_group_free( ecp_group *grp )
 | 
			
		||||
/*
 | 
			
		||||
 * Set point to zero
 | 
			
		||||
 */
 | 
			
		||||
void ecp_set_zero( ecp_point *pt )
 | 
			
		||||
int ecp_set_zero( ecp_point *pt )
 | 
			
		||||
{
 | 
			
		||||
    pt->is_zero = 1;
 | 
			
		||||
    mpi_free( &pt->X );
 | 
			
		||||
    mpi_free( &pt->Y );
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    MPI_CHK( mpi_lset( &pt->X , 1 ) );
 | 
			
		||||
    MPI_CHK( mpi_lset( &pt->Y , 1 ) );
 | 
			
		||||
    MPI_CHK( mpi_lset( &pt->Z , 0 ) );
 | 
			
		||||
 | 
			
		||||
cleanup:
 | 
			
		||||
    return( ret );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -114,14 +119,9 @@ int ecp_copy( ecp_point *P, const ecp_point *Q )
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    if( Q->is_zero ) {
 | 
			
		||||
        ecp_set_zero( P );
 | 
			
		||||
        return( 0 );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    P->is_zero = Q->is_zero;
 | 
			
		||||
    MPI_CHK( mpi_copy( &P->X, &Q->X ) );
 | 
			
		||||
    MPI_CHK( mpi_copy( &P->Y, &Q->Y ) );
 | 
			
		||||
    MPI_CHK( mpi_copy( &P->Z, &Q->Z ) );
 | 
			
		||||
 | 
			
		||||
cleanup:
 | 
			
		||||
    return( ret );
 | 
			
		||||
@ -135,9 +135,9 @@ int ecp_point_read_string( ecp_point *P, int radix,
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    P->is_zero = 0;
 | 
			
		||||
    MPI_CHK( mpi_read_string( &P->X, radix, x ) );
 | 
			
		||||
    MPI_CHK( mpi_read_string( &P->Y, radix, y ) );
 | 
			
		||||
    MPI_CHK( mpi_lset( &P->Z, 1 ) );
 | 
			
		||||
 | 
			
		||||
cleanup:
 | 
			
		||||
    return( ret );
 | 
			
		||||
@ -459,109 +459,35 @@ int ecp_use_known_dp( ecp_group *grp, size_t index )
 | 
			
		||||
        MPI_CHK( mpi_sub_mpi( &N, &N, &grp->P ) )
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Internal point format used for fast (that is, without mpi_inv_mod)
 | 
			
		||||
 * addition/doubling/multiplication: Jacobian coordinates (GECC ex 3.20)
 | 
			
		||||
 * Normalize jacobian coordinates so that Z == 0 || Z == 1  (GECC 3.2.1)
 | 
			
		||||
 */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    mpi X, Y, Z;
 | 
			
		||||
}
 | 
			
		||||
ecp_ptjac;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Initialize a point in Jacobian coordinates
 | 
			
		||||
 */
 | 
			
		||||
static void ecp_ptjac_init( ecp_ptjac *P )
 | 
			
		||||
{
 | 
			
		||||
    mpi_init( &P->X ); mpi_init( &P->Y ); mpi_init( &P->Z );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Free a point in Jacobian coordinates
 | 
			
		||||
 */
 | 
			
		||||
static void ecp_ptjac_free( ecp_ptjac *P )
 | 
			
		||||
{
 | 
			
		||||
    mpi_free( &P->X ); mpi_free( &P->Y ); mpi_free( &P->Z );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copy P to R in Jacobian coordinates
 | 
			
		||||
 */
 | 
			
		||||
static int ecp_ptjac_copy( ecp_ptjac *R, const ecp_ptjac *P )
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    MPI_CHK( mpi_copy( &R->X, &P->X ) );
 | 
			
		||||
    MPI_CHK( mpi_copy( &R->Y, &P->Y ) );
 | 
			
		||||
    MPI_CHK( mpi_copy( &R->Z, &P->Z ) );
 | 
			
		||||
 | 
			
		||||
cleanup:
 | 
			
		||||
    return( ret );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Set P to zero in Jacobian coordinates
 | 
			
		||||
 */
 | 
			
		||||
static int ecp_ptjac_set_zero( ecp_ptjac *P )
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    MPI_CHK( mpi_lset( &P->X, 1 ) );
 | 
			
		||||
    MPI_CHK( mpi_lset( &P->Y, 1 ) );
 | 
			
		||||
    MPI_CHK( mpi_lset( &P->Z, 0 ) );
 | 
			
		||||
 | 
			
		||||
cleanup:
 | 
			
		||||
    return( ret );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Convert from affine to Jacobian coordinates
 | 
			
		||||
 */
 | 
			
		||||
static int ecp_aff_to_jac( ecp_ptjac *jac, const ecp_point *aff )
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    if( aff->is_zero )
 | 
			
		||||
        return( ecp_ptjac_set_zero( jac ) );
 | 
			
		||||
 | 
			
		||||
    MPI_CHK( mpi_copy( &jac->X, &aff->X ) );
 | 
			
		||||
    MPI_CHK( mpi_copy( &jac->Y, &aff->Y ) );
 | 
			
		||||
    MPI_CHK( mpi_lset( &jac->Z, 1       ) );
 | 
			
		||||
 | 
			
		||||
cleanup:
 | 
			
		||||
    return( ret );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Convert from Jacobian to affine coordinates
 | 
			
		||||
 */
 | 
			
		||||
static int ecp_jac_to_aff( const ecp_group *grp,
 | 
			
		||||
                           ecp_point *aff, const ecp_ptjac *jac )
 | 
			
		||||
static int ecp_normalize( const ecp_group *grp, ecp_point *pt )
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    mpi Zi, ZZi, T;
 | 
			
		||||
 | 
			
		||||
    if( mpi_cmp_int( &jac->Z, 0 ) == 0 ) {
 | 
			
		||||
        ecp_set_zero( aff );
 | 
			
		||||
    if( mpi_cmp_int( &pt->Z, 0 ) == 0 )
 | 
			
		||||
        return( 0 );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mpi_init( &Zi ); mpi_init( &ZZi ); mpi_init( &T );
 | 
			
		||||
 | 
			
		||||
    aff->is_zero = 0;
 | 
			
		||||
    /*
 | 
			
		||||
     * X = X / Z^2  mod p
 | 
			
		||||
     */
 | 
			
		||||
    MPI_CHK( mpi_inv_mod( &Zi,      &pt->Z,     &grp->P ) );
 | 
			
		||||
    MPI_CHK( mpi_mul_mpi( &ZZi,     &Zi,        &Zi     ) ); MOD_MUL( ZZi );
 | 
			
		||||
    MPI_CHK( mpi_mul_mpi( &pt->X,   &pt->X,     &ZZi    ) ); MOD_MUL( pt->X );
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * aff.X = jac.X / (jac.Z)^2  mod p
 | 
			
		||||
     * Y = Y / Z^3  mod p
 | 
			
		||||
     */
 | 
			
		||||
    MPI_CHK( mpi_inv_mod( &Zi,      &jac->Z,  &grp->P ) );
 | 
			
		||||
    MPI_CHK( mpi_mul_mpi( &ZZi,     &Zi,      &Zi     ) ); MOD_MUL( ZZi );
 | 
			
		||||
    MPI_CHK( mpi_mul_mpi( &aff->X,  &jac->X,  &ZZi    ) ); MOD_MUL( aff->X );
 | 
			
		||||
    MPI_CHK( mpi_mul_mpi( &pt->Y,   &pt->Y,     &ZZi    ) ); MOD_MUL( pt->Y );
 | 
			
		||||
    MPI_CHK( mpi_mul_mpi( &pt->Y,   &pt->Y,     &Zi     ) ); MOD_MUL( pt->Y );
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * aff.Y = jac.Y / (jac.Z)^3  mod p
 | 
			
		||||
     * Z = 1
 | 
			
		||||
     */
 | 
			
		||||
    MPI_CHK( mpi_mul_mpi( &aff->Y,  &jac->Y,  &ZZi    ) ); MOD_MUL( aff->Y );
 | 
			
		||||
    MPI_CHK( mpi_mul_mpi( &aff->Y,  &aff->Y,  &Zi     ) ); MOD_MUL( aff->Y );
 | 
			
		||||
    MPI_CHK( mpi_lset( &pt->Z, 1 ) );
 | 
			
		||||
 | 
			
		||||
cleanup:
 | 
			
		||||
 | 
			
		||||
@ -573,14 +499,14 @@ cleanup:
 | 
			
		||||
/*
 | 
			
		||||
 * Point doubling R = 2 P, Jacobian coordinates (GECC 3.21)
 | 
			
		||||
 */
 | 
			
		||||
static int ecp_double_jac( const ecp_group *grp, ecp_ptjac *R,
 | 
			
		||||
                           const ecp_ptjac *P )
 | 
			
		||||
static int ecp_double_jac( const ecp_group *grp, ecp_point *R,
 | 
			
		||||
                           const ecp_point *P )
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    mpi T1, T2, T3, X, Y, Z;
 | 
			
		||||
 | 
			
		||||
    if( mpi_cmp_int( &P->Z, 0 ) == 0 )
 | 
			
		||||
        return( ecp_ptjac_set_zero( R ) );
 | 
			
		||||
        return( ecp_set_zero( R ) );
 | 
			
		||||
 | 
			
		||||
    mpi_init( &T1 ); mpi_init( &T2 ); mpi_init( &T3 );
 | 
			
		||||
    mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
 | 
			
		||||
@ -625,9 +551,10 @@ cleanup:
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
 | 
			
		||||
 * The coordinates of Q must be normalized (= affine).
 | 
			
		||||
 */
 | 
			
		||||
static int ecp_add_mixed( const ecp_group *grp, ecp_ptjac *R,
 | 
			
		||||
                          const ecp_ptjac *P, const ecp_point *Q )
 | 
			
		||||
static int ecp_add_mixed( const ecp_group *grp, ecp_point *R,
 | 
			
		||||
                          const ecp_point *P, const ecp_point *Q )
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    mpi T1, T2, T3, T4, X, Y, Z;
 | 
			
		||||
@ -636,10 +563,16 @@ static int ecp_add_mixed( const ecp_group *grp, ecp_ptjac *R,
 | 
			
		||||
     * Trivial cases: P == 0 or Q == 0
 | 
			
		||||
     */
 | 
			
		||||
    if( mpi_cmp_int( &P->Z, 0 ) == 0 )
 | 
			
		||||
        return( ecp_aff_to_jac( R, Q ) );
 | 
			
		||||
        return( ecp_copy( R, Q ) );
 | 
			
		||||
 | 
			
		||||
    if( Q->is_zero )
 | 
			
		||||
        return( ecp_ptjac_copy( R, P ) );
 | 
			
		||||
    if( mpi_cmp_int( &Q->Z, 0 ) == 0 )
 | 
			
		||||
        return( ecp_copy( R, P ) );
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Make sure Q coordinates are normalized
 | 
			
		||||
     */
 | 
			
		||||
    if( mpi_cmp_int( &Q->Z, 1 ) != 0 )
 | 
			
		||||
        return( POLARSSL_ERR_ECP_GENERIC );
 | 
			
		||||
 | 
			
		||||
    mpi_init( &T1 ); mpi_init( &T2 ); mpi_init( &T3 ); mpi_init( &T4 );
 | 
			
		||||
    mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
 | 
			
		||||
@ -660,7 +593,7 @@ static int ecp_add_mixed( const ecp_group *grp, ecp_ptjac *R,
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            ret = ecp_ptjac_set_zero( R );
 | 
			
		||||
            ret = ecp_set_zero( R );
 | 
			
		||||
            goto cleanup;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -691,24 +624,17 @@ cleanup:
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Addition: R = P + Q, affine wrapper
 | 
			
		||||
 * Addition: R = P + Q, result's coordinates normalized
 | 
			
		||||
 */
 | 
			
		||||
int ecp_add( const ecp_group *grp, ecp_point *R,
 | 
			
		||||
             const ecp_point *P, const ecp_point *Q )
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    ecp_ptjac J;
 | 
			
		||||
 | 
			
		||||
    ecp_ptjac_init( &J );
 | 
			
		||||
 | 
			
		||||
    MPI_CHK( ecp_aff_to_jac( &J, P ) );
 | 
			
		||||
    MPI_CHK( ecp_add_mixed( grp, &J, &J, Q ) );
 | 
			
		||||
    MPI_CHK( ecp_jac_to_aff( grp, R, &J ) );
 | 
			
		||||
    MPI_CHK( ecp_add_mixed( grp, R, P, Q ) );
 | 
			
		||||
    MPI_CHK( ecp_normalize( grp, R ) );
 | 
			
		||||
 | 
			
		||||
cleanup:
 | 
			
		||||
 | 
			
		||||
    ecp_ptjac_free( &J );
 | 
			
		||||
 | 
			
		||||
    return( ret );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -720,7 +646,7 @@ int ecp_mul( const ecp_group *grp, ecp_point *R,
 | 
			
		||||
{
 | 
			
		||||
    int ret, cmp;
 | 
			
		||||
    size_t pos;
 | 
			
		||||
    ecp_ptjac Q[2];
 | 
			
		||||
    ecp_point Q[2];
 | 
			
		||||
 | 
			
		||||
    cmp = mpi_cmp_int( m, 0 );
 | 
			
		||||
 | 
			
		||||
@ -731,29 +657,29 @@ int ecp_mul( const ecp_group *grp, ecp_point *R,
 | 
			
		||||
     * The general method works only for m != 0
 | 
			
		||||
     */
 | 
			
		||||
    if( cmp == 0 ) {
 | 
			
		||||
        ecp_set_zero( R );
 | 
			
		||||
        return( 0 );
 | 
			
		||||
        return( ecp_set_zero( R ) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ecp_ptjac_init( &Q[0] ); ecp_ptjac_init( &Q[1] );
 | 
			
		||||
    ecp_point_init( &Q[0] ); ecp_point_init( &Q[1] );
 | 
			
		||||
 | 
			
		||||
    ecp_ptjac_set_zero( &Q[0] );
 | 
			
		||||
    MPI_CHK( ecp_set_zero( &Q[0] ) );
 | 
			
		||||
 | 
			
		||||
    for( pos = mpi_msb( m ) - 1 ; ; pos-- )
 | 
			
		||||
    {
 | 
			
		||||
        MPI_CHK( ecp_double_jac( grp, &Q[0], &Q[0] ) );
 | 
			
		||||
        MPI_CHK( ecp_add_mixed( grp, &Q[1], &Q[0], P ) );
 | 
			
		||||
        MPI_CHK( ecp_ptjac_copy( &Q[0], &Q[ mpi_get_bit( m, pos ) ] ) );
 | 
			
		||||
        MPI_CHK( ecp_copy( &Q[0], &Q[ mpi_get_bit( m, pos ) ] ) );
 | 
			
		||||
 | 
			
		||||
        if( pos == 0 )
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    MPI_CHK( ecp_jac_to_aff( grp, R, &Q[0] ) );
 | 
			
		||||
    MPI_CHK( ecp_copy( R, &Q[0] ) );
 | 
			
		||||
    MPI_CHK( ecp_normalize( grp, R ) );
 | 
			
		||||
 | 
			
		||||
cleanup:
 | 
			
		||||
 | 
			
		||||
    ecp_ptjac_free( &Q[0] ); ecp_ptjac_free( &Q[1] );
 | 
			
		||||
    ecp_point_free( &Q[0] ); ecp_point_free( &Q[1] );
 | 
			
		||||
 | 
			
		||||
    return( ret );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -31,7 +31,7 @@ ecp_small_add:a_zero:x_a:y_a:b_zero:x_b:y_b:c_zero:x_c:y_c
 | 
			
		||||
    TEST_ASSERT( ecp_add( &grp, &C, &A, &B ) == 0 );
 | 
			
		||||
 | 
			
		||||
    if( {c_zero} )
 | 
			
		||||
        TEST_ASSERT( C.is_zero );
 | 
			
		||||
        TEST_ASSERT( mpi_cmp_int( &C.Z, 0 ) == 0 );
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        TEST_ASSERT( mpi_cmp_int( &C.X, {x_c} ) == 0 );
 | 
			
		||||
@ -41,7 +41,7 @@ ecp_small_add:a_zero:x_a:y_a:b_zero:x_b:y_b:c_zero:x_c:y_c
 | 
			
		||||
    TEST_ASSERT( ecp_add( &grp, &C, &B, &A ) == 0 );
 | 
			
		||||
 | 
			
		||||
    if( {c_zero} )
 | 
			
		||||
        TEST_ASSERT( C.is_zero );
 | 
			
		||||
        TEST_ASSERT( mpi_cmp_int( &C.Z, 0 ) == 0 );
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        TEST_ASSERT( mpi_cmp_int( &C.X, {x_c} ) == 0 );
 | 
			
		||||
@ -72,7 +72,7 @@ ecp_small_mul:m:r_zero:x_r:y_r:ret
 | 
			
		||||
    TEST_ASSERT( ecp_mul( &grp, &R, &m, &grp.G ) == {ret} );
 | 
			
		||||
 | 
			
		||||
    if( {r_zero} )
 | 
			
		||||
        TEST_ASSERT( R.is_zero );
 | 
			
		||||
        TEST_ASSERT( mpi_cmp_int( &R.Z, 0 ) == 0 );
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        TEST_ASSERT( mpi_cmp_int( &R.X, {x_r} ) == 0 );
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user