⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pgpringui.c

📁 著名的加密软件的应用于电子邮件中
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * pgpRingUI.c -- Various user-interface helpers for working with keyrings
 * on a simple stdio tty interface.
 *
 * Copyright (C) 1996,1997 Pretty Good Privacy, Inc. All rights reserved.
 *
 * Written by Colin Plumb.
 *
 * $Id: pgpRingUI.c,v 1.6.2.3.2.1 1997/07/14 16:29:56 quark Exp $
 */

#if HAVE_CONFIG_H
#include "config.h"
#endif

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>	/* for strtol() */
#include <string.h>	/* for strchr() */
#include <time.h>	/* for time () */

#include "pgpDebug.h"
#include "pgpErr.h"
#include "pgpTimeDate.h"	/* for pgpDateString */
#include "pgpUserIO.h"
#include "pgpOutput.h"
#include "pgpRingUI.h"
#include "pgpTrstPkt.h"
#include "pgpTrust.h"
#include "pgpRngPub.h"
#include "pgpRngRead.h"
#include "pgpPubKey.h"
#include "pgpSigSpec.h"
#include "pgpTimeDate.h"
#include "pgpEnv.h"
#include "pgpMem.h"

/*
 * The old PGP format...
  Type Date keyID/bits User ID
  PUB 1996-03-30 58B96505/2048 F0 4A 30 95 20 17 29 E0 DC A3 3F FB C6 5B 79 3F
  foo
  sig! 1996-03-30 58B96505 foo
  PUB 1996-03-30 E9D1E021/4096 1A E2 EF AA FC CB 59 AC D4 2A 1A 90 E3 DD 4F 45
  bar
  sig! 1996-03-30 E9D1E021 bar
 2 key(s) examined
 */

static char const hexchar[16] = {
 '0','1','2','3','4','5','6','7',
 '8','9','A','B','C','D','E','F'
};

/*
 * Pretty-print a 128-bit key fingerprint into the supplied buffer,
 * in varius forms, depending on the "len" argument:
 *           1111111111222222222233333333334444444444555
 * 01234567890123456789012345678901234567890123456789012
 * 01 23 45 67 89 AB CD EF 01 23 45 67 89 AB CD EF/1024 (53 chars)
 * 01 23 45 67 89 AB CD EF 01 23 45 67 89 AB CD EF/1024	(52 chars)
 * 0123 4567 89AB CDEF 0123 4567 89AB CDEF/1024	(45 chars)
 * 0123 4567 89AB CDEF 0123 4567 89AB CDEF/1024	(44 chars)
 * 01234567 89ABCDEF 01234567 89ABCDEF/1024	(41 chars)
 * 01234567 89ABCDEF 01234567 89ABCDEF/1024	(40 chars)
 * 0123456789ABCDEF 0123456789ABCDEF/1024	(38 chars)
 * 0123456789ABCDEF0123456789ABCDEF/1024	(37 chars)
 * 0123456789ABCDEF0123456789ABCDE/1024
 * 0123456789ABCDEF0123456789ABCD/1024
 * 0123456789ABCDEF0123456789ABC/1024 (etc., truncating as needed)
 * ...
 * /1024
 * /102
 * /10
 * /1
 * /
 *
 * Returns the number of characters actually used, guaranteed to
 * be <= the given len.
 * Does NOT null-terminate the array.
 */
