📄 pgpringui.c
字号:
/*
* 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 + -