mirror of
https://codeberg.org/scip/pcp.git
synced 2025-12-17 12:00:56 +01:00
added PBP public key import/export compatibility mode (-b --pbpcompat)
This commit is contained in:
109
src/keymgmt.c
109
src/keymgmt.c
@@ -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,8 +307,11 @@ 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);
|
||||
fprintf(stderr, "public key exported.\n");
|
||||
pcppubkey_print(key, out, pbpcompat);
|
||||
if(pbpcompat)
|
||||
fprintf(stderr, "public key exported in PBP format.\n");
|
||||
else
|
||||
fprintf(stderr, "public key exported.\n");
|
||||
}
|
||||
|
||||
free(key);
|
||||
@@ -370,31 +373,97 @@ int pcp_importsecret (vault_t *vault, FILE *in) {
|
||||
}
|
||||
|
||||
|
||||
int pcp_importpublic (vault_t *vault, FILE *in) {
|
||||
size_t clen;
|
||||
char *z85 = pcp_readz85file(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);
|
||||
|
||||
if(z85 == NULL)
|
||||
return 1;
|
||||
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);
|
||||
|
||||
unsigned char *z85decoded = pcp_z85_decode((char *)z85, &clen);
|
||||
free(z85);
|
||||
fread(date, 1, 19, in);
|
||||
date[19] = '\0';
|
||||
fread(&in_buf, 1, 44, in); // ignore validity date
|
||||
|
||||
if(z85decoded == NULL) {
|
||||
fatal("Error: could not decode input - it's probably not Z85 (got %d bytes)\n", clen);
|
||||
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);
|
||||
|
||||
if(clen != PCP_RAW_PUBKEYSIZE) {
|
||||
fatal("Error: decoded input didn't result to a proper sized key (got %d, expected %d)!\n", clen, PCP_RAW_PUBKEYSIZE);
|
||||
free(z85decoded);
|
||||
return 1;
|
||||
if(z85 == NULL)
|
||||
return 1;
|
||||
|
||||
unsigned char *z85decoded = pcp_z85_decode((char *)z85, &clen);
|
||||
free(z85);
|
||||
|
||||
if(z85decoded == NULL) {
|
||||
fatal("Error: could not decode input - it's probably not Z85 (got %d bytes)\n", clen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(clen != PCP_RAW_PUBKEYSIZE) {
|
||||
fatal("Error: decoded input didn't result to a proper sized key (got %d, expected %d)!\n", clen, PCP_RAW_PUBKEYSIZE);
|
||||
free(z85decoded);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// all good now
|
||||
pub = ucmalloc(sizeof(pcp_pubkey_t));
|
||||
memcpy(pub, z85decoded, PCP_RAW_PUBKEYSIZE);
|
||||
pubkey2native(pub);
|
||||
}
|
||||
|
||||
// all good now
|
||||
pcp_pubkey_t *pub = ucmalloc(sizeof(pcp_pubkey_t));
|
||||
memcpy(pub, z85decoded, PCP_RAW_PUBKEYSIZE);
|
||||
pubkey2native(pub);
|
||||
kimp:
|
||||
|
||||
if(debug)
|
||||
pcp_dumppubkey(pub);
|
||||
|
||||
@@ -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);
|
||||
|
||||
173
src/keyprint.c
173
src/keyprint.c
@@ -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,74 +214,139 @@ void pcpkey_print(pcp_key_t *key, FILE* out) {
|
||||
free(z85encoded);
|
||||
}
|
||||
|
||||
void pcppubkey_print(pcp_pubkey_t *key, FILE* out) {
|
||||
size_t zlen;
|
||||
|
||||
//printf("version: %08x\n", key->version);
|
||||
|
||||
pubkey2be(key);
|
||||
|
||||
void *blob = ucmalloc(PCP_RAW_PUBKEYSIZE);
|
||||
pcp_pubkeyblob(blob, key);
|
||||
char *z85encoded = pcp_z85_encode((unsigned char*)blob, PCP_RAW_PUBKEYSIZE, &zlen);
|
||||
pubkey2native(key);
|
||||
|
||||
free(blob);
|
||||
|
||||
void pcppubkey_print(pcp_pubkey_t *key, FILE* out, int pbpcompat) {
|
||||
struct tm *c;
|
||||
time_t t = (time_t)key->ctime;
|
||||
c = localtime(&t);
|
||||
|
||||
fprintf(out, "%s\n", PCP_PUBKEY_HEADER);
|
||||
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));
|
||||
|
||||
fprintf(out, " Generated by: %s Version %d.%d.%d\n",
|
||||
PCP_ME, PCP_VERSION_MAJOR, PCP_VERSION_MINOR, PCP_VERSION_PATCH);
|
||||
memcpy(raw, key->pub, crypto_box_PUBLICKEYBYTES);
|
||||
pos += crypto_box_PUBLICKEYBYTES;
|
||||
|
||||
fprintf(out, " Cipher: %s\n", PCP_KEY_PRIMITIVE);
|
||||
memcpy(&raw[pos], key->edpub, crypto_sign_PUBLICKEYBYTES);
|
||||
pos += crypto_sign_PUBLICKEYBYTES;
|
||||
|
||||
fprintf(out, " Owner: %s\n", key->owner);
|
||||
fprintf(out, " Mail: %s\n", key->mail);
|
||||
memcpy(&raw[pos], key->pub, crypto_box_PUBLICKEYBYTES);
|
||||
pos += crypto_box_PUBLICKEYBYTES;
|
||||
|
||||
fprintf(out, " Key-ID: 0x%s\n", key->id);
|
||||
fprintf(out, " Public-Key: %s\n", pcp_z85_encode(key->pub, 32, &zlen));
|
||||
struct tm *v;
|
||||
time_t vt = t + 31536000;
|
||||
v = localtime(&vt);
|
||||
|
||||
//2004-06-14T23:34:30.
|
||||
fprintf(out, " Creation Time: %04d-%02d-%02dT%02d:%02d:%02d\n",
|
||||
c->tm_year+1900, c->tm_mon+1, c->tm_mday,
|
||||
c->tm_hour, c->tm_min, c->tm_sec);
|
||||
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);
|
||||
|
||||
unsigned char *hash = pcppubkey_getchecksum(key);
|
||||
fprintf(out, " Checksum: ");
|
||||
sprintf(name, "%s|%s", key->owner, key->mail);
|
||||
|
||||
int i;
|
||||
for ( i = 0;i <15 ;++i) fprintf(out, "%02X:",(unsigned int) hash[i]);
|
||||
fprintf(out, "%02X", hash[15]);
|
||||
fprintf(out, "\n ");
|
||||
for ( i = 16;i <31 ;++i) fprintf(out, "%02X:",(unsigned int) hash[i]);
|
||||
fprintf(out, "%02X", hash[31]);
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, " Serial Number: 0x%08X\n", key->serial);
|
||||
fprintf(out, " Key Version: 0x%08X\n", key->version);
|
||||
|
||||
char *r = pcppubkey_get_art(key);
|
||||
fprintf(out, " Random Art ID: ");
|
||||
for (i=0; i<strlen(r); ++i) {
|
||||
if(r[i] == '\n') {
|
||||
fprintf(out, "\n ");
|
||||
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 {
|
||||
fprintf(out, "%c", r[i]);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(out, "\n");
|
||||
else {
|
||||
size_t zlen;
|
||||
|
||||
//printf("version: %08x\n", key->version);
|
||||
|
||||
pubkey2be(key);
|
||||
|
||||
void *blob = ucmalloc(PCP_RAW_PUBKEYSIZE);
|
||||
pcp_pubkeyblob(blob, key);
|
||||
char *z85encoded = pcp_z85_encode((unsigned char*)blob, PCP_RAW_PUBKEYSIZE, &zlen);
|
||||
pubkey2native(key);
|
||||
|
||||
free(blob);
|
||||
|
||||
|
||||
|
||||
fprintf(out, "%s\n", PCP_PUBKEY_HEADER);
|
||||
|
||||
fprintf(out, " Generated by: %s Version %d.%d.%d\n",
|
||||
PCP_ME, PCP_VERSION_MAJOR, PCP_VERSION_MINOR, PCP_VERSION_PATCH);
|
||||
|
||||
fprintf(out, " Cipher: %s\n", PCP_KEY_PRIMITIVE);
|
||||
|
||||
fprintf(out, " Owner: %s\n", key->owner);
|
||||
fprintf(out, " Mail: %s\n", key->mail);
|
||||
|
||||
fprintf(out, " Key-ID: 0x%s\n", key->id);
|
||||
fprintf(out, " Public-Key: %s\n", pcp_z85_encode(key->pub, 32, &zlen));
|
||||
|
||||
//2004-06-14T23:34:30.
|
||||
fprintf(out, " Creation Time: %04d-%02d-%02dT%02d:%02d:%02d\n",
|
||||
c->tm_year+1900, c->tm_mon+1, c->tm_mday,
|
||||
c->tm_hour, c->tm_min, c->tm_sec);
|
||||
|
||||
unsigned char *hash = pcppubkey_getchecksum(key);
|
||||
fprintf(out, " Checksum: ");
|
||||
|
||||
int i;
|
||||
for ( i = 0;i <15 ;++i) fprintf(out, "%02X:",(unsigned int) hash[i]);
|
||||
fprintf(out, "%02X", hash[15]);
|
||||
fprintf(out, "\n ");
|
||||
for ( i = 16;i <31 ;++i) fprintf(out, "%02X:",(unsigned int) hash[i]);
|
||||
fprintf(out, "%02X", hash[31]);
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, " Serial Number: 0x%08X\n", key->serial);
|
||||
fprintf(out, " Key Version: 0x%08X\n", key->version);
|
||||
|
||||
fprintf(out, "\n%s\n", z85encoded);
|
||||
|
||||
fprintf(out, "%s\n", PCP_PUBKEY_FOOTER);
|
||||
|
||||
free(hash);
|
||||
free(r);
|
||||
free(z85encoded);
|
||||
char *r = pcppubkey_get_art(key);
|
||||
fprintf(out, " Random Art ID: ");
|
||||
for (i=0; i<strlen(r); ++i) {
|
||||
if(r[i] == '\n') {
|
||||
fprintf(out, "\n ");
|
||||
}
|
||||
else {
|
||||
fprintf(out, "%c", r[i]);
|
||||
}
|
||||
}
|
||||
fprintf(out, "\n");
|
||||
|
||||
fprintf(out, "\n%s\n", z85encoded);
|
||||
|
||||
fprintf(out, "%s\n", PCP_PUBKEY_FOOTER);
|
||||
|
||||
free(hash);
|
||||
free(r);
|
||||
free(z85encoded);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
15
src/pcp.c
15
src/pcp.c
@@ -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:
|
||||
|
||||
@@ -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" \
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user