size_t
ringTtyFormatFingerprint16(struct RingSet const *set, union RingObject *key,
			   char *buf, size_t len)
{
	static signed char const limits[16] = {
		-1, 46, 38, 46, 34, 46, 38, 46,
		 32, 46, 38, 46, 34, 46, 38, 46 };
	char *p = buf;
	byte hash[16];
	char bits[7];	/* '/' + 65535 max length + '\0' */
	int i;
	int hlen;
	unsigned keylen;

	keylen = ringKeyBits(set, key);	/* Length of key in bits */
	sprintf(bits, "/%u", keylen);	/* Length of decimal length */
	keylen = (unsigned)strlen(bits);
	if (keylen >= len) {
		memcpy(buf, bits, len);
		return len;
	}
	len -= keylen;

	hlen = ringKeyFingerprint16(set, key, hash);

	for (i = 0; i < hlen && (size_t)(p-buf) != len; i++) {
		/* Print each space iff it's okay to */
		if (len > (unsigned)(int)limits[i])
			*p++ = ' ';
		/* Double space in the middle if appropriate */
		if (i == 8 && len >= 36 && len != 39 && len != 47)
			*p++ = ' ';
		*p++ = hexchar[hash[i] >> 4 & 15];
		if ((size_t)(p-buf) == len)
			break;
		*p++ = hexchar[hash[i] & 15];
	}
	memcpy(p, bits, keylen);
	return p+keylen-buf;
}

/*
 * Pretty-print a 160-bit key fingerprint into the supplied buffer,
 * in varius forms, depending on the "len" argument:
 * Version a:
 *           11111111112222222222333333333344444444
 * 012345678901234567890123456789012345678901234567
 * 01234 56789 ABCDE F0123 45678 9ABCD EF012 34567 (48 chars)
 * 01234 56789 ABCDE F0123 45678 9ABCD EF012 34567	(47 chars)
 * 0123456789 ABCDEF0123 456789ABCD EF01234567	(44 chars)
 * 0123456789 ABCDEF0123 456789ABCD EF01234567	(43 chars)
 * 0123456789ABCDEF0123 456789ABCDEF01234567	(41 chars)
 * 0123456789ABCDEF0123456789ABCDEF01234567	(40 chars)
 * 0123456789ABCDEF0123456789ABCDEF0123456
 * 0123456789ABCDEF0123456789ABCDEF012345
 * 0123456789ABCDEF0123456789ABCDEF01234 (etc., truncating as needed)
 *
 * Version b:
 *           1111111111222222222233333333334444444444
 * 01234567890123456789012345678901234567890123456789
 * 0123 4567 89ab cdef 0123 4567 89ab cdef 0123 4567 (50 chars)
 * 0123 4567 89ab cdef 0123 4567 89ab cdef 0123 4567	(49 chars)
 * 01234567 89abcdef 01234567 89abcdef 01234567	(44 chars)
 * 0123456789abcdef0123 456789abcdef01234567	(41 chars)
 * 0123456789ABCDEF0123456789ABCDEF01234567	(40 chars)
 * 0123456789ABCDEF0123456789ABCDEF0123456
 * 0123456789ABCDEF0123456789ABCDEF012345
 * 0123456789ABCDEF0123456789ABCDEF01234 (etc., truncating as needed)
 */
size_t
ringTtyFormatFingerprint20(struct RingSet const *set, union RingObject *key,
			   char *buf, size_t len)
{
	static signed char const limitsa[40] =
		{-1, 46, 42, 46, 40, 46, 42, 46};
	static signed char const limitsb[10] =
		{-1, 48, 43, 48, 43, 48, 43, 48, 43, 48};
	signed char const *limits = limitsb; /* Choose B */
	int period = 4;		/* Use 5 for A, 4 for B */
	char *p = buf;
	byte hash[20];
	int i;
	int hlen;

	hlen = ringKeyFingerprint20(set, key, hash);
	if (hlen < 0)
		return hlen;

	hlen *= 2;

	/* Unlike the 16 byte version, this loops per character */
	for (i = 0; i < hlen && (size_t)(p-buf) != len; i++) {
		/* Print each space iff it's okay to */
		if (i%period == 0)
			 if (len > (unsigned)(int)limits[i/period])
				*p++ = ' ';
		/* Double space in the middle if appropriate */
		if (i == 20 && len >= (unsigned)(limits==limitsa ? 44 : 50) &&
		len != 47)
		 *p++ = ' ';
		if (i & 1)
			*p++ = hexchar[hash[i/2] & 15];
		else
			*p++ = hexchar[hash[i/2] >> 4 & 15];
	}
	return p-buf;
}

