mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-30 16:17:02 +01:00
common: Correctly render SHA256-based ssh fingerprints.
* common/ssh-utils.c (dummy_realloc): New function. (dummy_free): Likewise. (get_fingerprint): Prepend the fingerprint with the name of the digest algorithm. Correctly render SHA256-based ssh fingerprints. * common/t-ssh-utils.c (sample_keys): Add SHA256 hashes for the keys. (main): Add an option to dump the keys to gather fingerprints, also print the SHA256 fingerprint for keys given as arguments, and check the SHA256 fingerprints of the test keys. GnuPG-bug-id: 2106 Signed-off-by: Justus Winter <justus@g10code.com>
This commit is contained in:
parent
3ac1a9d3a0
commit
3a07a69dfc
@ -64,6 +64,9 @@ is_eddsa (gcry_sexp_t keyparms)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Dummy functions for es_mopen. */
|
||||
static void *dummy_realloc (void *mem, size_t size) { (void) size; return mem; }
|
||||
static void dummy_free (void *mem) { (void) mem; }
|
||||
|
||||
/* Return the Secure Shell type fingerprint for KEY using digest ALGO.
|
||||
The length of the fingerprint is returned at R_LEN and the
|
||||
@ -232,10 +235,74 @@ get_fingerprint (gcry_sexp_t key, int algo,
|
||||
|
||||
if (as_string)
|
||||
{
|
||||
*r_fpr = (algo == GCRY_MD_MD5 ? bin2hexcolon : /* XXX we need base64 */ bin2hex)
|
||||
(gcry_md_read (md, algo), gcry_md_get_algo_dlen (algo), NULL);
|
||||
const char *algo_name;
|
||||
char *fpr;
|
||||
|
||||
/* Prefix string with the algorithm name and a colon. */
|
||||
algo_name = gcry_md_algo_name (algo);
|
||||
*r_fpr = xtrymalloc (strlen (algo_name) + 1 + 3 * gcry_md_get_algo_dlen (algo) + 1);
|
||||
if (*r_fpr == NULL)
|
||||
{
|
||||
err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
|
||||
goto leave;
|
||||
}
|
||||
|
||||
strncpy (*r_fpr, algo_name, strlen (algo_name));
|
||||
fpr = (char *) *r_fpr + strlen (algo_name);
|
||||
*fpr++ = ':';
|
||||
|
||||
if (algo == GCRY_MD_MD5)
|
||||
{
|
||||
bin2hexcolon (gcry_md_read (md, algo), gcry_md_get_algo_dlen (algo), fpr);
|
||||
strlwr (fpr);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct b64state b64s;
|
||||
estream_t stream;
|
||||
char *p;
|
||||
long int len;
|
||||
|
||||
/* Write the base64-encoded hash to fpr. */
|
||||
stream = es_mopen (fpr, 3 * gcry_md_get_algo_dlen (algo) + 1, 0,
|
||||
0, dummy_realloc, dummy_free, "w");
|
||||
if (stream == NULL)
|
||||
{
|
||||
err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = b64enc_start_es (&b64s, stream, "");
|
||||
if (err)
|
||||
{
|
||||
es_fclose (stream);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = b64enc_write (&b64s,
|
||||
gcry_md_read (md, algo), gcry_md_get_algo_dlen (algo));
|
||||
if (err)
|
||||
{
|
||||
es_fclose (stream);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Finish, get the length, and close the stream. */
|
||||
err = b64enc_finish (&b64s);
|
||||
len = es_ftell (stream);
|
||||
es_fclose (stream);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
/* Terminate. */
|
||||
fpr[len] = 0;
|
||||
|
||||
/* Strip the trailing padding characters. */
|
||||
for (p = fpr + len - 1; p > fpr && *p == '='; p--)
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
*r_len = strlen (*r_fpr) + 1;
|
||||
strlwr (*r_fpr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -28,7 +28,12 @@
|
||||
#include "ssh-utils.h"
|
||||
|
||||
|
||||
static struct { const char *key; const char *fpr; } sample_keys[] = {
|
||||
static struct
|
||||
{
|
||||
const char *key;
|
||||
const char *fpr_md5;
|
||||
const char *fpr_sha256;
|
||||
} sample_keys[] = {
|
||||
{ "(protected-private-key "
|
||||
"(rsa "
|
||||
"(n #"
|
||||
@ -70,7 +75,8 @@ static struct { const char *key; const char *fpr; } sample_keys[] = {
|
||||
")"
|
||||
"(comment passphrase_is_abc)"
|
||||
")",
|
||||
"c7:c6:a7:ec:04:6c:87:59:54:f2:88:58:09:e0:f2:b1"
|
||||
"MD5:c7:c6:a7:ec:04:6c:87:59:54:f2:88:58:09:e0:f2:b1",
|
||||
"SHA256:ksKb4DKk2SFX56GRtpt0szBnyjiYARSb2FNlUb7snnE"
|
||||
},
|
||||
{
|
||||
"(protected-private-key "
|
||||
@ -99,7 +105,8 @@ static struct { const char *key; const char *fpr; } sample_keys[] = {
|
||||
")"
|
||||
"(comment sample_dsa_passphrase_is_abc)"
|
||||
")",
|
||||
"2d:b1:70:1a:04:9e:41:a3:ce:27:a5:c7:22:fe:3a:a3"
|
||||
"MD5:2d:b1:70:1a:04:9e:41:a3:ce:27:a5:c7:22:fe:3a:a3",
|
||||
"SHA256:z8+8HEuD/5QpegGS4tSK02dJF+a6o2V67VM2gOPz9oQ"
|
||||
},
|
||||
{ /* OpenSSH 6.7p1 generated key: */
|
||||
"(protected-private-key "
|
||||
@ -118,7 +125,8 @@ static struct { const char *key; const char *fpr; } sample_keys[] = {
|
||||
")"
|
||||
"(comment \"ecdsa w/o comment\")"
|
||||
")", /* Passphrase="abc" */
|
||||
"93:4f:08:02:7d:cb:16:9b:0c:39:21:4b:cf:28:5a:19"
|
||||
"MD5:93:4f:08:02:7d:cb:16:9b:0c:39:21:4b:cf:28:5a:19",
|
||||
"SHA256:zSj4uXfE1hlQnESD2LO723fMGXsNwzHrfqOfqep37is"
|
||||
},
|
||||
{ /* OpenSSH 6.7p1 generated key: */
|
||||
"(protected-private-key "
|
||||
@ -139,7 +147,8 @@ static struct { const char *key; const char *fpr; } sample_keys[] = {
|
||||
")"
|
||||
"(comment \"ecdsa w/o comment\")"
|
||||
")", /* Passphrase="abc" */
|
||||
"a3:cb:44:c8:56:15:25:62:85:fd:e8:04:7a:26:dc:76"
|
||||
"MD5:a3:cb:44:c8:56:15:25:62:85:fd:e8:04:7a:26:dc:76",
|
||||
"SHA256:JuQh5fjduynuuTEwI9C6yAKK1NnLX9PPd7TP0qZfbGs"
|
||||
},
|
||||
{ /* OpenSSH 6.7p1 generated key: */
|
||||
"(protected-private-key "
|
||||
@ -161,7 +170,8 @@ static struct { const char *key; const char *fpr; } sample_keys[] = {
|
||||
")"
|
||||
"(comment \"ecdsa w/o comment\")"
|
||||
")", /* Passphrase="abc" */
|
||||
"1e:a6:94:ab:bd:81:73:5f:22:bc:0e:c7:89:f6:68:df"
|
||||
"MD5:1e:a6:94:ab:bd:81:73:5f:22:bc:0e:c7:89:f6:68:df",
|
||||
"SHA256:+pbRyYa2UBwDki1k4Wziu2CKrdJIbZM/hOWOQ/sNe/0"
|
||||
},
|
||||
{ /* OpenSSH 6.7p1 generated key: */
|
||||
"(protected-private-key "
|
||||
@ -180,7 +190,8 @@ static struct { const char *key; const char *fpr; } sample_keys[] = {
|
||||
")"
|
||||
"(comment \"eddsa w/o comment\")"
|
||||
")", /* Passphrase="abc" */
|
||||
"f1:fa:c8:a6:40:bb:b9:a1:65:d7:62:65:ac:26:78:0e"
|
||||
"MD5:f1:fa:c8:a6:40:bb:b9:a1:65:d7:62:65:ac:26:78:0e",
|
||||
"SHA256:yhwBfYnTOnSXcWf1EOPo+oIIpNJ6w/bG36udZ96MmsQ"
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
@ -259,9 +270,43 @@ main (int argc, char **argv)
|
||||
char *string;
|
||||
int idx;
|
||||
|
||||
if (argc == 2)
|
||||
/* --dump-keys dumps the keys as KEYGRIP.key.IDX. Useful to compute
|
||||
fingerprints to enhance the test vectors. */
|
||||
if (argc == 2 && strcmp (argv[1], "--dump-keys") == 0)
|
||||
for (idx=0; sample_keys[idx].key; idx++)
|
||||
{
|
||||
FILE *s;
|
||||
char *name;
|
||||
char grip[20];
|
||||
char *hexgrip;
|
||||
|
||||
err = keygrip_from_canon_sexp (sample_keys[idx].key,
|
||||
strlen (sample_keys[idx].key),
|
||||
grip);
|
||||
if (err)
|
||||
{
|
||||
fprintf (stderr, "%s:%d: error computing keygrip: %s\n",
|
||||
__FILE__, __LINE__, gpg_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
hexgrip = bin2hex (grip, 20, NULL);
|
||||
|
||||
name = xtryasprintf ("%s.key.%d", hexgrip, idx);
|
||||
s = fopen (name, "w");
|
||||
if (s == NULL)
|
||||
{
|
||||
fprintf (stderr, "%s:%d: error opening file: %s\n",
|
||||
__FILE__, __LINE__, gpg_strerror (gpg_error_from_syserror ()));
|
||||
exit (1);
|
||||
}
|
||||
xfree (name);
|
||||
fprintf (s, "%s", sample_keys[idx].key);
|
||||
fclose (s);
|
||||
}
|
||||
else if (argc == 2)
|
||||
{
|
||||
key = read_key (argv[1]);
|
||||
|
||||
err = ssh_get_fingerprint_string (key, GCRY_MD_MD5, &string);
|
||||
if (err)
|
||||
{
|
||||
@ -271,6 +316,17 @@ main (int argc, char **argv)
|
||||
}
|
||||
puts (string);
|
||||
xfree (string);
|
||||
|
||||
err = ssh_get_fingerprint_string (key, GCRY_MD_SHA256, &string);
|
||||
if (err)
|
||||
{
|
||||
fprintf (stderr, "%s:%d: error getting fingerprint: %s\n",
|
||||
__FILE__, __LINE__, gpg_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
puts (string);
|
||||
xfree (string);
|
||||
|
||||
gcry_sexp_release (key);
|
||||
}
|
||||
else
|
||||
@ -288,7 +344,6 @@ main (int argc, char **argv)
|
||||
}
|
||||
|
||||
err = ssh_get_fingerprint_string (key, GCRY_MD_MD5, &string);
|
||||
gcry_sexp_release (key);
|
||||
if (err)
|
||||
{
|
||||
fprintf (stderr, "%s:%d: error getting fingerprint for "
|
||||
@ -297,16 +352,38 @@ main (int argc, char **argv)
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (strcmp (string, sample_keys[idx].fpr))
|
||||
if (strcmp (string, sample_keys[idx].fpr_md5))
|
||||
{
|
||||
fprintf (stderr, "%s:%d: fingerprint mismatch for "
|
||||
"sample key %d\n",
|
||||
__FILE__, __LINE__, idx);
|
||||
fprintf (stderr, "want: %s\n got: %s\n",
|
||||
sample_keys[idx].fpr, string);
|
||||
sample_keys[idx].fpr_md5, string);
|
||||
exit (1);
|
||||
}
|
||||
xfree (string);
|
||||
|
||||
err = ssh_get_fingerprint_string (key, GCRY_MD_SHA256, &string);
|
||||
if (err)
|
||||
{
|
||||
fprintf (stderr, "%s:%d: error getting fingerprint for "
|
||||
"sample key %d: %s\n",
|
||||
__FILE__, __LINE__, idx, gpg_strerror (err));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (strcmp (string, sample_keys[idx].fpr_sha256))
|
||||
{
|
||||
fprintf (stderr, "%s:%d: fingerprint mismatch for "
|
||||
"sample key %d\n",
|
||||
__FILE__, __LINE__, idx);
|
||||
fprintf (stderr, "want: %s\n got: %s\n",
|
||||
sample_keys[idx].fpr_sha256, string);
|
||||
exit (1);
|
||||
}
|
||||
xfree (string);
|
||||
|
||||
gcry_sexp_release (key);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user