Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Wim Lewis
nettle
Commits
e89a1126
Commit
e89a1126
authored
Jan 16, 2002
by
Niels Möller
Browse files
New file.
Rev: src/nettle/rsa-keygen.c:1.1
parent
c251c1fc
Changes
1
Hide whitespace changes
Inline
Side-by-side
rsa-keygen.c
0 → 100644
View file @
e89a1126
/* rsa-keygen.c
*
* Generation of RSA keypairs
*/
/* nettle, low-level cryptographics library
*
* Copyright (C) 2002 Niels Mller
*
* The nettle library 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.
*
* The nettle library 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 the nettle library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#if HAVE_CONFIG_H
#include
"config.h"
#endif
#if HAVE_LIBGMP
#include
"rsa.h"
#include
"bignum.h"
#include
<assert.h>
#include
<limits.h>
#include
<stdlib.h>
#ifndef DEBUG
# define DEBUG 0
#endif
#if DEBUG
# include <stdio.h>
#endif
/* Returns a random number, 0 <= x < 2^bits. */
static
void
bignum_random_size
(
mpz_t
x
,
unsigned
bits
,
void
*
random_ctx
,
nettle_random_func
random
)
{
unsigned
length
=
(
bits
+
7
)
/
8
;
uint8_t
*
data
=
alloca
(
length
);
random
(
random_ctx
,
length
,
data
);
nettle_mpz_set_str_256
(
x
,
length
,
data
);
if
(
bits
%
8
)
mpz_fdiv_r_2exp
(
x
,
x
,
bits
);
}
#define NUMBER_OF_PRIMES 167
static
const
unsigned
long
primes
[
NUMBER_OF_PRIMES
]
=
{
3
,
5
,
7
,
11
,
13
,
17
,
19
,
23
,
29
,
31
,
37
,
41
,
43
,
47
,
53
,
59
,
61
,
67
,
71
,
73
,
79
,
83
,
89
,
97
,
101
,
103
,
107
,
109
,
113
,
127
,
131
,
137
,
139
,
149
,
151
,
157
,
163
,
167
,
173
,
179
,
181
,
191
,
193
,
197
,
199
,
211
,
223
,
227
,
229
,
233
,
239
,
241
,
251
,
257
,
263
,
269
,
271
,
277
,
281
,
283
,
293
,
307
,
311
,
313
,
317
,
331
,
337
,
347
,
349
,
353
,
359
,
367
,
373
,
379
,
383
,
389
,
397
,
401
,
409
,
419
,
421
,
431
,
433
,
439
,
443
,
449
,
457
,
461
,
463
,
467
,
479
,
487
,
491
,
499
,
503
,
509
,
521
,
523
,
541
,
547
,
557
,
563
,
569
,
571
,
577
,
587
,
593
,
599
,
601
,
607
,
613
,
617
,
619
,
631
,
641
,
643
,
647
,
653
,
659
,
661
,
673
,
677
,
683
,
691
,
701
,
709
,
719
,
727
,
733
,
739
,
743
,
751
,
757
,
761
,
769
,
773
,
787
,
797
,
809
,
811
,
821
,
823
,
827
,
829
,
839
,
853
,
857
,
859
,
863
,
877
,
881
,
883
,
887
,
907
,
911
,
919
,
929
,
937
,
941
,
947
,
953
,
967
,
971
,
977
,
983
,
991
,
997
};
/* NOTE: The mpz_nextprime in current GMP is unoptimized. */
static
void
bignum_next_prime
(
mpz_t
p
,
mpz_t
n
,
int
count
,
void
*
progress_ctx
,
nettle_progress_func
progress
)
{
mpz_t
tmp
;
unsigned
long
*
moduli
=
NULL
;
unsigned
long
difference
;
int
prime_limit
=
NUMBER_OF_PRIMES
;
/* First handle tiny numbers */
if
(
mpz_cmp_ui
(
n
,
2
)
<=
0
)
{
mpz_set_ui
(
p
,
2
);
return
;
}
mpz_set
(
p
,
n
);
mpz_setbit
(
p
,
0
);
if
(
mpz_cmp_ui
(
p
,
8
)
<
0
)
return
;
mpz_init
(
tmp
);
if
(
prime_limit
&&
(
mpz_cmp_ui
(
p
,
primes
[
prime_limit
])
<=
0
)
)
/* Use unly 3, 5 and 7 */
prime_limit
=
3
;
if
(
prime_limit
)
{
/* Compute residues modulo small odd primes */
int
i
;
moduli
=
alloca
(
prime_limit
*
sizeof
(
*
moduli
));
for
(
i
=
0
;
i
<
prime_limit
;
i
++
)
moduli
[
i
]
=
mpz_fdiv_ui
(
p
,
primes
[
i
]);
}
for
(
difference
=
0
;
;
difference
+=
2
)
{
if
(
difference
>=
ULONG_MAX
-
10
)
{
/* Should not happen, at least not very often... */
mpz_add_ui
(
p
,
p
,
difference
);
difference
=
0
;
}
/* First check residues */
if
(
prime_limit
)
{
int
composite
=
0
;
int
i
;
for
(
i
=
0
;
i
<
prime_limit
;
i
++
)
{
if
(
moduli
[
i
]
==
0
)
composite
=
1
;
moduli
[
i
]
=
(
moduli
[
i
]
+
2
)
%
primes
[
i
];
}
if
(
composite
)
continue
;
}
mpz_add_ui
(
p
,
p
,
difference
);
difference
=
0
;
if
(
progress
)
progress
(
progress_ctx
,
'.'
);
/* Fermat test, with respect to 2 */
mpz_set_ui
(
tmp
,
2
);
mpz_powm
(
tmp
,
tmp
,
p
,
p
);
if
(
mpz_cmp_ui
(
tmp
,
2
)
!=
0
)
continue
;
if
(
progress
)
progress
(
progress_ctx
,
'+'
);
/* Miller-Rabin test */
if
(
mpz_probab_prime_p
(
p
,
count
))
break
;
}
mpz_clear
(
tmp
);
}
/* Returns a random prime of size BITS */
static
void
bignum_random_prime
(
mpz_t
x
,
unsigned
bits
,
void
*
random_ctx
,
nettle_random_func
random
,
void
*
progress_ctx
,
nettle_progress_func
progress
)
{
assert
(
bits
);
for
(;;)
{
bignum_random_size
(
x
,
bits
,
random_ctx
,
random
);
mpz_setbit
(
x
,
bits
-
1
);
/* Miller-rabin count of 25 is probably much overkill. */
bignum_next_prime
(
x
,
x
,
25
,
progress_ctx
,
progress
);
if
(
mpz_sizeinbase
(
x
,
2
)
==
bits
)
break
;
}
}
int
rsa_generate_keypair
(
struct
rsa_public_key
*
pub
,
struct
rsa_private_key
*
key
,
void
*
random_ctx
,
nettle_random_func
random
,
void
*
progress_ctx
,
nettle_progress_func
progress
,
unsigned
n_size
,
unsigned
e_size
)
{
mpz_t
p1
;
mpz_t
q1
;
mpz_t
phi
;
mpz_t
tmp
;
if
(
e_size
)
{
/* We should choose e randomly. Is the size reasonable? */
if
((
e_size
<
16
)
||
(
e_size
>
n_size
)
)
return
0
;
}
else
{
/* We have a fixed e. Check that it makes sense */
/* It must be odd */
if
(
!
mpz_tstbit
(
pub
->
e
,
0
))
return
0
;
/* And 3 or larger */
if
(
mpz_cmp_ui
(
pub
->
e
,
3
)
<
0
)
return
0
;
}
if
(
n_size
<
RSA_MINIMUM_N_BITS
)
return
0
;
mpz_init
(
p1
);
mpz_init
(
q1
);
mpz_init
(
phi
);
mpz_init
(
tmp
);
/* Generate primes */
for
(;;)
{
/* Generate p, such that gcd(p-1, e) = 1 */
for
(;;)
{
bignum_random_prime
(
key
->
p
,
(
n_size
+
1
)
/
2
,
random_ctx
,
random
,
progress_ctx
,
progress
);
mpz_sub_ui
(
p1
,
key
->
p
,
1
);
/* If e was given, we must chose p such that p-1 has no factors in
* common with e. */
if
(
e_size
)
break
;
mpz_gcd
(
tmp
,
pub
->
e
,
p1
);
if
(
mpz_cmp_ui
(
tmp
,
1
)
==
0
)
break
;
else
if
(
progress
)
progress
(
progress_ctx
,
'c'
);
}
if
(
progress
)
progress
(
progress_ctx
,
'\n'
);
/* Generate q, such that gcd(q-1, e) = 1 */
for
(;;)
{
bignum_random_prime
(
key
->
q
,
n_size
/
2
,
random_ctx
,
random
,
progress_ctx
,
progress
);
mpz_sub_ui
(
q1
,
key
->
q
,
1
);
/* If e was given, we must chose q such that q-1 has no factors in
* common with e. */
if
(
e_size
)
break
;
mpz_gcd
(
tmp
,
pub
->
e
,
q1
);
if
(
mpz_cmp_ui
(
tmp
,
1
)
==
0
)
break
;
else
if
(
progress
)
progress
(
progress_ctx
,
'c'
);
}
/* Now we have the primes. Is the product of the right size? */
mpz_mul
(
pub
->
n
,
key
->
p
,
key
->
q
);
if
(
mpz_sizeinbase
(
pub
->
n
,
2
)
!=
n_size
)
/* We might get an n of size n_size-1. Then just try again. */
{
#if DEBUG
fprintf
(
stderr
,
"
\n
Wanted size: %d, p-size: %d, q-size: %d, n-size: %d
\n
"
,
n_size
,
mpz_sizeinbase
(
key
->
p
,
2
),
mpz_sizeinbase
(
key
->
q
,
2
),
mpz_sizeinbase
(
pub
->
n
,
2
));
#endif
if
(
progress
)
{
progress
(
progress_ctx
,
'b'
);
progress
(
progress_ctx
,
'\n'
);
}
continue
;
}
if
(
progress
)
progress
(
progress_ctx
,
'\n'
);
/* c = q^{-1} (mod p) */
if
(
mpz_invert
(
key
->
c
,
key
->
q
,
key
->
p
))
/* This should succeed everytime. But if it doesn't,
* we try again. */
break
;
else
if
(
progress
)
progress
(
progress_ctx
,
'?'
);
}
mpz_mul
(
phi
,
p1
,
q1
);
/* If we didn't have a given e, generate one now. */
if
(
e_size
)
for
(;;)
{
bignum_random_size
(
pub
->
e
,
e_size
,
random_ctx
,
random
);
/* Make sure it's odd and that the most significant bit is
* set */
mpz_setbit
(
pub
->
e
,
0
);
mpz_setbit
(
pub
->
e
,
e_size
-
1
);
/* Needs gmp-3, or inverse might be negative. */
if
(
mpz_invert
(
key
->
d
,
pub
->
e
,
phi
))
break
;
else
if
(
progress
)
progress
(
progress_ctx
,
'e'
);
}
else
{
/* Must always succeed, as we already that e
* doesn't have any common factor with p-1 or q-1. */
int
res
=
mpz_invert
(
key
->
d
,
pub
->
e
,
phi
);
assert
(
res
);
}
/* Done! Almost, we must compute the auxillary private values. */
/* a = d % (p-1) */
mpz_fdiv_r
(
key
->
a
,
key
->
d
,
p1
);
/* b = d % (q-1) */
mpz_fdiv_r
(
key
->
b
,
key
->
d
,
q1
);
/* c was computed earlier */
pub
->
size
=
key
->
size
=
(
mpz_sizeinbase
(
pub
->
n
,
2
)
+
7
)
/
8
;
assert
(
pub
->
size
>=
RSA_MINIMUM_N_OCTETS
);
mpz_clear
(
p1
);
mpz_clear
(
q1
);
mpz_clear
(
phi
);
mpz_clear
(
tmp
);
return
1
;
}
#endif
/* HAVE_LIBGMP */
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment