Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34024272
rsacvt.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
9 KB
Subscribers
None
rsacvt.c
View Options
/* rsacvt.c - A debug tool to convert RSA formats.
Copyright (C) 2009 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/>.
*/
/* Input data format:
=======
# A hash denotes a comment line
e861b700e17e8afe68[...]f1
f7a7ca5367c661f8e6[...]61
10001
# After an empty line another input block may follow.
7861b700e17e8afe68[...]f3
e7a7ca5367c661f8e6[...]71
3
=========
*/
#ifdef HAVE_CONFIG_H
#include
<config.h>
#endif
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<stdarg.h>
#include
<errno.h>
#include
<ctype.h>
#ifdef HAVE_W32_SYSTEM
# include <fcntl.h>
/* We need setmode(). */
#else
# include <signal.h>
#endif
#include
<assert.h>
#include
<unistd.h>
#ifdef _GCRYPT_IN_LIBGCRYPT
# include "../src/gcrypt-int.h"
#else
# include <gcrypt.h>
# define PACKAGE_BUGREPORT "devnull@example.org"
# define PACKAGE_VERSION "[build on " __DATE__ " " __TIME__ "]"
#endif
#define PGM "rsacvt"
#include
"t-common.h"
/* Prefix output with labels. */
static
int
with_labels
;
/* Do not suppress leading zeroes. */
static
int
keep_lz
;
/* Create parameters as specified by OpenPGP (rfc4880). That is we
don't store dmp1 and dmp1 but d and make sure that p is less than q. */
static
int
openpgp_mode
;
static
char
*
read_textline
(
FILE
*
fp
)
{
char
line
[
4096
];
char
*
p
;
int
any
=
0
;
/* Read line but skip over initial empty lines. */
do
{
do
{
if
(
!
fgets
(
line
,
sizeof
line
,
fp
))
{
if
(
feof
(
fp
))
return
NULL
;
die
(
"error reading input line: %s
\n
"
,
strerror
(
errno
));
}
p
=
strchr
(
line
,
'\n'
);
if
(
p
)
*
p
=
0
;
p
=
line
+
(
*
line
?
(
strlen
(
line
)
-1
)
:
0
);
for
(
;
p
>
line
;
p
--
)
if
(
my_isascii
(
*
p
)
&&
isspace
(
*
p
))
*
p
=
0
;
}
while
(
!
any
&&
!*
line
);
any
=
1
;
}
while
(
*
line
==
'#'
);
/* Always skip comment lines. */
if
(
verbose
>
1
)
fprintf
(
stderr
,
PGM
": received line: %s
\n
"
,
line
);
return
gcry_xstrdup
(
line
);
}
static
gcry_mpi_t
read_hexmpi_line
(
FILE
*
fp
,
int
*
got_eof
)
{
gpg_error_t
err
;
gcry_mpi_t
a
;
char
*
line
;
*
got_eof
=
0
;
line
=
read_textline
(
fp
);
if
(
!
line
)
{
*
got_eof
=
1
;
return
NULL
;
}
err
=
gcry_mpi_scan
(
&
a
,
GCRYMPI_FMT_HEX
,
line
,
0
,
NULL
);
gcry_free
(
line
);
if
(
err
)
a
=
NULL
;
return
a
;
}
static
int
skip_to_empty_line
(
FILE
*
fp
)
{
char
line
[
256
];
char
*
p
;
do
{
if
(
!
fgets
(
line
,
sizeof
line
,
fp
))
{
if
(
feof
(
fp
))
return
-1
;
die
(
"error reading input line: %s
\n
"
,
strerror
(
errno
));
}
p
=
strchr
(
line
,
'\n'
);
if
(
p
)
*
p
=
0
;
}
while
(
*
line
);
return
0
;
}
/* Print an MPI on a line. */
static
void
print_mpi_line
(
const
char
*
label
,
gcry_mpi_t
a
)
{
unsigned
char
*
buf
,
*
p
;
gcry_error_t
err
;
int
writerr
=
0
;
if
(
with_labels
&&
label
)
printf
(
"%s = "
,
label
);
err
=
gcry_mpi_aprint
(
GCRYMPI_FMT_HEX
,
&
buf
,
NULL
,
a
);
if
(
err
)
die
(
"gcry_mpi_aprint failed: %s
\n
"
,
gpg_strerror
(
err
));
p
=
buf
;
if
(
!
keep_lz
&&
p
[
0
]
==
'0'
&&
p
[
1
]
==
'0'
&&
p
[
2
])
p
+=
2
;
printf
(
"%s
\n
"
,
p
);
if
(
ferror
(
stdout
))
writerr
++
;
if
(
!
writerr
&&
fflush
(
stdout
)
==
EOF
)
writerr
++
;
if
(
writerr
)
die
(
"writing output failed: %s
\n
"
,
strerror
(
errno
));
gcry_free
(
buf
);
}
/* Compute and print missing RSA parameters. */
static
void
compute_missing
(
gcry_mpi_t
rsa_p
,
gcry_mpi_t
rsa_q
,
gcry_mpi_t
rsa_e
)
{
gcry_mpi_t
rsa_n
,
rsa_d
,
rsa_pm1
,
rsa_qm1
,
rsa_u
;
gcry_mpi_t
phi
,
tmp_g
,
tmp_f
;
rsa_n
=
gcry_mpi_new
(
0
);
rsa_d
=
gcry_mpi_new
(
0
);
rsa_pm1
=
gcry_mpi_new
(
0
);
rsa_qm1
=
gcry_mpi_new
(
0
);
rsa_u
=
gcry_mpi_new
(
0
);
phi
=
gcry_mpi_new
(
0
);
tmp_f
=
gcry_mpi_new
(
0
);
tmp_g
=
gcry_mpi_new
(
0
);
/* Check that p < q; if not swap p and q. */
if
(
openpgp_mode
&&
gcry_mpi_cmp
(
rsa_p
,
rsa_q
)
>
0
)
{
fprintf
(
stderr
,
PGM
": swapping p and q
\n
"
);
gcry_mpi_swap
(
rsa_p
,
rsa_q
);
}
gcry_mpi_mul
(
rsa_n
,
rsa_p
,
rsa_q
);
/* Compute the Euler totient: phi = (p-1)(q-1) */
gcry_mpi_sub_ui
(
rsa_pm1
,
rsa_p
,
1
);
gcry_mpi_sub_ui
(
rsa_qm1
,
rsa_q
,
1
);
gcry_mpi_mul
(
phi
,
rsa_pm1
,
rsa_qm1
);
if
(
!
gcry_mpi_gcd
(
tmp_g
,
rsa_e
,
phi
))
die
(
"parameter 'e' does match 'p' and 'q'
\n
"
);
/* Compute: f = lcm(p-1,q-1) = phi / gcd(p-1,q-1) */
gcry_mpi_gcd
(
tmp_g
,
rsa_pm1
,
rsa_qm1
);
gcry_mpi_div
(
tmp_f
,
NULL
,
phi
,
tmp_g
,
-1
);
/* Compute the secret key: d = e^{-1} mod lcm(p-1,q-1) */
gcry_mpi_invm
(
rsa_d
,
rsa_e
,
tmp_f
);
/* Compute the CRT helpers: d mod (p-1), d mod (q-1) */
gcry_mpi_mod
(
rsa_pm1
,
rsa_d
,
rsa_pm1
);
gcry_mpi_mod
(
rsa_qm1
,
rsa_d
,
rsa_qm1
);
/* Compute the CRT value: OpenPGP: u = p^{-1} mod q
Standard: iqmp = q^{-1} mod p */
if
(
openpgp_mode
)
gcry_mpi_invm
(
rsa_u
,
rsa_p
,
rsa_q
);
else
gcry_mpi_invm
(
rsa_u
,
rsa_q
,
rsa_p
);
gcry_mpi_release
(
phi
);
gcry_mpi_release
(
tmp_f
);
gcry_mpi_release
(
tmp_g
);
/* Print everything. */
print_mpi_line
(
"n"
,
rsa_n
);
print_mpi_line
(
"e"
,
rsa_e
);
if
(
openpgp_mode
)
print_mpi_line
(
"d"
,
rsa_d
);
print_mpi_line
(
"p"
,
rsa_p
);
print_mpi_line
(
"q"
,
rsa_q
);
if
(
openpgp_mode
)
print_mpi_line
(
"u"
,
rsa_u
);
else
{
print_mpi_line
(
"dmp1"
,
rsa_pm1
);
print_mpi_line
(
"dmq1"
,
rsa_qm1
);
print_mpi_line
(
"iqmp"
,
rsa_u
);
}
gcry_mpi_release
(
rsa_n
);
gcry_mpi_release
(
rsa_d
);
gcry_mpi_release
(
rsa_pm1
);
gcry_mpi_release
(
rsa_qm1
);
gcry_mpi_release
(
rsa_u
);
}
static
void
usage
(
int
show_help
)
{
if
(
!
show_help
)
{
fputs
(
"usage: "
PGM
" [OPTION] [FILE] (try --help for more information)
\n
"
,
stderr
);
exit
(
2
);
}
fputs
(
"Usage: "
PGM
" [OPTIONS] [FILE]
\n
"
"Take RSA parameters p, n, e and compute missing parameters.
\n
"
"OPTIONS:
\n
"
" --openpgp Compute as specified by RFC4880
\n
"
" --labels Prefix output with labels
\n
"
" --keep-lz Keep all leading zeroes in the output
\n
"
" --verbose Print additional information
\n
"
" --version Print version information
\n
"
" --help Print this text
\n
"
"With no FILE, or if FILE is -, read standard input.
\n
"
"Report bugs to "
PACKAGE_BUGREPORT
".
\n
"
,
stdout
);
exit
(
0
);
}
int
main
(
int
argc
,
char
**
argv
)
{
int
last_argc
=
-1
;
FILE
*
input
;
gcry_mpi_t
rsa_p
,
rsa_q
,
rsa_e
;
int
got_eof
;
int
any
=
0
;
if
(
argc
)
{
argc
--
;
argv
++
;
}
while
(
argc
&&
last_argc
!=
argc
)
{
last_argc
=
argc
;
if
(
!
strcmp
(
*
argv
,
"--"
))
{
argc
--
;
argv
++
;
break
;
}
else
if
(
!
strcmp
(
*
argv
,
"--help"
))
{
usage
(
1
);
}
else
if
(
!
strcmp
(
*
argv
,
"--version"
))
{
fputs
(
PGM
" (Libgcrypt) "
PACKAGE_VERSION
"
\n
"
,
stdout
);
printf
(
"libgcrypt %s
\n
"
,
gcry_check_version
(
NULL
));
exit
(
0
);
}
else
if
(
!
strcmp
(
*
argv
,
"--verbose"
))
{
verbose
++
;
argc
--
;
argv
++
;
}
else
if
(
!
strcmp
(
*
argv
,
"--labels"
))
{
with_labels
=
1
;
argc
--
;
argv
++
;
}
else
if
(
!
strcmp
(
*
argv
,
"--keep-lz"
))
{
keep_lz
=
1
;
argc
--
;
argv
++
;
}
else
if
(
!
strcmp
(
*
argv
,
"--openpgp"
))
{
openpgp_mode
=
1
;
argc
--
;
argv
++
;
}
}
if
(
argc
>
1
)
usage
(
0
);
#if !defined (HAVE_W32_SYSTEM) && !defined (_WIN32)
signal
(
SIGPIPE
,
SIG_IGN
);
#endif
if
(
argc
==
1
&&
strcmp
(
argv
[
0
],
"-"
))
{
input
=
fopen
(
argv
[
0
],
"r"
);
if
(
!
input
)
die
(
"can't open `%s': %s
\n
"
,
argv
[
0
],
strerror
(
errno
));
}
else
input
=
stdin
;
xgcry_control
(
GCRYCTL_SET_VERBOSITY
,
(
int
)
verbose
);
if
(
!
gcry_check_version
(
"1.4.0"
))
die
(
"Libgcrypt is not sufficient enough
\n
"
);
xgcry_control
(
GCRYCTL_DISABLE_SECMEM
,
0
);
xgcry_control
(
GCRYCTL_INITIALIZATION_FINISHED
,
0
);
do
{
rsa_p
=
read_hexmpi_line
(
input
,
&
got_eof
);
if
(
!
rsa_p
&&
got_eof
)
break
;
if
(
!
rsa_p
)
die
(
"RSA parameter 'p' missing or not properly hex encoded
\n
"
);
rsa_q
=
read_hexmpi_line
(
input
,
&
got_eof
);
if
(
!
rsa_q
)
die
(
"RSA parameter 'q' missing or not properly hex encoded
\n
"
);
rsa_e
=
read_hexmpi_line
(
input
,
&
got_eof
);
if
(
!
rsa_e
)
die
(
"RSA parameter 'e' missing or not properly hex encoded
\n
"
);
got_eof
=
skip_to_empty_line
(
input
);
if
(
any
)
putchar
(
'\n'
);
compute_missing
(
rsa_p
,
rsa_q
,
rsa_e
);
gcry_mpi_release
(
rsa_p
);
gcry_mpi_release
(
rsa_q
);
gcry_mpi_release
(
rsa_e
);
any
=
1
;
}
while
(
!
got_eof
);
return
0
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sat, Nov 29, 7:14 AM (43 m, 34 s)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
f3/e2/0ac19eb5ea977a5ef4713231e002
Attached To
rC libgcrypt
Event Timeline
Log In to Comment