gpg: Add option --with-v5-fingerprint

* g10/gpg.c (oWithV5Fingerprint): New.
(opts): Add new option.
(main): Set option.
* g10/options.h (opt): Add with_v5_fingerprint.
* g10/keyid.c (hash_public_key): Factor out to ...
(do_hash_public_key): this.  Add new arg to foce v5 style hashing.
(v5_fingerprint_from_pk): New.
(v5hexfingerprint): New.
* g10/keylist.c (print_fingerprint): Print v5 fingerprint for v4 keys
if the option is set.
--

GnuPG-bug-id: 6705
This commit is contained in:
Werner Koch 2023-09-04 16:34:55 +02:00
parent d90f1e5fa4
commit 1be7882344
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
6 changed files with 102 additions and 9 deletions

View File

@ -2849,6 +2849,11 @@ achieved by using the @option{--with-fingerprint} twice but by using
this option along with keyid-format "none" a compact fingerprint is this option along with keyid-format "none" a compact fingerprint is
printed. printed.
@item --with-v5-fingerprint
@opindex with-v5-fingerprint
In a colon mode listing emit "fp2" lines for version 4 OpenPGP keys
having a v5 style fingerprint of the key.
@item --with-icao-spelling @item --with-icao-spelling
@opindex with-icao-spelling @opindex with-icao-spelling
Print the ICAO spelling of the fingerprint in addition to the hex digits. Print the ICAO spelling of the fingerprint in addition to the hex digits.

View File

@ -203,6 +203,7 @@ enum cmd_and_opt_values
oAskCertLevel, oAskCertLevel,
oNoAskCertLevel, oNoAskCertLevel,
oFingerprint, oFingerprint,
oWithV5Fingerprint,
oWithFingerprint, oWithFingerprint,
oWithSubkeyFingerprint, oWithSubkeyFingerprint,
oWithICAOSpelling, oWithICAOSpelling,
@ -816,6 +817,7 @@ static gpgrt_opt_t opts[] = {
ARGPARSE_s_n (oWithKeyData,"with-key-data", "@"), ARGPARSE_s_n (oWithKeyData,"with-key-data", "@"),
ARGPARSE_s_n (oWithSigList,"with-sig-list", "@"), ARGPARSE_s_n (oWithSigList,"with-sig-list", "@"),
ARGPARSE_s_n (oWithSigCheck,"with-sig-check", "@"), ARGPARSE_s_n (oWithSigCheck,"with-sig-check", "@"),
ARGPARSE_s_n (oWithV5Fingerprint, "with-v5-fingerprint", "@"),
ARGPARSE_s_n (oWithFingerprint, "with-fingerprint", "@"), ARGPARSE_s_n (oWithFingerprint, "with-fingerprint", "@"),
ARGPARSE_s_n (oWithSubkeyFingerprint, "with-subkey-fingerprint", "@"), ARGPARSE_s_n (oWithSubkeyFingerprint, "with-subkey-fingerprint", "@"),
ARGPARSE_s_n (oWithSubkeyFingerprint, "with-subkey-fingerprints", "@"), ARGPARSE_s_n (oWithSubkeyFingerprint, "with-subkey-fingerprints", "@"),
@ -2887,6 +2889,9 @@ main (int argc, char **argv)
opt_log_time = 1; opt_log_time = 1;
break; break;
case oWithV5Fingerprint:
opt.with_v5_fingerprint = 1;
break;
case oWithFingerprint: case oWithFingerprint:
opt.with_fingerprint = 1; opt.with_fingerprint = 1;
opt.fingerprint++; opt.fingerprint++;
@ -3791,6 +3796,14 @@ main (int argc, char **argv)
g10_exit(2); g10_exit(2);
} }
/* Set depended fingerprint options. */
if (opt.with_v5_fingerprint && !opt.with_fingerprint)
{
opt.with_fingerprint = 1;
if (!opt.fingerprint)
opt.fingerprint = 1;
}
/* Process common component options. */ /* Process common component options. */
if (parse_comopt (GNUPG_MODULE_NAME_GPG, debug_argparser)) if (parse_comopt (GNUPG_MODULE_NAME_GPG, debug_argparser))
{ {

View File

@ -570,8 +570,10 @@ const char *colon_datestr_from_pk (PKT_public_key *pk);
const char *colon_datestr_from_sig (PKT_signature *sig); const char *colon_datestr_from_sig (PKT_signature *sig);
const char *colon_expirestr_from_sig (PKT_signature *sig); const char *colon_expirestr_from_sig (PKT_signature *sig);
byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len ); byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
byte *v5_fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len);
void fpr20_from_pk (PKT_public_key *pk, byte array[20]); void fpr20_from_pk (PKT_public_key *pk, byte array[20]);
char *hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen); char *hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen);
char *v5hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen);
char *format_hexfingerprint (const char *fingerprint, char *format_hexfingerprint (const char *fingerprint,
char *buffer, size_t buflen); char *buffer, size_t buflen);
gpg_error_t keygrip_from_pk (PKT_public_key *pk, unsigned char *array); gpg_error_t keygrip_from_pk (PKT_public_key *pk, unsigned char *array);

View File

@ -2,7 +2,7 @@
* Copyright (C) 1998, 1999, 2000, 2001, 2003, * Copyright (C) 1998, 1999, 2000, 2001, 2003,
* 2004, 2006, 2010 Free Software Foundation, Inc. * 2004, 2006, 2010 Free Software Foundation, Inc.
* Copyright (C) 2014 Werner Koch * Copyright (C) 2014 Werner Koch
* Copyright (C) 2016 g10 Code GmbH * Copyright (C) 2016, 2023 g10 Code GmbH
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -18,6 +18,7 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>. * along with this program; if not, see <https://www.gnu.org/licenses/>.
* SPDX-License-Identifier: GPL-3.0-or-later
*/ */
#include <config.h> #include <config.h>
@ -144,10 +145,11 @@ pubkey_string (PKT_public_key *pk, char *buffer, size_t bufsize)
} }
/* Hash a public key. This function is useful for v4 and v5 /* Hash a public key and allow to specify the to be used format.
* fingerprints and for v3 or v4 key signing. */ * Note that if the v5 format is requested for a v4 key, a 0x04 as
void * version is hashed instead of the 0x05. */
hash_public_key (gcry_md_hd_t md, PKT_public_key *pk) static void
do_hash_public_key (gcry_md_hd_t md, PKT_public_key *pk, int use_v5)
{ {
unsigned int n; unsigned int n;
unsigned int nn[PUBKEY_MAX_NPKEY]; unsigned int nn[PUBKEY_MAX_NPKEY];
@ -156,9 +158,8 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
unsigned int nbits; unsigned int nbits;
size_t nbytes; size_t nbytes;
int npkey = pubkey_get_npkey (pk->pubkey_algo); int npkey = pubkey_get_npkey (pk->pubkey_algo);
int is_v5 = pk->version == 5;
n = is_v5? 10 : 6; n = use_v5? 10 : 6;
/* FIXME: We can avoid the extra malloc by calling only the first /* FIXME: We can avoid the extra malloc by calling only the first
mpi_print here which computes the required length and calling the mpi_print here which computes the required length and calling the
real mpi_print only at the end. The speed advantage would only be real mpi_print only at the end. The speed advantage would only be
@ -235,13 +236,14 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
} }
} }
if (is_v5) if (use_v5)
{ {
gcry_md_putc ( md, 0x9a ); /* ctb */ gcry_md_putc ( md, 0x9a ); /* ctb */
gcry_md_putc ( md, n >> 24 ); /* 4 byte length header */ gcry_md_putc ( md, n >> 24 ); /* 4 byte length header */
gcry_md_putc ( md, n >> 16 ); gcry_md_putc ( md, n >> 16 );
gcry_md_putc ( md, n >> 8 ); gcry_md_putc ( md, n >> 8 );
gcry_md_putc ( md, n ); gcry_md_putc ( md, n );
/* Note that the next byte may either be 4 or 5. */
gcry_md_putc ( md, pk->version ); gcry_md_putc ( md, pk->version );
} }
else else
@ -258,7 +260,7 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
gcry_md_putc ( md, pk->pubkey_algo ); gcry_md_putc ( md, pk->pubkey_algo );
if (is_v5) if (use_v5)
{ {
n -= 10; n -= 10;
gcry_md_putc ( md, n >> 24 ); gcry_md_putc ( md, n >> 24 );
@ -285,6 +287,15 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
} }
/* Hash a public key. This function is useful for v4 and v5
* fingerprints and for v3 or v4 key signing. */
void
hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
{
do_hash_public_key (md, pk, pk->version);
}
/* fixme: Check whether we can replace this function or if not /* fixme: Check whether we can replace this function or if not
describe why we need it. */ describe why we need it. */
u32 u32
@ -893,6 +904,37 @@ fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len)
} }
/*
* Return a byte array with the fingerprint for the given PK/SK The
* length of the array is returned in ret_len. Caller must free the
* array or provide an array of length MAX_FINGERPRINT_LEN. This
* version creates a v5 fingerprint even vor v4 keys.
*/
byte *
v5_fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len)
{
const byte *dp;
gcry_md_hd_t md;
if (pk->version == 5)
return fingerprint_from_pk (pk, array, ret_len);
if (gcry_md_open (&md, GCRY_MD_SHA256, 0))
BUG ();
do_hash_public_key (md, pk, 1);
gcry_md_final (md);
dp = gcry_md_read (md, 0);
if (!array)
array = xmalloc (32);
memcpy (array, dp, 32);
gcry_md_close (md);
if (ret_len)
*ret_len = 32;
return array;
}
/* /*
* Get FPR20 for the given PK/SK into ARRAY. * Get FPR20 for the given PK/SK into ARRAY.
* *
@ -952,6 +994,30 @@ hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen)
} }
/* Same as hexfingerprint but returns a v5 fingerprint also for a v4
* key. */
char *
v5hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen)
{
char fprbuf[32];
if (pk->version == 5)
return hexfingerprint (pk, buffer, buflen);
if (!buffer)
{
buffer = xtrymalloc (2 * 32 + 1);
if (!buffer)
return NULL;
}
else if (buflen < 2 * 32 + 1)
log_fatal ("%s: buffer too short (%zu)\n", __func__, buflen);
v5_fingerprint_from_pk (pk, fprbuf, NULL);
return bin2hex (fprbuf, 32, buffer);
}
/* Pretty print a hex fingerprint. If BUFFER is NULL the result is a /* Pretty print a hex fingerprint. If BUFFER is NULL the result is a
malloc'd string. If BUFFER is not NULL the result will be copied malloc'd string. If BUFFER is not NULL the result will be copied
into this buffer. In the latter case BUFLEN describes the length into this buffer. In the latter case BUFLEN describes the length

View File

@ -2413,6 +2413,12 @@ print_fingerprint (ctrl_t ctrl, estream_t override_fp,
if (with_colons && !mode) if (with_colons && !mode)
{ {
es_fprintf (fp, "fpr:::::::::%s:", hexfpr); es_fprintf (fp, "fpr:::::::::%s:", hexfpr);
if (opt.with_v5_fingerprint && pk->version == 4)
{
char *v5fpr = v5hexfingerprint (pk, NULL, 0);
es_fprintf (fp, "\nfp2:::::::::%s:", v5fpr);
xfree (v5fpr);
}
} }
else if (compact && !opt.fingerprint && !opt.with_fingerprint) else if (compact && !opt.fingerprint && !opt.with_fingerprint)
{ {

View File

@ -79,6 +79,7 @@ struct
int with_colons; int with_colons;
int with_key_data; int with_key_data;
int with_icao_spelling; /* Print ICAO spelling with fingerprints. */ int with_icao_spelling; /* Print ICAO spelling with fingerprints. */
int with_v5_fingerprint; /* Option --with-v5-fingerprint active. */
int with_fingerprint; /* Option --with-fingerprint active. */ int with_fingerprint; /* Option --with-fingerprint active. */
int with_subkey_fingerprint; /* Option --with-subkey-fingerprint active. */ int with_subkey_fingerprint; /* Option --with-subkey-fingerprint active. */
int with_keygrip; /* Option --with-keygrip active. */ int with_keygrip; /* Option --with-keygrip active. */