bugfix in encryption key computing, added new feature: derived public keys

This commit is contained in:
TLINDEN
2013-11-02 11:02:36 +01:00
parent c93f9c6cdd
commit bf5556e1ec
29 changed files with 514 additions and 242 deletions

View File

@@ -67,14 +67,22 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd) {
if(combined == NULL)
goto errde1;
char *senderid = ucmalloc(17);
memcpy(senderid, combined, 16);
senderid[16] = '\0';
unsigned char *hash = ucmalloc(crypto_hash_BYTES);
unsigned char *check = ucmalloc(crypto_hash_BYTES);
memcpy(hash, combined, crypto_hash_BYTES);
HASH_FIND_STR(pcppubkey_hash, senderid, public);
for(public=pcppubkey_hash;
public != NULL;
public=(pcp_pubkey_t*)(public->hh.next)) {
crypto_hash(check, (unsigned char*)public->id, 16);
if(memcmp(check, hash, crypto_hash_BYTES) == 0) {
// found one
break;
}
}
if(public == NULL) {
fatal("Could not find a public key with id 0x%s in vault %s!\n",
senderid, vault->filename);
fatal("Could not find a usable public key in vault %s!\n",
vault->filename);
goto errde0;
}
@@ -85,29 +93,52 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd) {
pcppubkey_printshortinfo(public);
}
unsigned char *encrypted = ucmalloc(clen - 16);
memcpy(encrypted, &combined[16], clen - 16);
unsigned char *encrypted = ucmalloc(clen - crypto_hash_BYTES);
memcpy(encrypted, &combined[crypto_hash_BYTES], clen - crypto_hash_BYTES);
size_t dlen;
unsigned char *decrypted = pcp_box_decrypt(secret, public,
encrypted, clen - 16, &dlen);
encrypted,
clen - crypto_hash_BYTES, &dlen);
if(decrypted == NULL) {
// try it with a derived secret from the sender id
pcp_key_t *s = pcp_derive_pcpkey(secret, public->id);
decrypted = pcp_box_decrypt(s, public,
encrypted,
clen - crypto_hash_BYTES, &dlen);
if(decrypted == NULL) {
// now try the senders key mail address
s = pcp_derive_pcpkey(secret, public->mail);
decrypted = pcp_box_decrypt(s, public,
encrypted,
clen - crypto_hash_BYTES, &dlen);
if(decrypted == NULL) {
// try the name
s = pcp_derive_pcpkey(secret, public->owner);
decrypted = pcp_box_decrypt(s, public,
encrypted,
clen - crypto_hash_BYTES, &dlen);
}
}
}
if(decrypted != NULL) {
fatals_reset();
fwrite(decrypted, dlen, 1, out);
fclose(out);
if(ferror(out) != 0) {
fatal("Failed to write decrypted output!\n");
}
free(decrypted);
}
fprintf(stderr, "Decrypted %d bytes from 0x%s successfully\n",
(int)dlen, senderid);
fprintf(stderr, "Decrypted %d bytes from 0x%s successfully\n",
(int)dlen, public->id);
}
free(encrypted);
errde0:
free(senderid);
free(combined);
errde1:
@@ -121,7 +152,7 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd) {
int pcpencrypt(char *id, char *infile, char *outfile, char *passwd) {
int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, char *recipient) {
FILE *in = NULL;
FILE *out = NULL;
pcp_pubkey_t *public = NULL;
@@ -175,6 +206,12 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd) {
goto erren2;
}
if(recipient != NULL) {
pcp_key_t *derived = pcp_derive_pcpkey(secret, recipient);
memcpy(secret, derived, sizeof(pcp_key_t));
free(derived);
}
if(debug) {
fprintf(stderr, "Using secret key:\n");
pcpkey_printshortinfo(secret);
@@ -208,10 +245,12 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd) {
goto erren1;
size_t zlen;
size_t clen = ciphersize + 16;
size_t clen = ciphersize + crypto_hash_BYTES;
unsigned char *combined = ucmalloc(clen);
memcpy(combined, secret->id, 16);
memcpy(&combined[16], cipher, clen - 16);
unsigned char *hash = ucmalloc(crypto_hash_BYTES);
crypto_hash(hash, (unsigned char*)secret->id, 16);
memcpy(combined, hash, crypto_hash_BYTES);
memcpy(&combined[crypto_hash_BYTES], cipher, clen - crypto_hash_BYTES);
// combined consists of:
// keyid|nonce|cipher

View File

@@ -13,6 +13,6 @@
#include "keyprint.h"
int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd);
int pcpencrypt(char *id, char *infile, char *outfile, char *passwd);
int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, char *recipient);
#endif // _HAVE_ENCRYPTION_H

