Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F22067653
mpi-inv.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
6 KB
Subscribers
None
mpi-inv.c
View Options
/* mpi-inv.c - MPI functions
* Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
* Libgcrypt is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Libgcrypt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include
<config.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
"mpi-internal.h"
#include
"g10lib.h"
/****************
* Calculate the multiplicative inverse X of A mod N
* That is: Find the solution x for
* 1 = (a*x) mod n
*/
int
gcry_mpi_invm
(
gcry_mpi_t
x
,
gcry_mpi_t
a
,
gcry_mpi_t
n
)
{
#if 0
gcry_mpi_t u, v, u1, u2, u3, v1, v2, v3, q, t1, t2, t3;
gcry_mpi_t ta, tb, tc;
u = mpi_copy(a);
v = mpi_copy(n);
u1 = mpi_alloc_set_ui(1);
u2 = mpi_alloc_set_ui(0);
u3 = mpi_copy(u);
v1 = mpi_alloc_set_ui(0);
v2 = mpi_alloc_set_ui(1);
v3 = mpi_copy(v);
q = mpi_alloc( mpi_get_nlimbs(u)+1 );
t1 = mpi_alloc( mpi_get_nlimbs(u)+1 );
t2 = mpi_alloc( mpi_get_nlimbs(u)+1 );
t3 = mpi_alloc( mpi_get_nlimbs(u)+1 );
while( mpi_cmp_ui( v3, 0 ) ) {
mpi_fdiv_q( q, u3, v3 );
mpi_mul(t1, v1, q); mpi_mul(t2, v2, q); mpi_mul(t3, v3, q);
mpi_sub(t1, u1, t1); mpi_sub(t2, u2, t2); mpi_sub(t3, u3, t3);
mpi_set(u1, v1); mpi_set(u2, v2); mpi_set(u3, v3);
mpi_set(v1, t1); mpi_set(v2, t2); mpi_set(v3, t3);
}
/* log_debug("result:\n");
log_mpidump("q =", q );
log_mpidump("u1=", u1);
log_mpidump("u2=", u2);
log_mpidump("u3=", u3);
log_mpidump("v1=", v1);
log_mpidump("v2=", v2); */
mpi_set(x, u1);
mpi_free(u1);
mpi_free(u2);
mpi_free(u3);
mpi_free(v1);
mpi_free(v2);
mpi_free(v3);
mpi_free(q);
mpi_free(t1);
mpi_free(t2);
mpi_free(t3);
mpi_free(u);
mpi_free(v);
#elif 0
/* Extended Euclid's algorithm (See TAOCP Vol II, 4.5.2, Alg X)
* modified according to Michael Penk's solution for Exercise 35 */
/* FIXME: we can simplify this in most cases (see Knuth) */
gcry_mpi_t
u
,
v
,
u1
,
u2
,
u3
,
v1
,
v2
,
v3
,
t1
,
t2
,
t3
;
unsigned
k
;
int
sign
;
u
=
mpi_copy
(
a
);
v
=
mpi_copy
(
n
);
for
(
k
=
0
;
!
mpi_test_bit
(
u
,
0
)
&&
!
mpi_test_bit
(
v
,
0
);
k
++
)
{
mpi_rshift
(
u
,
u
,
1
);
mpi_rshift
(
v
,
v
,
1
);
}
u1
=
mpi_alloc_set_ui
(
1
);
u2
=
mpi_alloc_set_ui
(
0
);
u3
=
mpi_copy
(
u
);
v1
=
mpi_copy
(
v
);
/* !-- used as const 1 */
v2
=
mpi_alloc
(
mpi_get_nlimbs
(
u
)
);
mpi_sub
(
v2
,
u1
,
u
);
v3
=
mpi_copy
(
v
);
if
(
mpi_test_bit
(
u
,
0
)
)
{
/* u is odd */
t1
=
mpi_alloc_set_ui
(
0
);
t2
=
mpi_alloc_set_ui
(
1
);
t2
->
sign
=
1
;
t3
=
mpi_copy
(
v
);
t3
->
sign
=
!
t3
->
sign
;
goto
Y4
;
}
else
{
t1
=
mpi_alloc_set_ui
(
1
);
t2
=
mpi_alloc_set_ui
(
0
);
t3
=
mpi_copy
(
u
);
}
do
{
do
{
if
(
mpi_test_bit
(
t1
,
0
)
||
mpi_test_bit
(
t2
,
0
)
)
{
/* one is odd */
mpi_add
(
t1
,
t1
,
v
);
mpi_sub
(
t2
,
t2
,
u
);
}
mpi_rshift
(
t1
,
t1
,
1
);
mpi_rshift
(
t2
,
t2
,
1
);
mpi_rshift
(
t3
,
t3
,
1
);
Y4
:
;
}
while
(
!
mpi_test_bit
(
t3
,
0
)
);
/* while t3 is even */
if
(
!
t3
->
sign
)
{
mpi_set
(
u1
,
t1
);
mpi_set
(
u2
,
t2
);
mpi_set
(
u3
,
t3
);
}
else
{
mpi_sub
(
v1
,
v
,
t1
);
sign
=
u
->
sign
;
u
->
sign
=
!
u
->
sign
;
mpi_sub
(
v2
,
u
,
t2
);
u
->
sign
=
sign
;
sign
=
t3
->
sign
;
t3
->
sign
=
!
t3
->
sign
;
mpi_set
(
v3
,
t3
);
t3
->
sign
=
sign
;
}
mpi_sub
(
t1
,
u1
,
v1
);
mpi_sub
(
t2
,
u2
,
v2
);
mpi_sub
(
t3
,
u3
,
v3
);
if
(
t1
->
sign
)
{
mpi_add
(
t1
,
t1
,
v
);
mpi_sub
(
t2
,
t2
,
u
);
}
}
while
(
mpi_cmp_ui
(
t3
,
0
)
);
/* while t3 != 0 */
/* mpi_lshift( u3, k ); */
mpi_set
(
x
,
u1
);
mpi_free
(
u1
);
mpi_free
(
u2
);
mpi_free
(
u3
);
mpi_free
(
v1
);
mpi_free
(
v2
);
mpi_free
(
v3
);
mpi_free
(
t1
);
mpi_free
(
t2
);
mpi_free
(
t3
);
#else
/* Extended Euclid's algorithm (See TAOCP Vol II, 4.5.2, Alg X)
* modified according to Michael Penk's solution for Exercise 35
* with further enhancement */
gcry_mpi_t
u
,
v
,
u1
,
u2
=
NULL
,
u3
,
v1
,
v2
=
NULL
,
v3
,
t1
,
t2
=
NULL
,
t3
;
unsigned
k
;
int
sign
;
int
odd
;
u
=
mpi_copy
(
a
);
v
=
mpi_copy
(
n
);
for
(
k
=
0
;
!
mpi_test_bit
(
u
,
0
)
&&
!
mpi_test_bit
(
v
,
0
);
k
++
)
{
mpi_rshift
(
u
,
u
,
1
);
mpi_rshift
(
v
,
v
,
1
);
}
odd
=
mpi_test_bit
(
v
,
0
);
u1
=
mpi_alloc_set_ui
(
1
);
if
(
!
odd
)
u2
=
mpi_alloc_set_ui
(
0
);
u3
=
mpi_copy
(
u
);
v1
=
mpi_copy
(
v
);
if
(
!
odd
)
{
v2
=
mpi_alloc
(
mpi_get_nlimbs
(
u
)
);
mpi_sub
(
v2
,
u1
,
u
);
/* U is used as const 1 */
}
v3
=
mpi_copy
(
v
);
if
(
mpi_test_bit
(
u
,
0
)
)
{
/* u is odd */
t1
=
mpi_alloc_set_ui
(
0
);
if
(
!
odd
)
{
t2
=
mpi_alloc_set_ui
(
1
);
t2
->
sign
=
1
;
}
t3
=
mpi_copy
(
v
);
t3
->
sign
=
!
t3
->
sign
;
goto
Y4
;
}
else
{
t1
=
mpi_alloc_set_ui
(
1
);
if
(
!
odd
)
t2
=
mpi_alloc_set_ui
(
0
);
t3
=
mpi_copy
(
u
);
}
do
{
do
{
if
(
!
odd
)
{
if
(
mpi_test_bit
(
t1
,
0
)
||
mpi_test_bit
(
t2
,
0
)
)
{
/* one is odd */
mpi_add
(
t1
,
t1
,
v
);
mpi_sub
(
t2
,
t2
,
u
);
}
mpi_rshift
(
t1
,
t1
,
1
);
mpi_rshift
(
t2
,
t2
,
1
);
mpi_rshift
(
t3
,
t3
,
1
);
}
else
{
if
(
mpi_test_bit
(
t1
,
0
)
)
mpi_add
(
t1
,
t1
,
v
);
mpi_rshift
(
t1
,
t1
,
1
);
mpi_rshift
(
t3
,
t3
,
1
);
}
Y4
:
;
}
while
(
!
mpi_test_bit
(
t3
,
0
)
);
/* while t3 is even */
if
(
!
t3
->
sign
)
{
mpi_set
(
u1
,
t1
);
if
(
!
odd
)
mpi_set
(
u2
,
t2
);
mpi_set
(
u3
,
t3
);
}
else
{
mpi_sub
(
v1
,
v
,
t1
);
sign
=
u
->
sign
;
u
->
sign
=
!
u
->
sign
;
if
(
!
odd
)
mpi_sub
(
v2
,
u
,
t2
);
u
->
sign
=
sign
;
sign
=
t3
->
sign
;
t3
->
sign
=
!
t3
->
sign
;
mpi_set
(
v3
,
t3
);
t3
->
sign
=
sign
;
}
mpi_sub
(
t1
,
u1
,
v1
);
if
(
!
odd
)
mpi_sub
(
t2
,
u2
,
v2
);
mpi_sub
(
t3
,
u3
,
v3
);
if
(
t1
->
sign
)
{
mpi_add
(
t1
,
t1
,
v
);
if
(
!
odd
)
mpi_sub
(
t2
,
t2
,
u
);
}
}
while
(
mpi_cmp_ui
(
t3
,
0
)
);
/* while t3 != 0 */
/* mpi_lshift( u3, k ); */
mpi_set
(
x
,
u1
);
mpi_free
(
u1
);
mpi_free
(
v1
);
mpi_free
(
t1
);
if
(
!
odd
)
{
mpi_free
(
u2
);
mpi_free
(
v2
);
mpi_free
(
t2
);
}
mpi_free
(
u3
);
mpi_free
(
v3
);
mpi_free
(
t3
);
mpi_free
(
u
);
mpi_free
(
v
);
#endif
return
1
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Tue, Apr 22, 3:54 AM (22 h, 24 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
ee/9c/5918337eb732030cf1e60216189c
Attached To
rC libgcrypt
Event Timeline
Log In to Comment