added PBP public key import/export compatibility mode (-b --pbpcompat)

This commit is contained in:
git@daemon.de
2014-01-28 16:53:26 +01:00
parent fa9d8ed800
commit 3f1bfef581
12 changed files with 248 additions and 82 deletions

View File

@@ -48,6 +48,10 @@
compile time with ./configure --enable-cbc. CBC mode
in PCP uses a blocksize of 1k.
Added PBP public key import and export compatibility
(untested against pbp yet), use -b when exporting a
public key, or when importing one.
0.1.5 Fixed a segmentation fault when using pcp1 -t on a
public key. I added a double free() there by purpose
to test segfault catching I added in unittest.pl

View File

@@ -123,6 +123,7 @@ pcp_key_t *pcpkey_encrypt(pcp_key_t *key, char *passphrase);
pcp_key_t *pcpkey_decrypt(pcp_key_t *key, char *passphrase);
pcp_pubkey_t *pcpkey_pub_from_secret(pcp_key_t *key);
char *pcp_getkeyid(pcp_key_t *k);
char *pcp_getpubkeyid(pcp_pubkey_t *k);
unsigned char *pcppubkey_getchecksum(pcp_pubkey_t *k);
unsigned char *pcpkey_getchecksum(pcp_key_t *k);
void pcp_inithashes();

View File

@@ -93,6 +93,16 @@ char *pcp_getkeyid(pcp_key_t *k) {
return id;
}
// same as above but for imported pbp keys
char *pcp_getpubkeyid(pcp_pubkey_t *k) {
uint32_t s, p;
p = jen_hash(k->pub, 32, JEN_PSALT);
s = jen_hash(k->edpub, 32, JEN_SSALT);
char *id = ucmalloc(17);
snprintf(id, 17, "%08X%08X", p, s);
return id;
}
void pcp_keypairs(byte *csk, byte *cpk, byte *esk, byte *epk) {
// generate ed25519 + curve25519 keypair from random seed
byte *seed = urmalloc(32);

View File

@@ -192,6 +192,9 @@ Pretty Curved Privacy \- File encryption using eliptic curve cryptography.
\& \-y \-\-export\-yaml Export all keys stored in your vault
\& as YAML formatted text. Use \-O to put
\& the export into a file.
\& \-b \-\-pbpcompat Enable PBP compatibility for public key
\& exports and imports.
\&
\& Encryption Options:
\& \-e \-\-encrypt Asym\-Encrypt a message. Read from stdin or
\& specified via \-I. Output will be written

View File

@@ -64,6 +64,9 @@ Pretty Curved Privacy - File encryption using eliptic curve cryptography.
-y --export-yaml Export all keys stored in your vault
as YAML formatted text. Use -O to put
the export into a file.
-b --pbpcompat Enable PBP compatibility for public key
exports and imports.
Encryption Options:
-e --encrypt Asym-Encrypt a message. Read from stdin or
specified via -I. Output will be written

View File

@@ -259,7 +259,7 @@ void pcp_exportsecretkey(pcp_key_t *key, char *outfile) {
keyid we use the primary key. if no keyid has been given but
a recipient instead, we try to look up the vault for a match.
*/
void pcp_exportpublic(char *keyid, char *recipient, char *passwd, char *outfile) {
void pcp_exportpublic(char *keyid, char *recipient, char *passwd, char *outfile, int pbpcompat) {
pcp_pubkey_t *key = NULL;
if(keyid != NULL) {
@@ -307,7 +307,10 @@ void pcp_exportpublic(char *keyid, char *recipient, char *passwd, char *outfile)
// scip
//printf("EXPORT:\n");
//pcpprint_bin(stdout, key, PCP_RAW_PUBKEYSIZE); printf("\n");
pcppubkey_print(key, out);
pcppubkey_print(key, out, pbpcompat);
if(pbpcompat)
fprintf(stderr, "public key exported in PBP format.\n");
else
fprintf(stderr, "public key exported.\n");
}
@@ -370,7 +373,70 @@ int pcp_importsecret (vault_t *vault, FILE *in) {
}
int pcp_importpublic (vault_t *vault, FILE *in) {
int pcp_importpublic (vault_t *vault, FILE *in, int pbpcompat) {
pcp_pubkey_t *pub = NULL;
if(pbpcompat == 1) {
size_t bufsize = 1024;
unsigned char in_buf[bufsize];
pub = ucmalloc(sizeof(pcp_pubkey_t));
char *date = ucmalloc(19);
char *tmp = ucmalloc(1024);
bufsize = fread(&in_buf, 1, crypto_sign_BYTES, in);
fread(&in_buf, 1, crypto_box_PUBLICKEYBYTES, in); // ignored currently
fread(pub->edpub, 1, crypto_sign_PUBLICKEYBYTES, in);
fread(pub->pub, 1, crypto_box_PUBLICKEYBYTES, in);
fread(date, 1, 19, in);
date[19] = '\0';
fread(&in_buf, 1, 44, in); // ignore validity date
bufsize = fread(tmp, 1, 1024, in);
tmp[bufsize] = '\0';
struct tm c;
if(strptime(date, "%Y-%m-%dT%H:%M:%S", &c) == NULL) {
fatal("Failed to parse creation time in PBP public key file (<%s>)\n", date);
goto errimp1;
}
char *parts = strtok (tmp, "|");
int pnum = 0;
while (parts != NULL) {
if(pnum == 0)
memcpy(pub->owner, parts, strlen(parts));
else if (pnum == 1)
memcpy(pub->mail, parts, strlen(parts));
parts = strtok(NULL, "|");
pnum++;
}
free(parts);
if(sscanf(tmp, "%s|%s", pub->owner, pub->mail) == 0) {
if(sscanf(tmp, "%s", pub->owner) == 0) {
fatal("Failed to parse owner in PBP public key file\n");
goto errimp1;
}
}
pub->ctime = (long)mktime(&c);
pub->type = PCP_KEY_TYPE_PUBLIC;
pub->version = PCP_KEY_VERSION;
pub->serial = arc4random();
memcpy(pub->id, pcp_getpubkeyid(pub), 17);
free(date);
free(tmp);
goto kimp;
errimp1:
free(date);
free(tmp);
free(pub);
return 1;
}
else {
size_t clen;
char *z85 = pcp_readz85file(in);
@@ -392,9 +458,12 @@ int pcp_importpublic (vault_t *vault, FILE *in) {
}
// all good now
pcp_pubkey_t *pub = ucmalloc(sizeof(pcp_pubkey_t));
pub = ucmalloc(sizeof(pcp_pubkey_t));
memcpy(pub, z85decoded, PCP_RAW_PUBKEYSIZE);
pubkey2native(pub);
}
kimp:
if(debug)
pcp_dumppubkey(pub);

View File

@@ -49,10 +49,10 @@ void pcp_listkeys();
void pcp_exportsecret(char *keyid, int useid, char *outfile);
void pcp_exportsecretkey(pcp_key_t *key, 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);
void pcp_exportpublic(char *keyid, char *recipient, char *passwd, char *outfile, int pbpcompat);
char *pcp_normalize_id(char *keyid);
pcp_key_t *pcp_find_primary_secret();
int pcp_importpublic (vault_t *vault, FILE *in);
int pcp_importpublic (vault_t *vault, FILE *in, int pbpcompat);
int pcp_importsecret (vault_t *vault, FILE *in);
void pcpdelete_key(char *keyid);
char *pcp_find_id_byrec(char *recipient);

View File

@@ -91,7 +91,7 @@ int pcptext_infile(char *infile) {
pubkey2native(key);
if(pcp_sanitycheck_pub(key) == 0) {
fprintf(stdout, "%s is a public key file:\n", infile);
pcppubkey_print(key, stdout);
pcppubkey_print(key, stdout, 0);
free(key);
goto tdone;
}
@@ -127,7 +127,7 @@ void pcptext_key(char *keyid) {
if(p != NULL) {
if(debug)
pcp_dumppubkey(p);
pcppubkey_print(p, stdout);
pcppubkey_print(p, stdout, 0);
}
else {
fatal("No key with id 0x%s found!\n", keyid);
@@ -214,7 +214,73 @@ void pcpkey_print(pcp_key_t *key, FILE* out) {
free(z85encoded);
}
void pcppubkey_print(pcp_pubkey_t *key, FILE* out) {
void pcppubkey_print(pcp_pubkey_t *key, FILE* out, int pbpcompat) {
struct tm *c;
time_t t = (time_t)key->ctime;
c = localtime(&t);
if(pbpcompat == 1) {
// sign(mk, master public | cipher public | sign public | created[32] | valid[32] | name... )
// dates='{:<32}{:<32}'.format(self.created.isoformat(), self.valid.isoformat())
// fd.write(nacl.crypto_sign(self.mp+self.sp+self.cp+dates+self.name, self.ms))
// >>> dates='{:<32}{:<32}'.format(c.isoformat(), c.isoformat())
// >>> dates
// '2014-01-28T13:30:32.674394 2014-01-28T13:30:32.674394 '
size_t namelen = strlen(key->owner) + 3 + strlen(key->mail);
size_t rawsize = (crypto_box_PUBLICKEYBYTES * 2) + crypto_sign_PUBLICKEYBYTES +\
64 + namelen;
size_t pos = 0;
unsigned char *raw = ucmalloc(rawsize);
char *dates = ucmalloc(65);
char *name = ucmalloc(strlen(key->owner) + 3 + strlen(key->mail));
memcpy(raw, key->pub, crypto_box_PUBLICKEYBYTES);
pos += crypto_box_PUBLICKEYBYTES;
memcpy(&raw[pos], key->edpub, crypto_sign_PUBLICKEYBYTES);
pos += crypto_sign_PUBLICKEYBYTES;
memcpy(&raw[pos], key->pub, crypto_box_PUBLICKEYBYTES);
pos += crypto_box_PUBLICKEYBYTES;
struct tm *v;
time_t vt = t + 31536000;
v = localtime(&vt);
sprintf(dates, "%04d-%02d-%02dT%02d:%02d:%02d %04d-%02d-%02dT%02d:%02d:%02d ",
c->tm_year+1900-1, c->tm_mon+1, c->tm_mday, // wtf? why -1?
c->tm_hour, c->tm_min, c->tm_sec,
v->tm_year+1900-1, v->tm_mon+1, v->tm_mday,
v->tm_hour, v->tm_min, v->tm_sec);
sprintf(name, "%s|%s", key->owner, key->mail);
memcpy(&raw[pos], dates, 64);
pos += 64;
memcpy(&raw[pos], name, namelen);
pcp_key_t *secret = NULL;
secret = pcp_find_primary_secret();
if(secret == NULL) {
fatal("Could not find a secret key in vault %s!\n", vault->filename);
}
else {
char *passphrase;
pcp_readpass(&passphrase,
"Enter passphrase to decrypt your secret key for signing the export", NULL, 1);
secret = pcpkey_decrypt(secret, passphrase);
if(secret != NULL) {
size_t siglen = rawsize + crypto_sign_BYTES;
unsigned char *sig = pcp_ed_sign(raw, rawsize, secret);
if(sig != NULL)
fwrite(sig, 1, siglen, out);
}
}
}
else {
size_t zlen;
//printf("version: %08x\n", key->version);
@@ -228,9 +294,7 @@ void pcppubkey_print(pcp_pubkey_t *key, FILE* out) {
free(blob);
struct tm *c;
time_t t = (time_t)key->ctime;
c = localtime(&t);
fprintf(out, "%s\n", PCP_PUBKEY_HEADER);
@@ -282,6 +346,7 @@ void pcppubkey_print(pcp_pubkey_t *key, FILE* out) {
free(hash);
free(r);
free(z85encoded);
}
}

View File

@@ -34,7 +34,7 @@ void pcp_dumpkey(pcp_key_t *k);
void pcp_dumppubkey(pcp_pubkey_t *k);
void pcpkey_print(pcp_key_t *key, FILE *out);
void pcppubkey_print(pcp_pubkey_t *key, FILE *out);
void pcppubkey_print(pcp_pubkey_t *key, FILE *out, int pbpcompat);
void pcpkey_printshortinfo(pcp_key_t *key);
void pcppubkey_printshortinfo(pcp_pubkey_t *key);

View File

@@ -46,7 +46,7 @@ char *default_vault() {
}
int main (int argc, char **argv) {
int opt, mode, usevault, useid, userec, lo, armor, detach, signcrypt;
int opt, mode, usevault, useid, userec, lo, armor, detach, signcrypt, pbpcompat;
char *vaultfile = default_vault();
char *outfile = NULL;
char *infile = NULL;
@@ -68,6 +68,7 @@ int main (int argc, char **argv) {
armor = 0;
detach = 0;
signcrypt = 0;
pbpcompat = 0;
static struct option longopts[] = {
// generics
@@ -89,6 +90,7 @@ int main (int argc, char **argv) {
{ "remove-key", no_argument, NULL, 'R' },
{ "edit-key", no_argument, NULL, 'E' },
{ "export-yaml", no_argument, NULL, 'y' },
{ "pbpcompat", no_argument, NULL, 'b' },
// crypto
{ "encrypt", no_argument, NULL, 'e' },
@@ -111,7 +113,7 @@ int main (int argc, char **argv) {
{ NULL, 0, NULL, 0 }
};
while ((opt = getopt_long(argc, argv, "klV:vdehsO:i:I:pSPRtEx:DzZr:gcymf:",
while ((opt = getopt_long(argc, argv, "klV:vdehsO:i:I:pSPRtEx:DzZr:gcymf:b",
longopts, NULL)) != -1) {
switch (opt) {
@@ -177,6 +179,9 @@ int main (int argc, char **argv) {
case 'Z':
armor = 1;
break;
case 'b':
pbpcompat = 1;
break;
case 'g':
mode += PCP_MODE_SIGN;
usevault = 1;
@@ -293,9 +298,9 @@ int main (int argc, char **argv) {
break;
}
if (recipient != NULL)
pcp_exportpublic(id, recipient->value, xpass, outfile);
pcp_exportpublic(id, recipient->value, xpass, outfile, pbpcompat);
else
pcp_exportpublic(id, NULL, xpass, outfile);
pcp_exportpublic(id, NULL, xpass, outfile, pbpcompat);
if(xpass != NULL)
free(xpass);
if(recipient != NULL)
@@ -312,7 +317,7 @@ int main (int argc, char **argv) {
break;
}
}
pcp_importpublic(vault, in);
pcp_importpublic(vault, in, pbpcompat);
break;
case PCP_MODE_IMPORT_SECRET:

View File

@@ -59,6 +59,9 @@
"-y --export-yaml Export all keys stored in your vault\n" \
" as YAML formatted text. Use -O to put\n" \
" the export into a file.\n" \
"-b --pbpcompat Enable PBP compatibility for public key\n" \
" exports and imports.\n" \
"\n" \
"Encryption Options:\n" \
"-e --encrypt Asym-Encrypt a message. Read from stdin or\n" \
" specified via -I. Output will be written\n" \

View File

@@ -57,6 +57,9 @@ Keymanagement Options:
-y --export-yaml Export all keys stored in your vault
as YAML formatted text. Use -O to put
the export into a file.
-b --pbpcompat Enable PBP compatibility for public key
exports and imports.
Encryption Options:
-e --encrypt Asym-Encrypt a message. Read from stdin or
specified via -I. Output will be written