mirror of
https://codeberg.org/scip/pcp.git
synced 2025-12-17 03:50:57 +01:00
bugfix in encryption key computing, added new feature: derived public keys
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
31
src/pcp.c
31
src/pcp.c
@@ -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 {
|
||||
|
||||
@@ -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" \
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user