Add an export secret key feature.

* src/gpgme.h.in (GPGME_EXPORT_MODE_SECRET): New.
(GPGME_EXPORT_MODE_RAW): New.
(GPGME_EXPORT_MODE_PKCS12): New.
* src/export.c (export_start, export_ext_start): Allow new flags.
* src/engine-gpg.c (export_common): Support secret key export.
* src/engine-gpgsm.c (gpgsm_export, gpgsm_export_ext): Ditto.

* src/gpgme-tool.c (cmd_export): Add options --secret, --raw,
and --pkcs12.
* tests/run-export.c (main): Likewise.
--

Note that exporting secret X.509 keys requires GnuPG 2.1.8.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2015-08-24 12:41:24 +02:00
parent ccbaccbf2e
commit 2b632bbb78
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
7 changed files with 123 additions and 20 deletions

View File

@ -3700,6 +3700,21 @@ keys it removes all signatures except for the latest self-signatures.
For X.509 keys it has no effect. For X.509 keys it has no effect.
@item GPGME_EXPORT_MODE_SECRET
Instead of exporting the public key, the secret key is exported. This
may not be combined with @code{GPGME_EXPORT_MODE_EXTERN}. For X.509
the export format is PKCS#8.
@item GPGME_EXPORT_MODE_RAW
If this flag is used with @code{GPGME_EXPORT_MODE_SECRET} for an X.509
key the export format will be changed to PKCS#1. This flag may not be
used with OpenPGP.
@item GPGME_EXPORT_MODE_PKCS12
If this flag is used with @code{GPGME_EXPORT_MODE_SECRET} for an X.509
key the export format will be changed to PKCS#12 which also includes
the certificate. This flag may not be used with OpenPGP.
@end table @end table

View File

@ -1793,7 +1793,8 @@ export_common (engine_gpg_t gpg, gpgme_export_mode_t mode,
gpgme_error_t err = 0; gpgme_error_t err = 0;
if ((mode & ~(GPGME_EXPORT_MODE_EXTERN if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
|GPGME_EXPORT_MODE_MINIMAL))) |GPGME_EXPORT_MODE_MINIMAL
|GPGME_EXPORT_MODE_SECRET)))
return gpg_error (GPG_ERR_NOT_SUPPORTED); return gpg_error (GPG_ERR_NOT_SUPPORTED);
if ((mode & GPGME_EXPORT_MODE_MINIMAL)) if ((mode & GPGME_EXPORT_MODE_MINIMAL))
@ -1807,6 +1808,9 @@ export_common (engine_gpg_t gpg, gpgme_export_mode_t mode,
} }
else else
{ {
if ((mode & GPGME_EXPORT_MODE_SECRET))
err = add_arg (gpg, "--export-secret-keys");
else
err = add_arg (gpg, "--export"); err = add_arg (gpg, "--export");
if (!err && use_armor) if (!err && use_armor)
err = add_arg (gpg, "--armor"); err = add_arg (gpg, "--armor");

View File

@ -1289,17 +1289,23 @@ gpgsm_export (void *engine, const char *pattern, gpgme_export_mode_t mode,
if (!gpgsm) if (!gpgsm)
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
if (mode)
return gpg_error (GPG_ERR_NOT_SUPPORTED);
if (!pattern) if (!pattern)
pattern = ""; pattern = "";
cmd = malloc (7 + strlen (pattern) + 1); cmd = malloc (7 + 9 + 9 + strlen (pattern) + 1);
if (!cmd) if (!cmd)
return gpg_error_from_syserror (); return gpg_error_from_syserror ();
strcpy (cmd, "EXPORT "); strcpy (cmd, "EXPORT ");
strcpy (&cmd[7], pattern); if ((mode & GPGME_EXPORT_MODE_SECRET))
{
strcat (cmd, "--secret ");
if ((mode & GPGME_EXPORT_MODE_RAW))
strcat (cmd, "--raw ");
else if ((mode & GPGME_EXPORT_MODE_PKCS12))
strcat (cmd, "--pkcs12 ");
}
strcat (cmd, pattern);
gpgsm->output_cb.data = keydata; gpgsm->output_cb.data = keydata;
err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor"
@ -1323,16 +1329,13 @@ gpgsm_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
engine_gpgsm_t gpgsm = engine; engine_gpgsm_t gpgsm = engine;
gpgme_error_t err = 0; gpgme_error_t err = 0;
char *line; char *line;
/* Length is "EXPORT " + p + '\0'. */ /* Length is "EXPORT " + "--secret " + "--pkcs12 " + p + '\0'. */
int length = 7 + 1; int length = 7 + 9 + 9 + 1;
char *linep; char *linep;
if (!gpgsm) if (!gpgsm)
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
if (mode)
return gpg_error (GPG_ERR_NOT_SUPPORTED);
if (pattern && *pattern) if (pattern && *pattern)
{ {
const char **pat = pattern; const char **pat = pattern;
@ -1357,7 +1360,15 @@ gpgsm_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
return gpg_error_from_syserror (); return gpg_error_from_syserror ();
strcpy (line, "EXPORT "); strcpy (line, "EXPORT ");
linep = &line[7]; if ((mode & GPGME_EXPORT_MODE_SECRET))
{
strcat (line, "--secret ");
if ((mode & GPGME_EXPORT_MODE_RAW))
strcat (line, "--raw ");
else if ((mode & GPGME_EXPORT_MODE_PKCS12))
strcat (line, "--pkcs12 ");
}
linep = &line[strlen (line)];
if (pattern && *pattern) if (pattern && *pattern)
{ {

View File

@ -120,9 +120,24 @@ export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern,
op_data_t opd; op_data_t opd;
if ((mode & ~(GPGME_EXPORT_MODE_EXTERN if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
|GPGME_EXPORT_MODE_MINIMAL))) |GPGME_EXPORT_MODE_MINIMAL
|GPGME_EXPORT_MODE_SECRET
|GPGME_EXPORT_MODE_RAW
|GPGME_EXPORT_MODE_PKCS12)))
return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE. */ return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE. */
if ((mode & GPGME_EXPORT_MODE_SECRET))
{
if ((mode & GPGME_EXPORT_MODE_EXTERN))
return gpg_error (GPG_ERR_INV_FLAG); /* Combination not allowed. */
if ((mode & GPGME_EXPORT_MODE_RAW)
&& (mode & GPGME_EXPORT_MODE_PKCS12))
return gpg_error (GPG_ERR_INV_FLAG); /* Combination not allowed. */
if (ctx->protocol != GPGME_PROTOCOL_CMS
&& (mode & (GPGME_EXPORT_MODE_RAW|GPGME_EXPORT_MODE_PKCS12)))
return gpg_error (GPG_ERR_INV_FLAG); /* Only supported for X.509. */
}
if ((mode & GPGME_EXPORT_MODE_EXTERN)) if ((mode & GPGME_EXPORT_MODE_EXTERN))
{ {
@ -199,9 +214,25 @@ export_ext_start (gpgme_ctx_t ctx, int synchronous, const char *pattern[],
op_data_t opd; op_data_t opd;
if ((mode & ~(GPGME_EXPORT_MODE_EXTERN if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
|GPGME_EXPORT_MODE_MINIMAL))) |GPGME_EXPORT_MODE_MINIMAL
|GPGME_EXPORT_MODE_SECRET
|GPGME_EXPORT_MODE_RAW
|GPGME_EXPORT_MODE_PKCS12)))
return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE. */ return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE. */
if ((mode & GPGME_EXPORT_MODE_SECRET))
{
if ((mode & GPGME_EXPORT_MODE_EXTERN))
return gpg_error (GPG_ERR_INV_FLAG); /* Combination not allowed. */
if ((mode & GPGME_EXPORT_MODE_RAW)
&& (mode & GPGME_EXPORT_MODE_PKCS12))
return gpg_error (GPG_ERR_INV_FLAG); /* Combination not allowed. */
if (ctx->protocol != GPGME_PROTOCOL_CMS
&& (mode & (GPGME_EXPORT_MODE_RAW|GPGME_EXPORT_MODE_PKCS12)))
return gpg_error (GPG_ERR_INV_FLAG); /* Only supported for X.509. */
}
if ((mode & GPGME_EXPORT_MODE_EXTERN)) if ((mode & GPGME_EXPORT_MODE_EXTERN))
{ {
if (keydata) if (keydata)

View File

@ -3054,7 +3054,7 @@ cmd_import (assuan_context_t ctx, char *line)
static const char hlp_export[] = static const char hlp_export[] =
"EXPORT [--extern] [--minimal] [<pattern>]\n" "EXPORT [--extern] [--minimal] [--secret [--pkcs12] [--raw]] [<pattern>]\n"
"\n" "\n"
"Export the keys described by PATTERN. Write the\n" "Export the keys described by PATTERN. Write the\n"
"the output to the object set by the last OUTPUT command."; "the output to the object set by the last OUTPUT command.";
@ -3082,6 +3082,12 @@ cmd_export (assuan_context_t ctx, char *line)
mode |= GPGME_EXPORT_MODE_EXTERN; mode |= GPGME_EXPORT_MODE_EXTERN;
if (has_option (line, "--minimal")) if (has_option (line, "--minimal"))
mode |= GPGME_EXPORT_MODE_MINIMAL; mode |= GPGME_EXPORT_MODE_MINIMAL;
if (has_option (line, "--secret"))
mode |= GPGME_EXPORT_MODE_SECRET;
if (has_option (line, "--raw"))
mode |= GPGME_EXPORT_MODE_RAW;
if (has_option (line, "--pkcs12"))
mode |= GPGME_EXPORT_MODE_PKCS12;
line = skip_options (line); line = skip_options (line);

View File

@ -392,6 +392,9 @@ gpgme_pinentry_mode_t;
/* The available export mode flags. */ /* The available export mode flags. */
#define GPGME_EXPORT_MODE_EXTERN 2 #define GPGME_EXPORT_MODE_EXTERN 2
#define GPGME_EXPORT_MODE_MINIMAL 4 #define GPGME_EXPORT_MODE_MINIMAL 4
#define GPGME_EXPORT_MODE_SECRET 16
#define GPGME_EXPORT_MODE_RAW 32
#define GPGME_EXPORT_MODE_PKCS12 64
typedef unsigned int gpgme_export_mode_t; typedef unsigned int gpgme_export_mode_t;

View File

@ -43,7 +43,12 @@ show_usage (int ex)
fputs ("usage: " PGM " [options] USERIDS\n\n" fputs ("usage: " PGM " [options] USERIDS\n\n"
"Options:\n" "Options:\n"
" --verbose run in verbose mode\n" " --verbose run in verbose mode\n"
" --openpgp use OpenPGP protocol (default)\n"
" --cms use X.509 protocol\n"
" --extern send keys to the keyserver (TAKE CARE!)\n" " --extern send keys to the keyserver (TAKE CARE!)\n"
" --secret export secret keys instead of public keys\n"
" --raw use PKCS#1 as secret key format\n"
" --pkcs12 use PKCS#12 as secret key format\n"
, stderr); , stderr);
exit (ex); exit (ex);
} }
@ -59,6 +64,7 @@ main (int argc, char **argv)
gpgme_key_t keyarray[100]; gpgme_key_t keyarray[100];
int keyidx = 0; int keyidx = 0;
gpgme_data_t out; gpgme_data_t out;
gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
gpgme_export_mode_t mode = 0; gpgme_export_mode_t mode = 0;
if (argc) if (argc)
@ -79,9 +85,34 @@ main (int argc, char **argv)
verbose = 1; verbose = 1;
argc--; argv++; argc--; argv++;
} }
else if (!strcmp (*argv, "--openpgp"))
{
protocol = GPGME_PROTOCOL_OpenPGP;
argc--; argv++;
}
else if (!strcmp (*argv, "--cms"))
{
protocol = GPGME_PROTOCOL_CMS;
argc--; argv++;
}
else if (!strcmp (*argv, "--extern")) else if (!strcmp (*argv, "--extern"))
{ {
mode |= GPGME_KEYLIST_MODE_EXTERN; mode |= GPGME_EXPORT_MODE_EXTERN;
argc--; argv++;
}
else if (!strcmp (*argv, "--secret"))
{
mode |= GPGME_EXPORT_MODE_SECRET;
argc--; argv++;
}
else if (!strcmp (*argv, "--raw"))
{
mode |= GPGME_EXPORT_MODE_RAW;
argc--; argv++;
}
else if (!strcmp (*argv, "--pkcs12"))
{
mode |= GPGME_EXPORT_MODE_PKCS12;
argc--; argv++; argc--; argv++;
} }
else if (!strncmp (*argv, "--", 2)) else if (!strncmp (*argv, "--", 2))
@ -92,11 +123,11 @@ main (int argc, char **argv)
if (!argc) if (!argc)
show_usage (1); show_usage (1);
init_gpgme (GPGME_PROTOCOL_OpenPGP); init_gpgme (protocol);
err = gpgme_new (&ctx); err = gpgme_new (&ctx);
fail_if_err (err); fail_if_err (err);
gpgme_set_protocol (ctx, GPGME_PROTOCOL_OpenPGP); gpgme_set_protocol (ctx, protocol);
/* Lookup the keys. */ /* Lookup the keys. */
err = gpgme_op_keylist_ext_start (ctx, (const char**)argv, 0, 0); err = gpgme_op_keylist_ext_start (ctx, (const char**)argv, 0, 0);
@ -131,8 +162,10 @@ main (int argc, char **argv)
} }
/* Now for the actual export. */ /* Now for the actual export. */
if ((mode & GPGME_KEYLIST_MODE_EXTERN)) if ((mode & GPGME_EXPORT_MODE_EXTERN))
printf ("sending keys to keyserver\n"); printf ("sending keys to keyserver\n");
if ((mode & GPGME_EXPORT_MODE_SECRET))
printf ("exporting secret keys!\n");
err = gpgme_data_new (&out); err = gpgme_data_new (&out);
fail_if_err (err); fail_if_err (err);