View File

@@ -1,14 +1,13 @@
#include "keymgmt.h"
char *pcp_getstdin(const char *prompt) {
char line[1024];
char line[255];
char *out;
fprintf(stderr, "%s: ", prompt);
if (fgets(line, 1024, stdin) == NULL) {
if (fgets(line, 255, stdin) == NULL) {
fatal("Cannot read from stdin");
goto errgst;
}
@@ -26,7 +25,6 @@ char *pcp_getstdin(const char *prompt) {
return NULL;
}
int pcp_storekey (pcp_key_t *key) {
if(vault->isnew == 1 || HASH_COUNT(pcpkey_hash) == 0) {
key->type = PCP_KEY_TYPE_MAINSECRET;
@@ -207,10 +205,46 @@ void pcp_exportsecret(char *keyid, int useid, char *outfile) {
}
void pcp_exportpublic(char *keyid, int useid, char *outfile) {
pcp_pubkey_t *key = NULL;
pcp_key_t *pcp_getrsk(pcp_key_t *s, char *recipient, char *passwd) {
if(recipient != NULL) {
if(s->secret[0] == 0) {
// encrypted, decrypt it
char *passphrase;
if(passwd == NULL) {
pcp_readpass(&passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1);
}
else {
passphrase = ucmalloc(strlen(passwd)+1);
strncpy(passphrase, passwd, strlen(passwd)+1);
}
s = pcpkey_decrypt(s, passphrase);
if(s == NULL)
goto errrsk1;
}
pcp_key_t *tmp;
tmp = pcp_derive_pcpkey(s, recipient);
return tmp;
}
if(useid == 1) {
return s;
errrsk1:
return NULL;
}
/*
if id given, look if it is already a public and export this,
else we look for a secret key with that id. without a given
keyid we use the primary key. if we start with a secret key
and a recipient have been given, we use a derived secret key
and export the public component from that. without recipient
just export the public component of the found secret key.
*/
void pcp_exportpublic(char *keyid, char *recipient, char *passwd, char *outfile) {
pcp_pubkey_t *key = NULL;
if(keyid != NULL) {
// look if we've got that one
HASH_FIND_STR(pcppubkey_hash, keyid, key);
if(key == NULL) {
@@ -222,7 +256,9 @@ void pcp_exportpublic(char *keyid, int useid, char *outfile) {
free(s);
}
else {
key = pcpkey_pub_from_secret(s);
s = pcp_getrsk(s, recipient, passwd);
if(s != NULL)
key = pcpkey_pub_from_secret(s);
}
}
}
@@ -235,7 +271,10 @@ void pcp_exportpublic(char *keyid, int useid, char *outfile) {
free(s);
}
else {
key = pcpkey_pub_from_secret(s);
pcp_key_t *t = NULL;
t = pcp_getrsk(s, recipient, passwd);
if(t != NULL)
key = pcpkey_pub_from_secret(t);
}
}

View File

@@ -22,7 +22,8 @@ int pcp_storekey (pcp_key_t *key);
void pcp_keygen();
void pcp_listkeys();
void pcp_exportsecret(char *keyid, int useid, char *outfile);
void pcp_exportpublic(char *keyid, int useid, char *outfile);
pcp_key_t *pcp_getrsk(pcp_key_t *s, char *recipient, char *passwd);
void pcp_exportpublic(char *keyid, char *recipient, char *passwd, char *outfile);
char *pcp_normalize_id(char *keyid);
pcp_key_t *pcp_find_primary_secret();
int pcp_importpublic (vault_t *vault, FILE *in);

View File

@@ -22,13 +22,14 @@ char *default_vault() {
}
int main (int argc, char **argv) {
int opt, mode, usevault, useid;
int opt, mode, usevault, useid, userec;
char *vaultfile = default_vault();
char *outfile = NULL;
char *infile = NULL;
char *keyid = NULL;
char *id = NULL;
char *xpass = NULL;
char *recipient = NULL;
FILE *in;
PCP_EXIT = 0;
@@ -37,6 +38,7 @@ int main (int argc, char **argv) {
mode = 0;
usevault = 0;
useid = 0;
userec = 0;
static struct option longopts[] = {
// generics
@@ -46,6 +48,7 @@ int main (int argc, char **argv) {
{ "keyid", required_argument, NULL, 'i' },
{ "text", required_argument, NULL, 't' },
{ "xpass", required_argument, NULL, 'x' },
{ "recipient", required_argument, NULL, 'R' },
// key management
{ "keygen", no_argument, NULL, 'k' },
@@ -72,7 +75,7 @@ int main (int argc, char **argv) {
{ NULL, 0, NULL, 0 }
};
while ((opt = getopt_long(argc, argv, "klV:vdehsO:i:I:pSPrtEx:DzZ",
while ((opt = getopt_long(argc, argv, "klV:vdehsO:i:I:pSPrtEx:DzZR:",
longopts, NULL)) != -1) {
switch (opt) {
@@ -150,7 +153,11 @@ int main (int argc, char **argv) {
xpass = ucmalloc(strlen(optarg)+1);
strncpy(xpass, optarg, strlen(optarg)+1);
break;
case 'R':
recipient = ucmalloc(strlen(optarg)+1);
strncpy(recipient, optarg, strlen(optarg)+1);
userec = 1;
break;
case 'D':
debug = 1;
@@ -204,14 +211,14 @@ int main (int argc, char **argv) {
case PCP_MODE_EXPORT_PUBLIC:
if(useid) {
id = pcp_normalize_id(keyid);
if(id != NULL) {
pcp_exportpublic(id, useid, outfile);
free(id);
}
}
else {
pcp_exportpublic(NULL, useid, outfile);
if(id == NULL)
break;
}
pcp_exportpublic(id, recipient, xpass, outfile);
if(xpass != NULL)
free(xpass);
if(recipient != NULL)
free(recipient);
break;
case PCP_MODE_IMPORT_PUBLIC:
@@ -283,10 +290,12 @@ int main (int argc, char **argv) {
if(useid) {
id = pcp_normalize_id(keyid);
if(id != NULL) {
pcpencrypt(id, infile, outfile, xpass);
pcpencrypt(id, infile, outfile, xpass, recipient);
free(id);
if(xpass != NULL)
free(xpass);
if(recipient != NULL)
free(recipient);
}
}
else {

View File

@@ -11,6 +11,8 @@
"-I --infile <file> Input file. If not specified, stdin\n" \
" will be used.\n" \
"-i --keyid <id> Specify a key id to import/export.\n" \
"-R --recipient <string> Specify a recpipient, used for public\n" \
" key export and encryption.\n" \
"-t --text Print textual representation of some\n" \
" item. Either -V or -i must be specified\n" \
" as well.\n" \

View File

@@ -9,6 +9,8 @@ General Options:
-I --infile <file> Input file. If not specified, stdin
will be used.
-i --keyid <id> Specify a key id to import/export.
-R --recipient <string> Specify a recpipient, used for public
key export and encryption.
-t --text Print textual representation of some
item. Either -V or -i must be specified
as well.