[PATCH] Re: command line keytocard
Meno Abels
meno.abels at adviser.com
Fri Dec 2 23:59:54 CET 2016
Now —quick-keytocard is working for me. I can pass the passphrase
and the adminpin down. I solved it by enabling the multiple use of
—passphrase-fd/file
here the patch for the passphrase change
commit 58bbd77b695a4beab60d6033024e3a7045dd078e
gpg: Signature made Fri Dec 2 23:55:25 2016 CET
gpg: using RSA key F78D5B547A9BB0E8A174C0F5060FF53CB3A32992
gpg: Good signature from "Meno Abels <meno.abels at adviser.com>" [ultimate]
Author: Meno Abels <meno.abels at adviser.com>
Date: Fri Dec 2 23:33:19 2016
gpg: Enable to pass multiple passphrases
This feature is required to copy keys in a smartcard without
any user interaction.
It currently only used by --quick-keytocard with a command line
like this:
gpg --batch --pinentry-mode loopback --passphrase-file ~/p1
--passphrase-file ~/p2 --quick-keytocard <keyid> auth
This is not a designed solution(hack). This could break any
time.
Next I will try to build tests explain the odd behavior.
The problem is (get_static_passphrase) now have a side
effect that after the call to (get_static_passphrase) the
next password will be returned on the next call to
(get_static_passphrase). And (get_static_passphrase) the
order and of calls defines the returned password.
I discovered that in gpgsm almost the same code is used.
But it is in different files. So should id refactor this?
Currently i did not changed this gpgsm.
* g10/gpg.c changed switch cases oPassphraseFD/oPassphraseFile
to store the incoming file descriptor.
* g10/gpg.c passed the collected fds to the new
(read_passphrase_from_fds)
* g10/keydb.h added STATIC_PASSWORD_COUNT constant (4)
* g10/keydb.h modified (read_passphrase_from_fd) to
(read_passphrase_from_fds) to pass multiple fds
* g10/passphrase.c removed fd_passwd
* g10/passphrase.c added fd_passwds[STATIC_PASSWORD_COUNT]
* g10/passphrase.c added fd_passwd_idx use count
* g10/passphrase.c added fd_passwd_req roundrobin counter
* g10/passphrase.c (have_static_passphrase) uses fd_passwd_idx
* g10/passphrase.c (get_static_passphrase) roundrobin behavior
* g10/passphrase.c (set_passphrase_from_string) appends to fd_passwds
* g10/passphrase.c (read_passphrase_from_fd) static and wipe added
* g10/passphrase.c (read_passphrase_from_fds) loops over fds
* g10/passphrase.c (passphrase_to_dek) change direct use of
fw_passwd to (get_static_passphrase)
Signed-off-by: Meno Abels <meno.abels at adviser.com>
diff --git a/doc/gpg.texi b/doc/gpg.texi
index 7adccf3..78da66a 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -678,8 +678,8 @@ is written. If 'auth' is choosen the @code{slot} 3 is used.
To write to a keyslot needs the smartcard admin pin. This is usally
requested with pinentry. In the case of passing the password through
loopback pinentry you have to provide a second password. This could
-be done with --passphrase-fds. The second specified fd should provide
-the admin pin.
+be done with --passphrase-fd. You can call --passphrase-fd/file
+multiple to pass the admin pin.
@item --gen-key
@opindex gen-key
@@ -2965,8 +2965,8 @@ passphrase. Defaults to 1 repetition.
@opindex passphrase-fd
Read the passphrase from file descriptor @code{n}. Only the first line
will be read from file descriptor @code{n}. If you use 0 for @code{n},
-the passphrase will be read from STDIN. This can only be used if only
-one passphrase is supplied.
+the passphrase will be read from STDIN. This can called multiple to
+pass multiple passphrases.
Note that this passphrase is only used if the option @option{--batch}
has also been given. This is different from GnuPG version 1.x.
@@ -2976,7 +2976,8 @@ has also been given. This is different from GnuPG version 1.x.
Read the passphrase from file @code{file}. Only the first line will
be read from file @code{file}. This can only be used if only one
passphrase is supplied. Obviously, a passphrase stored in a file is
-of questionable security if other users can read this file. Don't use
+of questionable security if other users can read this file.
+This can called multiple to pass multiple passphrases. Don't use
this option if you can avoid it.
Note that this passphrase is only used if the option @option{--batch}
has also been given. This is different from GnuPG version 1.x.
@@ -2985,8 +2986,9 @@ has also been given. This is different from GnuPG version 1.x.
@opindex passphrase
Use @code{string} as the passphrase. This can only be used if only one
passphrase is supplied. Obviously, this is of very questionable
-security on a multi-user system. Don't use this option if you can
-avoid it.
+security on a multi-user system. This can called multiple to
+pass multiple passphrases.
+Don't use this option if you can avoid it.
Note that this passphrase is only used if the option @option{--batch}
has also been given. This is different from GnuPG version 1.x.
diff --git a/g10/gpg.c b/g10/gpg.c
index deef69a..edca6c4 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -2270,7 +2270,8 @@ main (int argc, char **argv)
char *pers_compress_list = NULL;
int eyes_only=0;
int multifile=0;
- int pwfd = -1;
+ int pwfds_cnt = 0;
+ int pwfds[STATIC_PASSWORD_COUNT];
int ovrseskeyfd = -1;
int fpr_maybe_cmd = 0; /* --fingerprint maybe a command. */
int any_explicit_recipient = 0;
@@ -3036,10 +3037,22 @@ main (int argc, char **argv)
set_passphrase_from_string(pargs.r.ret_str);
break;
case oPassphraseFD:
- pwfd = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
+ if (pwfds_cnt < sizeof(pwfds)/sizeof(pwfds[0]))
+ {
+ pwfds[pwfds_cnt++] = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
+ }
+ else
+ {
+ log_error (_("to much passphrase-fds\n"));
+ }
break;
case oPassphraseFile:
- pwfd = open_info_file (pargs.r.ret_str, 0, 1);
+ if (pwfds_cnt < sizeof(pwfds)/sizeof(pwfds[0]))
+ {
+ pwfds[pwfds_cnt++] = open_info_file (pargs.r.ret_str, 0, 1);
+ } else {
+ log_error (_("to much passphrase-fds\n"));
+ }
break;
case oPassphraseRepeat:
opt.passphrase_repeat = pargs.r.ret_int;
@@ -3876,8 +3889,8 @@ main (int argc, char **argv)
g10_exit(0);
- if (pwfd != -1) /* Read the passphrase now. */
- read_passphrase_from_fd (pwfd);
+ /* Read the passphrase now. */
+ read_passphrase_from_fds (pwfds, pwfds_cnt);
if (ovrseskeyfd != -1 ) /* Read the sessionkey now. */
read_sessionkey_from_fd (ovrseskeyfd);
diff --git a/g10/keydb.h b/g10/keydb.h
index 8daa9ee..22c2170 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -26,6 +26,7 @@
#include "util.h"
#include "packet.h"
+#define STATIC_PASSWORD_COUNT 4
/* What qualifies as a certification (rather than a signature?) */
#define IS_CERT(s) (IS_KEY_SIG(s) || IS_UID_SIG(s) || IS_SUBKEY_SIG(s) \
|| IS_KEY_REV(s) || IS_UID_REV(s) || IS_SUBKEY_REV(s))
@@ -251,7 +252,7 @@ unsigned char encode_s2k_iterations (int iterations);
int have_static_passphrase(void);
const char *get_static_passphrase (void);
void set_passphrase_from_string(const char *pass);
-void read_passphrase_from_fd( int fd );
+void read_passphrase_from_fds( int *fds, int cnt);
void passphrase_clear_cache (const char *cacheid);
DEK *passphrase_to_dek_ext(u32 *keyid, int pubkey_algo,
int cipher_algo, STRING2KEY *s2k, int mode,
diff --git a/g10/passphrase.c b/g10/passphrase.c
index ccd232a..4067af4 100644
--- a/g10/passphrase.c
+++ b/g10/passphrase.c
@@ -43,7 +43,9 @@
#include "call-agent.h"
#include "../common/shareddefs.h"
-static char *fd_passwd = NULL;
+static char *fd_passwds[STATIC_PASSWORD_COUNT];
+static int fd_passwd_idx = 0;
+static int fd_passwd_req = 0;
static char *next_pw = NULL;
static char *last_pw = NULL;
@@ -102,7 +104,7 @@ encode_s2k_iterations (int iterations)
int
have_static_passphrase()
{
- return (!!fd_passwd
+ return (fd_passwd_idx > 0
&& (opt.batch || opt.pinentry_mode == PINENTRY_MODE_LOOPBACK));
}
@@ -111,9 +113,14 @@ have_static_passphrase()
be returned if no passphrase has been set; better use
have_static_passphrase first. */
const char *
-get_static_passphrase (void)
+get_static_passphrase ()
{
- return fd_passwd;
+ int idx = fd_passwd_req++ % fd_passwd_idx;
+ if (fd_passwd_req > fd_passwd_idx)
+ {
+ log_info(_("get_static_passphrase did a wrap a round %d"), fd_passwd_req);
+ }
+ return fd_passwds[idx];
}
@@ -154,14 +161,19 @@ get_last_passphrase()
void
set_passphrase_from_string(const char *pass)
{
- xfree (fd_passwd);
- fd_passwd = xmalloc_secure(strlen(pass)+1);
- strcpy (fd_passwd, pass);
+ if (fd_passwd_idx < sizeof(fd_passwds)/sizeof(fd_passwds[0]))
+ {
+ // xfree (fd_passwd);
+ fd_passwds[fd_passwd_idx] = xmalloc_secure(strlen(pass)+1);
+ strcpy (fd_passwds[fd_passwd_idx], pass);
+ ++fd_passwd_idx;
+ } else {
+ log_info(_("try to set too much passwords"));
+ }
}
-
-void
-read_passphrase_from_fd( int fd )
+static void
+read_passphrase_from_fd( int fd)
{
int i, len;
char *pw;
@@ -200,8 +212,22 @@ read_passphrase_from_fd( int fd )
if (!opt.batch && opt.pinentry_mode != PINENTRY_MODE_LOOPBACK)
tty_printf("\b\b\b \n" );
- xfree ( fd_passwd );
- fd_passwd = pw;
+ set_passphrase_from_string(pw);
+ // wipe the pass password
+ for (i = strlen(pw)-1; i >= 0; --i) {
+ pw[i] = 'X';
+ }
+}
+
+
+void
+read_passphrase_from_fds( int *fds, int cnt )
+{
+ int i;
+ for(i = 0; i < cnt; ++i)
+ {
+ read_passphrase_from_fd(fds[i]);
+ }
}
@@ -360,9 +386,10 @@ passphrase_to_dek (int cipher_algo, STRING2KEY *s2k,
}
else if ( have_static_passphrase () )
{
+ const char *s = get_static_passphrase();
/* Return the passphrase we have stored in FD_PASSWD. */
- pw = xmalloc_secure ( strlen(fd_passwd)+1 );
- strcpy ( pw, fd_passwd );
+ pw = xmalloc_secure ( strlen(s)+1 );
+ strcpy ( pw, s );
}
else
{
> On 2 Dec 2016, at 21:50, Meno Abels <meno.abels at adviser.com> wrote:
>
> Hi,
>
> attachments does not work:
>
> From bf9027719a27dc6c0d5eba5d8a067542ff79514d Mon Sep 17 00:00:00 2001
> From: Meno Abels <meno.abels at adviser.com>
> Date: Fri, 2 Dec 2016 21:23:39 +0100
> Subject: [PATCH] gpg: New option --quick-keytocard
>
> * wrote the documentation for the new option (untested)
> * g10/card-util.c (send_keytocard) added
> * g10/gpg.c added aQuickKeyToCard to cmd_and_opt_values
> * g10/gpg.c added ARGPARSE_c with aQuickKeyToCard
> * g10/gpg.c added handling for aQuickKeyToCard
> * g10/keyedit.c (get_keyno_from_slot_usage) new function
> maps commandline option to keyno.
> * g10/keyedit.c (is_keyno_matching_usage) tests if the
> key has the right usage for the keyno.
> * g10/keyedit.c (keyedit_quick_keytocard) new function
> to prepare the commandline parameter to call
> (send_keytocard) to transfer the key.
> * g10/main.h (keyedit_quick_keytocard) forward decl
> * g10/main.h (send_keytocard) forward decl
>
> Tested: by hand i send ~15 keys to reseted yubikeys
> and try successfully to use the key for sign,encr,auth
> Missing: in batch we need to pass the adminpin via
> loopback pinentry
>
> Signed-off-by: Meno Abels <meno.abels at adviser.com>
> ---
> doc/gpg.texi | 18 +++++++++++
> g10/card-util.c | 62 ++++++++++++++++++++++++++++++++++++
> g10/gpg.c | 25 +++++++++++++++
> g10/keyedit.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> g10/main.h | 4 +++
> 5 files changed, 208 insertions(+)
>
> diff --git a/doc/gpg.texi b/doc/gpg.texi
> index b01d0a3..7adccf3 100644
> --- a/doc/gpg.texi
> +++ b/doc/gpg.texi
> @@ -663,6 +663,24 @@ for the subkey. Several formats are supported; commonly the ISO
> YYYY-MM-DD format is used. The values ``never'', ``none'', or ``-''
> can be used for no expiration date.
>
> +
> + at item --quick-keytocard @code{fpr} (@code{slot}|@code{usage}) [@code{serial}]
> + at opindex quick-keytocard
> +Sends the key identified by the fingerprint @code{fpr} to the by
> + at code{serial} identified smartcard. If @code{serial} is not set
> +the first card will be used. The @code{serial} is the serialnumber
> +of the smartcard. This number is found in "--card-status".
> +The @code{slot} and @code{usage} specify the slot in the smartcard
> +which should receive the choosen key. @code{slot} is just the number
> +of the slot starting with 1. The @code{usage} maps if 'sign' is to
> + at code{slot} 1. If @code{usage} is set to 'encr' the @code{slot} 2
> +is written. If 'auth' is choosen the @code{slot} 3 is used.
> +To write to a keyslot needs the smartcard admin pin. This is usally
> +requested with pinentry. In the case of passing the password through
> +loopback pinentry you have to provide a second password. This could
> +be done with --passphrase-fds. The second specified fd should provide
> +the admin pin.
> +
> @item --gen-key
> @opindex gen-key
> Generate a new key pair using the current default parameters. This is
> diff --git a/g10/card-util.c b/g10/card-util.c
> index e358572..b905a29 100644
> --- a/g10/card-util.c
> +++ b/g10/card-util.c
> @@ -1628,6 +1628,68 @@ card_store_subkey (KBNODE node, int use)
> return okay;
> }
>
> +int
> +send_keytocard(PKT_public_key *pk, int keyno, const char *serialno) {
> + gnupg_isotime_t timebuf;
> + struct agent_card_info_s info;
> + unsigned int nbits;
> + gpg_error_t err = 0;
> + int rc = 0;
> + char *hexgrip = 0;
> + int okay = 0;
> +
> + if (get_info_for_key_operation (&info))
> + {
> + log_error (_("get_info_for_key_operations: failed:%s"),
> + gpg_strerror (err));
> + goto leave;
> + }
> + if (serialno && *serialno && strcmp(info.serialno, serialno)) {
> + log_error (_("The card serial no does not match %s!=%s"), serialno,
> + info.serialno);
> + goto leave;
> + }
> + if (!info.extcap.ki)
> + {
> + log_error (_("The card does not support the import of keys"));
> + goto leave;
> + }
> + nbits = nbits_from_pk (pk);
> + if (!info.is_v2 && nbits != 1024)
> + {
> + log_error (_("You may only store a 1024 bit RSA key on the card"));
> + goto leave;
> + }
> + if (info.is_v2 && !info.extcap.aac
> + && info.key_attr[keyno-1].nbits != nbits)
> + {
> + log_error (_("Key does not match the card's capability. %d %d"), keyno, nbits);
> + goto leave;
> + }
> + if ((keyno == 1 && info.fpr1valid)
> + || (keyno == 2 && info.fpr2valid)
> + || (keyno == 3 && info.fpr3valid)) {
> + log_info (_("replace existing key in slot %d"), keyno);
> + }
> + if ((err = hexkeygrip_from_pk (pk, &hexgrip))) {
> + log_error (_("hexkeygrip_from_pk failed with %s"), gpg_strerror(err));
> + goto leave;
> + }
> + epoch2isotime (timebuf, (time_t)pk->timestamp);
> + if ((err = agent_keytocard (hexgrip, keyno, rc, info.serialno, timebuf))) {
> + log_error (_("agent_keytocard failed: %s\n"), gpg_strerror (rc));
> + if ((rc = agent_scd_learn (NULL, 1))) {
> + log_error (_("agent_scd_learn failed: %s\n"), gpg_strerror (rc));
> + }
> + } else {
> + okay = 1;
> + }
> +leave:
> + xfree (hexgrip);
> + agent_release_card_info (&info);
> + return okay;
> +}
> +
>
>
> /* Direct sending of an hex encoded APDU with error printing. */
> diff --git a/g10/gpg.c b/g10/gpg.c
> index 7cf51f2..deef69a 100644
> --- a/g10/gpg.c
> +++ b/g10/gpg.c
> @@ -123,6 +123,7 @@ enum cmd_and_opt_values
> aQuickAddUid,
> aQuickAddKey,
> aQuickRevUid,
> + aQuickKeyToCard,
> aListConfig,
> aListGcryptConfig,
> aGPGConfList,
> @@ -448,6 +449,8 @@ static ARGPARSE_OPTS opts[] = {
> ARGPARSE_c (aQuickAddKey, "quick-addkey", "@"),
> ARGPARSE_c (aQuickRevUid, "quick-revuid",
> N_("quickly revoke a user-id")),
> + ARGPARSE_c (aQuickKeyToCard, "quick-keytocard",
> + N_("send a secret key to a smartcard")),
> ARGPARSE_c (aFullKeygen, "full-gen-key" ,
> N_("full featured key pair generation")),
> ARGPARSE_c (aGenRevoke, "gen-revoke",N_("generate a revocation certificate")),
> @@ -2549,6 +2552,7 @@ main (int argc, char **argv)
> case aQuickAddUid:
> case aQuickAddKey:
> case aQuickRevUid:
> + case aQuickKeyToCard:
> case aExportOwnerTrust:
> case aImportOwnerTrust:
> case aRebuildKeydbCaches:
> @@ -3953,6 +3957,7 @@ main (int argc, char **argv)
> case aQuickAddUid:
> case aQuickAddKey:
> case aQuickRevUid:
> + case aQuickKeyToCard:
> case aFullKeygen:
> case aKeygen:
> case aImport:
> @@ -4383,6 +4388,26 @@ main (int argc, char **argv)
> keyedit_quick_revuid (ctrl, uid, uidtorev);
> }
> break;
> + case aQuickKeyToCard:
> + {
> + const char *x_fpr, *x_slot_usage, *x_smartcard_serial;
> +
> + if (argc < 1 || argc > 4)
> + wrong_args ("--quick-addkey FINGERPRINT (SLOT|USAGE) [SMARTCARDSERIAL]");
> + x_fpr = *argv++; argc--;
> + x_slot_usage = "";
> + x_smartcard_serial = "";
> + if (argc)
> + {
> + x_slot_usage = *argv++; argc--;
> + if (argc)
> + {
> + x_smartcard_serial = *argv++; argc--;
> + }
> + }
> + keyedit_quick_keytocard (ctrl, x_fpr, x_slot_usage, x_smartcard_serial);
> + }
> + break;
>
> case aFastImport:
> opt.import_options |= IMPORT_FAST;
> diff --git a/g10/keyedit.c b/g10/keyedit.c
> index 94fa8c4..764c0df 100644
> --- a/g10/keyedit.c
> +++ b/g10/keyedit.c
> @@ -3341,6 +3341,105 @@ keyedit_quick_addkey (ctrl_t ctrl, const char *fpr, const char *algostr,
> keydb_release (kdbhd);
> }
>
> +int
> +get_keyno_from_slot_usage(const char *slot_usage)
> +{
> + int keyno = 1;
> + if (strcmp(slot_usage, "sign"))
> + {
> + keyno = 2;
> + if (strcmp(slot_usage, "encr"))
> + {
> + keyno = 3;
> + if (strcmp(slot_usage, "auth"))
> + {
> + keyno = atoi(slot_usage);
> + }
> + }
> + }
> + return keyno;
> +}
> +
> +int
> +is_keyno_matching_usage(int keyno, int usage)
> +{
> + if (keyno == 1) {
> + if (!(usage & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_CERT))) {
> + log_error (_("the key for slot 1 is not for signature or certification"));
> + return 0;
> + }
> + }
> + if (keyno == 2) {
> + if (!(usage & (PUBKEY_USAGE_ENC))) {
> + log_error (_("the key for slot 2 is not for encryption"));
> + return 0;
> + }
> + }
> + if (keyno == 3) {
> + if (!(usage & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH))) {
> + log_error (_("the key for slot 1 is not for signature or authentication"));
> + return 0;
> + }
> + }
> + return 1;
> +}
> +/* Unattended send a key to a smartcard */
> +void
> +keyedit_quick_keytocard (ctrl_t ctrl, const char *fpr, const char *slot_usage,
> + const char *serialno)
> +{
> + gpg_error_t err;
> + kbnode_t keyblock;
> + KEYDB_HANDLE kdbhd;
> + KBNODE node = NULL;
> +
> +#ifdef HAVE_W32_SYSTEM
> + /* See keyedit_menu for why we need this. */
> + check_trustdb_stale (ctrl);
> +#endif
> +
> + /* We require a fingerprint because only this uniquely identifies a
> + * key */
> + err = get_pubkey_byname (ctrl, NULL, NULL, fpr, &keyblock, &kdbhd, 1, 1);
> + if (err)
> + {
> + log_error (_("key \"%s\" not found: %s\n"), fpr, gpg_strerror (err));
> + goto leave;
> + }
> +
> + for (node = keyblock; node; node = node->next)
> + {
> + if (PKT_PUBLIC_KEY == node->pkt->pkttype ||
> + PKT_PUBLIC_SUBKEY == node->pkt->pkttype ||
> + PKT_SECRET_KEY == node->pkt->pkttype)
> + {
> + PKT_public_key *pk = node->pkt->pkt.public_key;
> + char hexfpr[2*MAX_FINGERPRINT_LEN+1];
> + hexfingerprint (pk, hexfpr, sizeof hexfpr);
> + if (!strcmp(fpr, hexfpr))
> + {
> + int keyno = get_keyno_from_slot_usage(slot_usage);
> + if (!(1 <= keyno && keyno <= 3))
> + {
> + log_error (_("slot has to be 1,2,3 is %s"), slot_usage);
> + goto leave;
> + }
> + if (!is_keyno_matching_usage(keyno, pk->pubkey_usage))
> + {
> + goto leave;
> + }
> + if (send_keytocard(pk, keyno, serialno))
> + {
> + log_info(_("keytocard for %s to slot %u successful"), hexfpr, keyno);
> + }
> + }
> + }
> + }
> +leave:
> + release_kbnode (keyblock);
> + keydb_release (kdbhd);
> +}
> +
>
>
> static void
> diff --git a/g10/main.h b/g10/main.h
> index 63aec47..c73f682 100644
> --- a/g10/main.h
> +++ b/g10/main.h
> @@ -295,6 +295,9 @@ void keyedit_quick_revuid (ctrl_t ctrl, const char *username,
> const char *uidtorev);
> void keyedit_quick_sign (ctrl_t ctrl, const char *fpr,
> strlist_t uids, strlist_t locusr, int local);
> +void keyedit_quick_keytocard (ctrl_t ctrl, const char *fpr,
> + const char *slot_usage, const char *sm_serial);
> +
> void show_basic_key_info (KBNODE keyblock);
>
> /*-- keygen.c --*/
> @@ -479,6 +482,7 @@ void card_status (estream_t fp, char *serialno, size_t serialnobuflen);
> void card_edit (ctrl_t ctrl, strlist_t commands);
> gpg_error_t card_generate_subkey (KBNODE pub_keyblock);
> int card_store_subkey (KBNODE node, int use);
> +int send_keytocard(PKT_public_key *pk, int keyno, const char *serialno);
> #endif
>
> #define S2K_DECODE_COUNT(_val) ((16ul + ((_val) & 15)) << (((_val) >> 4) + 6))
> --
> 2.9.3 (Apple Git-75)
>
> ----BEGIN PGP MESSAGE-----
> Comment: GPGTools - http://gpgtools.org
>
> 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
> 1e3KzDbkGw8vyc06XXSCRQCZxuE4hN3kxIgIboDhymHNOYf9cZZMCr1ewwEDCAUW
> rqvEKYyNzI4VOxMJq651ak/CaKnG+0ZPjLFQoYugzb3ZDVPDN4qBllOcHJuOZ/bX
> gREu4ElsQMZxE5BBbqaG6j3GmgrdOq/SMTgPoF2JCxbozkW+Xe3zU2WGbNzkbdHV
> 5d1sxIwa6CSbOshmh2N5sSLhxz/8appJZBPsc5w3EW9LuI2f1VNjgLVONdertzjT
> 88KKU+jE8GqIhb7noJU8Mo0PBCvoA2dcXvj58z7Qz3qmFT5MdYntyjK1bdWtomZ8
> HwjMV0OMhZqTxvjNH7LxTMuqIAtIvkuHZtAft10m+AMgVkRa+mE8X6YqXhvLH7xO
> uLdHonKuL5WS+3rU3v5sayfsgTfaYG+BjSYG8mwyAZcB7H+R+gqH1LblC2dCmD9b
> 5i5NvyaMwCG3DUUs4ecplyuQghCtarYDqEDGTgSewRqubfGWEO75oaYN/f9abdHu
> VJzbyRxsjpvWa4ETlqcOu2IsiCXJ5hnOm9h6RTngVmxIC2aeYwMLOCslk1Dg2ISi
> jw2ccv3evInt6n1gheYIjucUa41UA9FUMxHqI3gKFJ16kJVctUr1urXYRqivkHoa
> mpaNWk3SFfze0tSNcFR/chb+zgtpQwyKh3Za9WfhIXYkIL+GL8BDgkO8FgQ0fA20
> PJpOSSG7UxwdGwHC4siu3dPFKA6WYyQazfS6VRKHG77QRTJ56F03boQVb2kzTkoA
> pBeSFZhLyKYGUj0kOmya0PWMa06yLx8ThI9f0HPRmrUXr/nQ+9dd9JMje4s3f+Zv
> X/mc842z777i7MYvHo/d8a4Lbhw+dXqNcMlv+CvP3nvFufd//I3C2d/J/Medez70
> v/+jP/6VP97/rqMHz3zyq9l3xNJ7nh5Z1m/fMabf++PHvvt/hUvuzN/+wtKbn775
> kYFt/zm07cznRm946+Dak989ZR7//l3vvUf72C3LkvaZk9KTb3Z/+czXv2c8/ejF
> ByIf/vzWfQ+ee23qmPQT+WPv3Xi5k/7h7tOv3/qdnWde/8NnRt5ev7Dd/Ob3rzt3
> /auXPvNU92XvG3t4t7Hjg/tH37gydePlk9f9waXuX754dOSt+x9/5cm9S/kbXnzn
> sasuOvPRkcrkVTu7rto/8Ogjjz0cfW5CWbdZ/GFt5r4dt920zjwVveXM0X/+ys+i
> A8f3Hfn3+Mj4C2Nnzqz9xcMvxk5sO0Rf+Jcv3Hn78QdPf+8j9x77zntqz27+1uv/
> ps+m3h56/O1HH77yg8/9fP3XT//u3x+5e+7P/2Tdjpc2PXE0e/SdWvX4iU8ePGLc
> 9g/PyKfPfeO+Z7cmf/HqrT+9d8dnx7uunn5AVv7q6VeVi9684JVrzj1RflmbvvBb
> T129b/LM9M+ev+fC+7/87Ytf+tcH8nvvfui+V9b9zV1fG/rCTx+687Mf3vpnXzqx
> fPUnvn3yt2966Pfeia259Xl6ee/zL98yZi+e/f2b7//v3JB1R+TSr732kad+NJhZ
> zn/gWO1L13drn3/ut/7oU490U6n3MvfgE4MvfPrkNydvveDRJ3/ztsTRKz7xvjd+
> fOyfTvz1j8bP9ab+8dj4W39X+upbz/385bWXPvDmzkM/2PXEgy/9oP/kuTvuufLu
> Pz3yFx84FD1xavSu/wc=
> =KMn1
> -----END PGP MESSAGE-----
>
>
>> On 2 Dec 2016, at 21:45, Meno Abels <meno.abels at adviser.com> wrote:
>>
>> Hi,
>>
>> i yesterday, ask about this new option.
>> And now I used this lazy friday evening to implement the first part.
>> I tried to figure out how to contribute code and the right coding style. Both I did not
>> had success with. So please be patient with me and give me feedback what i should change
>> to get this in upstream.
>>
>> I attached the patch from this commit:
>> ce29272e24e7b718b8fca9b84bc728e65f3dea24
>>
>> I’m not sure how the process with code contribution works in gpg so again please be
>> patient and give me feedback.
>>
>> Next i will try to find a solution to the loopback pinentry to pass both password.
>>
>> Thx in advance
>>
>> meno
>>
>> <0001-gpg-New-option-quick-keytocard.patch><0001-gpg-New-option-quick-keytocard.patch.asc>
>>
>>> On 1 Dec 2016, at 13:26, Meno Abels <meno.abels at adviser.com> wrote:
>>>
>>> hello,
>>>
>>> i tried to invoke from the --card-edit menu the keytocard function within batch file. But that seams not work.
>>>
>>> Which is a document feature —card-edit is a interactive tool.
>>>
>>> To make it working, I would try to implement —quick-keytocard in the same style like —quick-addkey.
>>>
>>> I looked around in gpgme and didn’t not found any entry point which allows me to do keytocard.
>>>
>>> My question is, if i try now to implement quick-keytocard, would you accept my patch?
>>>
>>> Or is there any other idea how to send a key from gpg to a smartcard within a batch?
>>>
>>> I currently only know one bigger obstacle keytocard needs a passphrase and the adminpin both a gather via
>>> pinentry. This leads to a extension to the batch mode command line (--no-tty --pinentry-mode loopback --passphrase-fd).
>>>
>>> Thx in advance
>>>
>>> meno
>>>
>>>
>>>
>>
>> _______________________________________________
>> Gnupg-devel mailing list
>> Gnupg-devel at gnupg.org
>> http://lists.gnupg.org/mailman/listinfo/gnupg-devel
>
More information about the Gnupg-devel
mailing list