int
ringTtyPutFingerprint16(PgpOutputType OutputType, struct RingSet const *set,
			union RingObject *key, unsigned wid)
{
	char buf[54];		/* Incestuous knowledge */

	if (wid > sizeof(buf))
		wid = sizeof(buf);
	wid = (unsigned)ringTtyFormatFingerprint16(set, key, buf, (size_t)wid);
	SpecifiedOutputString(FALSE, OutputType, 0, buf);
	return(wid);
}

int
ringTtyPutFingerprint20(PgpOutputType OutputType, struct RingSet const *set,
	union RingObject *key, unsigned wid)
{
	char buf[50];		/* Incestuous knowledge */

	if (wid > sizeof(buf))
		wid = sizeof(buf);
	wid = (unsigned)ringTtyFormatFingerprint20(set, key, buf, (size_t)wid);
	SpecifiedOutputString(FALSE, OutputType, 0, buf);

	return(wid);
}

int
ringTtyPutKeyID(Boolean DisplayHeaders,
		PgpOutputType OutputType,
		struct RingSet const *set,
		union RingObject *key)
{
	byte buf[8];
	int i;

	if(DisplayHeaders)
	    SpecifiedOutputString(DisplayHeaders,
				  OutputType,
				  0,
				  "");

	ringKeyID8(set, key, NULL, buf);
	for (i = 4; i < 8; i++) {
	    SpecifiedOutputString(FALSE,
				  OutputType,
				  0,
				  "%c%c",
				  hexchar[buf[i] >> 4 & 15],
				  hexchar[buf[i] & 15]);
	}
	return 8;
}

int
ringTtyPutSigID(Boolean DisplayHeaders,
		PgpOutputType OutputType,
		struct RingSet const *set,
		union RingObject *sig)
{
    byte buf[8];
    int i;

    if(DisplayHeaders)
	SpecifiedOutputString(TRUE, OutputType, 0, "");

    ringSigID8(set, sig, NULL, buf);
    for (i = 4; i < 8; i++) {
	SpecifiedOutputString(FALSE,
			      OutputType,
			      0,
			      "%c%c",
			      hexchar[buf[i] >> 4 & 15],
			      hexchar[buf[i] & 15]);
    }
    return 8;
}



/*
 * Write out the given string with all funny characters \-escaped in
 * the manner of C strings, up to "maxlen" characters. Returns the
 * actual number of characters printed, which will always be <= maxlen.
 * If f is NULL, prints nothing. (May be useful for justification
 * computations.) The string is surrounded by quotes q1 and q2
 * (if not '\0'). q2 is also \-escaped if it appears in the string.
 */
unsigned
ringTtyPutString(char const *str,
		 size_t len,
		 unsigned maxlen,
		 Boolean DisplayHeaders,
		 PgpOutputType OutputType,
                 char q1,
		 char q2)
{
    int c = 0;
    size_t t;
    char const *p;
    unsigned remaining = maxlen;
    static char const escapes[] = "\a\b\f\n\r\t\v";
    static char const letters[] = {'a','b','f','n','r','t','v'};

    /* Opening quote */
    if(remaining) {
	if (q1) {
	    SpecifiedOutputString(DisplayHeaders, OutputType, 0, "%c", q1);
	    remaining--;
	}
	else {
	    if(DisplayHeaders)
		/*Display the headers, if desired:*/
		SpecifiedOutputString(TRUE, OutputType, 0, "");
	}
    }

    for (;;) {
	/* Printing can only expand the string, so truncate it */
	if (len > remaining)
	    len = remaining;

	/* Find a directly printable substring */
	p = str;	/* Remember start of substring */
	while (len) {
	    c = (unsigned char)*str;
	    if (!isprint(c) || c == '\\' || c == q2)
		break;
	    str++;
	    len--;
	}

	/* Print from p up to str */
	t = (size_t)(str - p);
	if (t) {
	    char *tmp;
	    if((tmp = pgpAlloc(sizeof(char) * (t + 1)))) {
		memcpy(tmp, p, t);
		*(tmp + t) = '\0';
		SpecifiedOutputString(FALSE, OutputType, 0, tmp);
		pgpFree(tmp);
	    }
	    remaining -= t;
	}

	/* Done with the string? */
	if (!len)
	    break;
	/* Note that remaining >= len > 0, so remaining > 0. */

	/*
	 * c is a character to print that needs escaping.
	 * Now we're going to print it, so remove it from the string.
	 */
	len--;
	str++;

	/* Start with the obligatory backslash */
	SpecifiedOutputString(FALSE, OutputType, 0, "\\");
	if (!--remaining)
	    break;

	/* Simple case 1: escaping printable characters */
	if (isprint(c)) {
	    SpecifiedOutputString(FALSE, OutputType, 0, "%c", c);
	    --remaining;
	    continue;
	}

	/* Simple case 2: standard C escape */
	p = strchr(escapes, c);
	if (p && c) {
	    SpecifiedOutputString(FALSE,
				  OutputType,
				  0,
				  "%c",
				  letters[p - escapes]);
	    --remaining;
	    continue;
	}

	/* General octal escapes */
	/* If next char makes it ambiguous, force 3-char escape */
	if (len && isdigit(*str)) /* Force on 8 and 9, too! */
	    c += 256;
	if (c > 077) {
	    SpecifiedOutputString(FALSE,
				  OutputType,
				  0,
				  "%c",
				  '0' + (c>>6 & 3));

	    if (!--remaining)
		break;
	}
	if (c > 07) {	
	    SpecifiedOutputString(FALSE,
				  OutputType,
				  0,
				  "%c",
				  '0' + (c>>3 & 7));
	    if (!--remaining)
		break;
	}

	SpecifiedOutputString(FALSE, OutputType, 0, "%c", '0' + (c & 7));

	--remaining;
    }

    /* Closing quote (if string ended) */
    if (q2 && remaining) {
	SpecifiedOutputString(FALSE, OutputType, 0, "%c", q2);
	remaining--;
    }

    return maxlen - remaining;
}


/*
 * Print info about a key, in the format
 *
 *   1024 bits, Key ID FBBB8AB1, created 1984-12-25
 *
 * The ", created" part is omitted if the creation timestamp is 0.
 */
void
ringTtyPutKeyInfo(Boolean DisplayHeader,
		  PgpOutputType OutputType,
		  struct RingSet const *set,
		  union RingObject *obj)
{
	char buf[PGPDATESTRINGLEN+1];
	word32 tstamp;

	SpecifiedOutput(DisplayHeader,
			OutputType,
			0,
			"BITS_AND_KEYID",
			(unsigned)ringKeyBits(set, obj));

	ringTtyPutKeyID(FALSE,
			OutputType,
			set,
			obj);

	tstamp = ringKeyCreation(set, obj);
	if (tstamp) {
	    SpecifiedOutputString(FALSE,
				  OutputType,
				  0,
				  ", Created ");
		pgpDateString(tstamp, buf);
		SpecifiedOutputString(FALSE,
				      OutputType,
				      0,
				      buf);
	}

	SpecifiedOutputString(FALSE,
			      OutputType,
			      0,
			      "\n");
#if 0
	if (trust & PGP_KEYTRUSTF_REVOKED)
		fprintf(f, "%sThis key has been revoked by its owner\n",
		        prefix);
#endif
}


void ringKeyIDprint(Boolean DisplayHeaders,
		    PgpOutputType OutputType,
		    char const *prompt,
		    byte const keyID[8])
{
	char buf[18];
	char *p = buf;
	int i;

	for (i = 0; i < 4; i++) {
		*p++ = hexchar[keyID[i] >> 4];
		*p++ = hexchar[keyID[i] & 15];
	}
	*p++ = ' ';
	for (i = 4; i < 8; i++) {
		*p++ = hexchar[keyID[i] >> 4];
		*p++ = hexchar[keyID[i] & 15];
	}
	*p = '\n';

	SpecifiedOutputString(DisplayHeaders, OutputType, 0, prompt);
	SpecifiedOutputBuffer(FALSE, OutputType, 0, buf, sizeof(char), 18);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -