📄 pgpk.c
字号:
int needwritesec=0;
int newkeys = 0;
int err = 0;
mainOpenPubSec(env, &pub, &pubring, &sec, &secring, stderr);
if (!argc) {
#if 0
fprintf (stderr, "No input files -- reading from stdin\n");
/* BUG. This won't work, requires fseek/ftell */
keyfile = mainOpenKeyring (stdin, 0);
#else
fprintf (stderr, "No key file specified for addition\n");
goto cleanup;
#endif
} else while (argc--) {
struct RingSet *temp;
FILE *fp;
struct PgpFile *pfp;
struct RingFile *ring;
fprintf (stderr, "Opening ringfile \"%s\"...\n", argv[0]);
fp = fopen (argv[0], "rb");
pfp = pgpFileReadOpen (fp, NULL, NULL); /* chain errors */
/* We will never close this ringfile */
ring = ringFileOpen (ringpool, pfp, 0, &err); /* chain */
temp = ringSetCopy(ringFileSet(ring)); /* chain */
if (!temp) {
fprintf (stderr, "Unable to open file \"%s\"\n",
argv[0]);
} else {
fprintf (stderr,
"\nAdding keys:\n\n");
ringTtyKeyView((void *)ui_arg, NULL, temp, argv[0], 0);
newkeys++;
if (keyfile) {
struct RingSet *tring;
tring = ringSetUnion(keyfile, temp);
ringSetDestroy(keyfile);
ringSetDestroy(temp);
keyfile = tring;
} else
keyfile = temp;
}
fprintf (stderr, "\n");
argv++;
}
if (!newkeys) {
fprintf (stderr, "No keys to add\n");
goto cleanup;
}
/* Add keys in keyfile to copy of pubring/secring as appropriate */
newpub = ringSetCreate(ringpool);
newsec = ringSetCreate(ringpool);
if (!newpub || !newsec) {
err = PGPERR_NOMEM;
goto cleanup;
}
ringSetAddSet(newpub, pubring);
ringSetAddSet(newsec, secring);
ringSetDestroy(pubring);
ringSetDestroy(secring);
pubring = secring = NULL;
ringSetFreeze(keyfile);
iter = ringIterCreate(keyfile);
if (!iter) {
err = ringPoolError(ringpool)->error;
goto cleanup;
}
while (ringIterNextObject(iter, 1) > 0) {
union RingObject *obj = ringIterCurrentObject(iter, 1);
pgpAssert(obj);
pgpAssert (ringObjectType (obj) == RINGTYPE_KEY);
/* Treat secret keys differently from public */
if (ringKeyIsSec(keyfile, obj)) {
struct RingSet *tring;
struct RingSet *tring2;
union RingObject *secobj;
struct RingIterator *itersec;
int level;
/* Create tring holding just this key and children */
tring = ringSetCreate(ringpool);
tring2 = ringSetCreate(ringpool);
if (!tring || !tring2) {
err = ringPoolError(ringpool)->error;
ringSetDestroy(tring);
ringSetDestroy(tring2);
goto cleanup;
}
ringSetAddHierarchy(tring, keyfile, obj);
ringSetFreeze(tring);
/* Make tring2 which holds tring minus signatures */
ringSetAddSet(tring2, tring);
itersec = ringIterCreate(tring);
while ((level=ringIterNextObjectAnywhere(itersec))>0) {
union RingObject *iterobj;
iterobj = ringIterCurrentObject(itersec,level);
if (ringObjectType(iterobj) == RINGTYPE_SIG)
ringSetRemObject(tring2, iterobj);
}
/* Add set minus sigs to secret keyring */
ringSetAddSet(newsec, tring2);
/* Make another copy of tring, this one minus secret */
ringSetAddSet(tring2, tring);
ringIterRewind(itersec, 1);
ringIterNextObject(itersec, 1);
secobj = NULL;
while (ringIterNextObject(itersec, 2) > 0) {
secobj = ringIterCurrentObject(itersec, 2);
if (ringObjectType(secobj) == RINGTYPE_SEC)
break;
}
pgpAssert (secobj);
ringIterDestroy(itersec);
ringSetRemObject(tring2, secobj);
ringObjectRelease(secobj);
/* Add set without secret to pubring */
ringSetAddSet(newpub, tring2);
ringSetDestroy(tring2);
ringSetDestroy(tring);
needwritesec = 1;
} else {
/* Add to public keyring */
ringSetAddHierarchy(newpub, keyfile, obj);
}
}
ringIterDestroy(iter);
ringSetDestroy(keyfile);
keyfile = NULL;
ringSetFreeze(newpub);
ringSetFreeze(newsec);
if (!pgpenvGetInt (env, PGPENV_FORCE, NULL, NULL)) {
if (pgpenvGetInt (env, PGPENV_BATCHMODE, NULL, NULL)) {
fprintf (stderr,
"Use +force to add keys in batchmode\n\
Key addition cancelled.\n");
goto cleanup;
}
if (needwritesec)
fprintf (stderr,
"Do you want to add these keys to keyrings \"%s\" and\n"\
"\"%s\" (y/N)? ", pub, sec);
else
fprintf (stderr,
"Do you want to add these keys to keyring \"%s\" (y/N)? ", pub);
if (!pgpTtyGetBool(0, stderr)) {
fprintf (stderr, "Key addition cancelled.\n");
err = 0;
goto cleanup;
}
}
/* Do maintenance pass on new rings. */
reloadAllKeys (env, 0, 1); /* no untrusted keyrings */
tmpring = ringSetUnion(allkeys, newpub);
ringSetDestroy(allkeys);
allkeys = ringSetUnion(tmpring, newsec);
ringSetDestroy(tmpring);
err = mainDoMaint ((void *) ui_arg, allkeys, 1, newpub);
if (err < 0)
goto cleanup;
mainRingNewSet (pub, PGP_WRITETRUST_PUB, newpub);
newpub = 0; /* Don't destroy it */
if (needwritesec) {
mainRingNewSet (sec, PGP_WRITETRUST_SEC, newsec);
newsec = 0; /* Don't destroy it */
}
fprintf (stderr,
"Keys added successfully.\n");
err = 0;
cleanup:
if (pubring)
ringSetDestroy(pubring);
if (secring)
ringSetDestroy(secring);
if (newpub)
ringSetDestroy(newpub);
if (newsec)
ringSetDestroy(newsec);
if (keyfile)
ringSetDestroy(keyfile);
return err;
}
static int
doKeyExtract (struct PgpEnv *env, struct Flags *flags, int argc, char *argv[],
struct PgpTtyUI *ui_arg)
{
struct RingSet *pubring = NULL;
struct RingSet *keyfile = NULL;
char const *pub;
byte doarmor = flags->doarmor;
int err;
(void) ui_arg;
/* Check the command-line args for armor */
if (!doarmor && flags->argc && strchr (flags->args, 'a'))
doarmor++;
mainOpenPubSec(env, &pub, &pubring, NULL, NULL, stderr);
if (!pubring) {
fprintf (stderr, "No keys in pubring\n");
return 0;
}
err = selectKeyArgs (env, argc, argv, pub, pubring, &keyfile, 0);
if (err < 0)
return err;
if (err == 0) {
fprintf (stderr, "No keys were selected for extraction.\n");
return 0;
}
ringSetFreeze (keyfile);
ringSetDestroy(pubring);
if (flags->outfile &&
pgpTtyCheckOverwrite ((void *) ui_arg, flags->outfile))
return PGPERR_NO_FILE;
if (doarmor) {
FILE *fp = flags->outfile ? fopen(flags->outfile, "w") :
stdout;
if (!fp)
return PGPERR_NO_FILE;
err = mainWriteArmoredSet (fp, 0, keyfile, env);
} else if (flags->outfile) {
FILE *fp = fopen(flags->outfile, "wb");
if (!fp)
return PGPERR_NO_FILE;
err = mainWriteSet (fp, 0, keyfile);
} else {
err = mainWriteSet (stdout, 0, keyfile);
}
ringSetDestroy(keyfile);
return err;
}
static int
keygenProgress (void *arg, int c)
{
(void)arg; /* make the compiler happy */
putc (c, stderr);
fflush (stderr);
return 0;
}
/* Optional Arguments: name keybits */
static int
doKeyGenerate (struct PgpEnv *env, int argc, char *argv[], void *ui_arg)
{
struct RingSet *pubring = NULL, *secring = NULL;
struct RingSet *newpub = NULL, *newsec = NULL;
struct PgpKeySpec *keyspec = NULL;
struct PgpSecKey *seckey = NULL, *subseckey = NULL;
struct PgpPkAlg const *pkalg, *subkalg;
char const *pub = NULL, *sec = NULL; /* make the compiler happy */
char *name = NULL, namebuf[256];
size_t namelen = 0;
unsigned keybits = 0;
int keytype;
unsigned entropy;
int error = 0;
unsigned len;
char buf[20];
fprintf (stderr,
"Choose the type of your public key:\n"
" 1) DSS/Diffie-Hellman - New for PGP 5! "
"Separate signing and encryption keys\n"
" 2) RSA - Compatible with old versions of PGP\n"
" 3) RSA pair - Separate signing and encryption using RSA\n"
"Choose 1, 2, or 3: ");
len = pgpTtyGetString (buf, sizeof(buf), stderr);
if (!len) {
fprintf (stderr, "No key type was chosen\n");
error = -1;
goto cleanup;
}
keytype = atoi(buf);
switch (keytype) {
case 1:
pkalg = pgpPkalgByNumber(PGP_PKALG_DSA);
subkalg = pgpPkalgByNumber(PGP_PKALG_ELGAMAL);
break;
case 2:
pkalg = pgpPkalgByNumber(PGP_PKALG_RSA);
subkalg = 0;
break;
case 3:
pkalg = pgpPkalgByNumber(PGP_PKALG_RSA);
subkalg = pgpPkalgByNumber(PGP_PKALG_RSA);
break;
default:
/* Allow unforeseen key types */
pkalg = pgpPkalgByNumber(keytype);
subkalg = 0;
break;
}
if (!pkalg) {
fprintf (stderr, "No legal key type was chosen\n");
error = -1;
goto cleanup;
}
/* Need to get userid, keysizes, etc. */
if (argc) {
name = argv[0];
namelen = strlen (name);
argv++;
argc--;
}
if (argc) {
keybits = atoi (argv[0]);
argv++;
argc--;
}
if (!keybits) {
fputs (
"\nPick your public/private keypair key size:\n\
\n***** TEMPORARY LABELS, TO BE DETERMINED LATER!! *****\n\n\
1) 768 bits- Commercial grade, probably not currently breakable\n\
2) 1024 bits- High commercial grade, secure for many years\n\
3) 2048 bits- \"Military\" grade, secure for the forseeable future\n\
4) 3072 bits- Archival grade, slow, highest security\n\
Choose 1, 2, 3, or 4, or enter desired number of bits: ", stderr);
fflush (stderr);
len = pgpTtyGetString (buf, sizeof(buf), stderr);
if (!len) {
fprintf (stderr, "Keygen error\n");
error = -1;
goto cleanup;
}
keybits = atoi (buf);
switch (keybits) {
case 1: keybits = 768; break;
case 2: keybits = 1024; break;
case 3: keybits = 2048; break;
case 4: keybits = 3072; break;
default:
if (keybits < 512) {
fprintf (stderr,
"Minimum key size is 512 bits\n");
error = -1;
goto cleanup;
}
if (keybits > 4096) {
fprintf (stderr,
"Maximum key size is 4096 bits\n");
error = -1;
goto cleanup;
}
break;
}
}
if (!name) {
name = namebuf;
fputs (
"\nYou need a user ID for your public key. The desired form for this\n\
user ID is your name, followed by your E-mail address enclosed in\n\
<angle brackets>, if you have an E-mail address.\n\
For example: John Q. Smith <12345.6789@compuserve.com>\n\
Enter a user ID for your public key: ", stderr);
fflush (stderr);
namelen = pgpTtyGetString (namebuf, sizeof (namebuf), stderr);
}
if (!namelen) {
fprintf (stderr, "Keygen error\n");
error = -1;
goto cleanup;
}
/* Open the existing keyrings */
mainOpenPubSec(env, &pub, &pubring, &sec, &secring, stderr);
/* Copy pubring and secring */
newpub = ringSetCreate (ringpool);
ringSetAddSet (newpub, pubring);
ringSetDestroy(pubring);
newsec = ringSetCreate (ringpool);
ringSetAddSet (newsec, secring);
ringSetDestroy(secring);
if (!newpub || !newsec) {
error = PGPERR_NOMEM;
goto cleanup;
}
/* Generate Randomness */
if (!rng)
rng = pgpRandomCreate();
/* Need to ask for randomness */
entropy = pgpSecKeyEntropy (pkalg, keybits, FALSE);
if (subkalg)
entropy += pgpSecKeyEntropy (subkalg, keybits, FALSE);
pgpTtyRandAccum (ui_arg, entropy);
/* Generate the SecKey */
seckey = pgpSecKeyGenerate (pkalg, keybits, FALSE, rng, keygenProgress,
NULL, &error);
pgpRandomStir (rng);
if (!seckey && !error)
error = PGPERR_NOMEM;
if (error)
goto cleanup;
/* Need to lock the SecKey */
fprintf(stderr, "\n\
You need a pass phrase to protect your %s private key.\n\
Your pass phrase can be any sentence or phrase and may have many\n\
words, spaces, punctuation, or any other printable characters.\n",
(subkalg ? "signature" : "RSA"));
error = setPassword (env, seckey, ui_arg);
if (error)
goto cleanup;
/* Generate the keyring objects */
keyspec = pgpKeySpecCreate (env);
if (!keyspec) {
error = PGPERR_NOMEM;
goto cleanup;
}
error = ringCreateKeypair (env, seckey, keyspec, name, namelen, rng,
newpub, newsec);
if (error)
goto cleanup;
/* Make subkey if requested */
if (subkalg) {
/* Generate the subseckey */
subseckey = pgpSecKeyGenerate (subkalg, keybits, FALSE, rng,
keygenProgress, NULL, &error);
pgpRandomStir (rng);
if (!subseckey && !error)
error = PGPERR_NOMEM;
if (error)
goto cleanup;
/* Need to lock the encryption SubSecKey */
fprintf(stderr, "\n\
You also need a pass phrase to protect your encryption private key.\n\
Your pass phrase can be any sentence or phrase and may have many\n\
words, spaces, punctuation, or any other printable characters.\n");
error = setPassword (env, subseckey, ui_arg);
if (error)
goto cleanup;
error = ringCreateSubkeypair (env, seckey, subseckey, keyspec,
rng, newpub, newsec);
if (error)
goto cleanup;
}
/* Freeze the sets */
ringSetFreeze (newpub);
ringSetFreeze (newsec);
/* Write out newpub and newsec */
mainRingNewSet (sec, PGP_WRITETRUST_SEC, newsec);
mainRingNewSet (pub, PGP_WRITETRUST_PUB, newpub);
newsec = newpub = 0; /* Don't destroy these */
cleanup:
if (newpub)
ringSetDestroy (newpub);
if (newsec)
ringSetDestroy (newsec);
if (seckey)
pgpSecKeyDestroy (seckey);
if (subseckey)
pgpSecKeyDestroy (subseckey);
if (keyspec)
pgpKeySpecDestroy (keyspec);
putc ('\n', stderr);
if (!error)
fprintf (stderr,
"Keypair created successfully.\n\
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -