📄 pgppubring.c
字号:
/* * Copyright (C) 1997-2001 Thomas Roessler <roessler@does-not-exist.org> * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later * version. * * This program 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 General Public License for more * details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. *//* * This is a "simple" PGP key ring dumper. * * The output format is supposed to be compatible to the one GnuPG * emits and Mutt expects. * * Note that the code of this program could be considerably less * complex, but most of it was taken from mutt's second generation * key ring parser. * * You can actually use this to put together some fairly general * PGP key management applications. * */#if HAVE_CONFIG_H# include "config.h"#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <time.h>#ifdef HAVE_GETOPT_H# include <getopt.h>#endif#include <errno.h>extern char *optarg;extern int optind;#include "sha1.h"#include "md5.h"#include "lib.h"#include "pgplib.h"#include "pgppacket.h"#define MD5_DIGEST_LENGTH 16#ifdef HAVE_FGETPOS#define FGETPOS(fp,pos) fgetpos((fp),&(pos))#define FSETPOS(fp,pos) fsetpos((fp),&(pos))#else#define FGETPOS(fp,pos) pos=ftello((fp));#define FSETPOS(fp,pos) fseeko((fp),(pos),SEEK_SET)#endifstatic short dump_signatures = 0;static short dump_fingerprints = 0;static void pgpring_find_candidates (char *ringfile, const char *hints[], int nhints);static void pgpring_dump_keyblock (pgp_key_t p);int main (int argc, char * const argv[]){ int c; short version = 2; short secring = 0; const char *_kring = NULL; char *env_pgppath, *env_home; char pgppath[_POSIX_PATH_MAX]; char kring[_POSIX_PATH_MAX]; while ((c = getopt (argc, argv, "f25sk:S")) != EOF) { switch (c) { case 'S': { dump_signatures = 1; break; } case 'f': { dump_fingerprints = 1; break; } case 'k': { _kring = optarg; break; } case '2': case '5': { version = c - '0'; break; } case 's': { secring = 1; break; } default: { fprintf (stderr, "usage: %s [-k <key ring> | [-2 | -5] [ -s] [-S] [-f]] [hints]\n", argv[0]); exit (1); } } } if (_kring) strfcpy (kring, _kring, sizeof (kring)); else { if ((env_pgppath = getenv ("PGPPATH"))) strfcpy (pgppath, env_pgppath, sizeof (pgppath)); else if ((env_home = getenv ("HOME"))) snprintf (pgppath, sizeof (pgppath), "%s/.pgp", env_home); else { fprintf (stderr, "%s: Can't determine your PGPPATH.\n", argv[0]); exit (1); } if (secring) snprintf (kring, sizeof (kring), "%s/secring.%s", pgppath, version == 2 ? "pgp" : "skr"); else snprintf (kring, sizeof (kring), "%s/pubring.%s", pgppath, version == 2 ? "pgp" : "pkr"); } pgpring_find_candidates (kring, (const char**) argv + optind, argc - optind); return 0;}/* The actual key ring parser */static void pgp_make_pgp2_fingerprint (unsigned char *buff, unsigned char *digest){ MD5_CTX context; unsigned int size = 0; MD5Init (&context); size = (buff[0] << 8) + buff[1]; size = ((size + 7) / 8); buff = &buff[2]; MD5Update (&context, buff, size); buff = &buff[size]; size = (buff[0] << 8) + buff[1]; size = ((size + 7) / 8); buff = &buff[2]; MD5Update (&context, buff, size); MD5Final (digest, &context);} /* pgp_make_pgp2_fingerprint() */static pgp_key_t pgp_parse_pgp2_key (unsigned char *buff, size_t l){ pgp_key_t p; unsigned char alg; unsigned char digest[MD5_DIGEST_LENGTH]; size_t expl; unsigned long id; time_t gen_time = 0; unsigned short exp_days = 0; size_t j; int i, k; unsigned char scratch[LONG_STRING]; if (l < 12) return NULL; p = pgp_new_keyinfo(); for (i = 0, j = 2; i < 4; i++) gen_time = (gen_time << 8) + buff[j++]; p->gen_time = gen_time; for (i = 0; i < 2; i++) exp_days = (exp_days << 8) + buff[j++]; if (exp_days && time (NULL) > gen_time + exp_days * 24 * 3600) p->flags |= KEYFLAG_EXPIRED; alg = buff[j++]; p->numalg = alg; p->algorithm = pgp_pkalgbytype (alg); p->flags |= pgp_get_abilities (alg); if (dump_fingerprints) { /* j now points to the key material, which we need for the fingerprint */ p->fp_len = MD5_DIGEST_LENGTH; pgp_make_pgp2_fingerprint (&buff[j], digest); memcpy (p->fingerprint, digest, MD5_DIGEST_LENGTH); } else /* just to be usre */ memset (p->fingerprint, 0, MD5_DIGEST_LENGTH); expl = 0; for (i = 0; i < 2; i++) expl = (expl << 8) + buff[j++]; p->keylen = expl; expl = (expl + 7) / 8; if (expl < 4) goto bailout; j += expl - 8; for (k = 0; k < 2; k++) { for (id = 0, i = 0; i < 4; i++) id = (id << 8) + buff[j++]; snprintf ((char *) scratch + k * 8, sizeof (scratch) - k * 8, "%08lX", id); } p->keyid = safe_strdup ((char *) scratch); return p;bailout: FREE (&p); return NULL;}static void pgp_make_pgp3_fingerprint (unsigned char *buff, size_t l, unsigned char *digest){ unsigned char dummy; SHA1_CTX context; SHA1_Init (&context); dummy = buff[0] & 0x3f; if (dummy == PT_SUBSECKEY || dummy == PT_SUBKEY || dummy == PT_SECKEY) dummy = PT_PUBKEY; dummy = (dummy << 2) | 0x81; SHA1_Update (&context, &dummy, 1); dummy = ((l - 1) >> 8) & 0xff; SHA1_Update (&context, &dummy, 1); dummy = (l - 1) & 0xff; SHA1_Update (&context, &dummy, 1); SHA1_Update (&context, buff + 1, l - 1); SHA1_Final (digest, &context);}static void skip_bignum (unsigned char *buff, size_t l, size_t j, size_t * toff, size_t n){ size_t len; do { len = (buff[j] << 8) + buff[j + 1]; j += (len + 7) / 8 + 2; } while (j <= l && --n > 0); if (toff) *toff = j;}static pgp_key_t pgp_parse_pgp3_key (unsigned char *buff, size_t l){ pgp_key_t p; unsigned char alg; unsigned char digest[SHA_DIGEST_LENGTH]; unsigned char scratch[LONG_STRING]; time_t gen_time = 0; unsigned long id; int i, k; short len; size_t j; p = pgp_new_keyinfo (); j = 2; for (i = 0; i < 4; i++) gen_time = (gen_time << 8) + buff[j++]; p->gen_time = gen_time; alg = buff[j++]; p->numalg = alg; p->algorithm = pgp_pkalgbytype (alg); p->flags |= pgp_get_abilities (alg); if (alg == 17) skip_bignum (buff, l, j, &j, 3); else if (alg == 16 || alg == 20) skip_bignum (buff, l, j, &j, 2); len = (buff[j] << 8) + buff[j + 1]; p->keylen = len; if (alg >= 1 && alg <= 3) skip_bignum (buff, l, j, &j, 2); else if (alg == 17 || alg == 16 || alg == 20) skip_bignum (buff, l, j, &j, 1); pgp_make_pgp3_fingerprint (buff, j, digest); p->fp_len = SHA_DIGEST_LENGTH; for (k = 0; k < 2; k++) { for (id = 0, i = SHA_DIGEST_LENGTH - 8 + k * 4; i < SHA_DIGEST_LENGTH + (k - 1) * 4; i++) id = (id << 8) + digest[i]; snprintf ((char *) scratch + k * 8, sizeof (scratch) - k * 8, "%08lX", id); } p->keyid = safe_strdup ((char *) scratch); return p;}static pgp_key_t pgp_parse_keyinfo (unsigned char *buff, size_t l){ if (!buff || l < 2) return NULL; switch (buff[1]) { case 2: case 3: return pgp_parse_pgp2_key (buff, l); case 4: return pgp_parse_pgp3_key (buff, l); default: return NULL; }}static int pgp_parse_pgp2_sig (unsigned char *buff, size_t l, pgp_key_t p, pgp_sig_t *s){ unsigned char sigtype; time_t sig_gen_time; unsigned long signerid1; unsigned long signerid2; size_t j; int i; if (l < 22) return -1; j = 3; sigtype = buff[j++]; sig_gen_time = 0; for (i = 0; i < 4; i++) sig_gen_time = (sig_gen_time << 8) + buff[j++]; signerid1 = signerid2 = 0; for (i = 0; i < 4; i++) signerid1 = (signerid1 << 8) + buff[j++]; for (i = 0; i < 4; i++) signerid2 = (signerid2 << 8) + buff[j++]; if (sigtype == 0x20 || sigtype == 0x28) p->flags |= KEYFLAG_REVOKED; if (s) { s->sigtype = sigtype; s->sid1 = signerid1; s->sid2 = signerid2; } return 0;}static int pgp_parse_pgp3_sig (unsigned char *buff, size_t l, pgp_key_t p, pgp_sig_t *s){ unsigned char sigtype; unsigned char pkalg; unsigned char hashalg; unsigned char skt; time_t sig_gen_time = -1; long validity = -1; long key_validity = -1; unsigned long signerid1 = 0; unsigned long signerid2 = 0; size_t ml; size_t j; int i; short ii; short have_critical_spks = 0; if (l < 7) return -1; j = 2; sigtype = buff[j++]; pkalg = buff[j++]; hashalg = buff[j++]; for (ii = 0; ii < 2; ii++) { size_t skl; size_t nextone; ml = (buff[j] << 8) + buff[j + 1]; j += 2; if (j + ml > l) break; nextone = j; while (ml) { j = nextone; skl = buff[j++]; if (!--ml) break; if (skl >= 192) { skl = (skl - 192) * 256 + buff[j++] + 192; if (!--ml) break; } if ((int) ml - (int) skl < 0) break; ml -= skl; nextone = j + skl; skt = buff[j++];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -