changed secret key export format, now we encrypt the whole thing, and we use an extra passphrase to do so. import wrapper in src/ not implemented yet.

This commit is contained in:
git@daemon.de
2014-02-12 16:47:24 +01:00
parent a78dd9c6eb
commit 621cece568
12 changed files with 294 additions and 148 deletions

5
TODO
View File

@@ -14,10 +14,6 @@ Implement pbp crypto fix https://github.com/stef/pbp/commit/7d7b7c9ecb7604ad2293
move remaining Export+Import stuff from src => lib. move remaining Export+Import stuff from src => lib.
Update pubimport to new format
Update secret im+ex-port to new format.
Update pod key format spec. Update pod key format spec.
-l show keysig, if any -l show keysig, if any
@@ -26,6 +22,7 @@ vault checksum: add keysigs as well
keysig: fix struct to be even (i.e. type => uint16_t or something) OR add a keysig2blob function keysig: fix struct to be even (i.e. type => uint16_t or something) OR add a keysig2blob function
Secretkey import: fill in calculated fields (keyid etc), add pcp_importsecret() wrapper to keymgmt.c
Python binding, e.g.: Python binding, e.g.:
py % cdll.LoadLibrary("libsodium.so.8") py % cdll.LoadLibrary("libsodium.so.8")

View File

@@ -8,7 +8,6 @@ extern "C" {
#include "pcp/config.h" #include "pcp/config.h"
#include "pcp/base85.h" #include "pcp/base85.h"
#include "pcp/buffer.h" #include "pcp/buffer.h"
#include "pcp/config.h"
#include "pcp/crypto.h" #include "pcp/crypto.h"
#include "pcp/defines.h" #include "pcp/defines.h"
#include "pcp/digital_crc32.h" #include "pcp/digital_crc32.h"
@@ -17,6 +16,7 @@ extern "C" {
#include "pcp/jenhash.h" #include "pcp/jenhash.h"
#include "pcp/key.h" #include "pcp/key.h"
#include "pcp/keyhash.h" #include "pcp/keyhash.h"
#include "pcp/keysig.h"
#include "pcp/mac.h" #include "pcp/mac.h"
#include "pcp/mem.h" #include "pcp/mem.h"
#include "pcp/mgmt.h" #include "pcp/mgmt.h"

View File

@@ -38,6 +38,7 @@
#include "uthash.h" #include "uthash.h"
#include "jenhash.h" #include "jenhash.h"
#include "scrypt.h" #include "scrypt.h"
#include "keysig.h"
/* /*
PCP private key structure. Most fields are self explanatory. PCP private key structure. Most fields are self explanatory.
@@ -142,22 +143,6 @@ typedef struct _pcp_rec_t pcp_rec_t;
#define PCP_RAW_KEYSIZE sizeof(pcp_key_t) - sizeof(UT_hash_handle) #define PCP_RAW_KEYSIZE sizeof(pcp_key_t) - sizeof(UT_hash_handle)
#define PCP_RAW_PUBKEYSIZE sizeof(pcp_pubkey_t) - sizeof(UT_hash_handle) #define PCP_RAW_PUBKEYSIZE sizeof(pcp_pubkey_t) - sizeof(UT_hash_handle)
#define PCP_RAW_KEYSIGSIZE sizeof(pcp_keysig_t) - sizeof(UT_hash_handle)
/* holds a public key signature */
struct _pcp_keysig_t {
uint8_t type;
uint32_t size;
char belongs[17];
byte checksum[32];
byte *blob;
UT_hash_handle hh;
};
typedef struct _pcp_keysig_t pcp_keysig_t;
@@ -186,10 +171,6 @@ pcp_key_t *key2native(pcp_key_t *k);
pcp_pubkey_t * pubkey2be(pcp_pubkey_t *k); pcp_pubkey_t * pubkey2be(pcp_pubkey_t *k);
pcp_pubkey_t *pubkey2native(pcp_pubkey_t *k); pcp_pubkey_t *pubkey2native(pcp_pubkey_t *k);
pcp_keysig_t *keysig2be(pcp_keysig_t *s);
pcp_keysig_t *keysig2native(pcp_keysig_t *s);
unsigned char * pcp_gennonce(); unsigned char * pcp_gennonce();
void pcpedit_key(char *keyid); void pcpedit_key(char *keyid);
@@ -207,8 +188,5 @@ void *pcp_keyblob(void *k, int type); /* allocates blob */
int pcp_sanitycheck_pub(pcp_pubkey_t *key); int pcp_sanitycheck_pub(pcp_pubkey_t *key);
int pcp_sanitycheck_key(pcp_key_t *key); int pcp_sanitycheck_key(pcp_key_t *key);
/* fetch a keysig from a buffer, usually loaded from vault */
pcp_keysig_t *pcp_keysig_new(Buffer *blob);
#endif /* _HAVE_PCP_KEYPAIR_H */ #endif /* _HAVE_PCP_KEYPAIR_H */

View File

@@ -19,6 +19,9 @@
You can contact me by mail: <tom AT vondein DOT org>. You can contact me by mail: <tom AT vondein DOT org>.
*/ */
/*
key management, namely import and export routines.
we're working with buffers only, no direct file i/o */
#ifndef _HAVE_PCP_MGMT_H #ifndef _HAVE_PCP_MGMT_H
#define _HAVE_PCP_MGMT_H #define _HAVE_PCP_MGMT_H
@@ -33,16 +36,32 @@
#include "mem.h" #include "mem.h"
#include "ed.h" #include "ed.h"
#include "key.h" #include "key.h"
#include "keysig.h"
#include "buffer.h" #include "buffer.h"
#include "scrypt.h"
/* key management api, export, import, yaml and stuff */ /* key management api, export, import, yaml and stuff */
/* RFC4880 alike public key export with some simplifications: /* RFC4880 alike public key export with some modifications:
In sig subpackets we're using fixed sized fields instead - Key material is native to us and not specified in the
of the mess they use in rfc4880. Sorry. We use only these types: rfc for curve25519/ed25519. Therefore we're doing it like
so: mp|sp|cp
where mp = master keysigning public key (ed25519), 32 bytes
sp = signing public key (ed25519), 32 bytes
cp = encryption public key (curve25519), 32 bytes
- The various cipher (algorithm) id's are unspecified for
our native ciphers. Therefore I created them, starting at
33 (afaik 22 is the last officially assigned one). Once
those cipher numbers become official, I'll use them instead
of my own.
- The exported public key packet contains a signature. We're
filling out all required fields. A signature has a variable
number of sig sub packets. We use only these types:
2 = Signature Creation Time (4 byte) 2 = Signature Creation Time (4 byte)
3 = Signature Expiration Time (4 byte) 3 = Signature Expiration Time (4 byte)
@@ -50,26 +69,64 @@
20 = Notation Data (4 byte flags, N bytes name+value) 20 = Notation Data (4 byte flags, N bytes name+value)
27 = Key Flags (1 byte, use 0x02, 0x08 and 0x80 27 = Key Flags (1 byte, use 0x02, 0x08 and 0x80
The actual signature field doesn't contain the 1st 16 bits - We use 3 notation fields:
of the hash, since crypto_sign() created signatures consist * "owner", which contains the owner name, if set
of the hash+signature anyway. * "mail", which contains the emailaddress, if set
* "serial", which contains the 32bit serial number
- The actual signature field consists of the blake2 hash of
(mp|sp|cp|keysig) followed by the nacl signature. However, we do
not put an extra 16byte value of the hash, since the nacl
signature already contains the full hash. So, an implementation
could simply pull the fist 16 bytes of said hash to get
the same result.
- The mp keypair will be used for signing. The recipient can
verify the signature, since mp is included.
- While we put expiration dates for the key and the signature
into the export as the rfc demands, we ignore them. Key expiring
is not implemented in PCP yet.
So, a full pubkey export looks like this So, a full pubkey export looks like this
version version
ctime ctime
cipher cipher
3 x raw keys \ 3 x raw keys \
sigheader > calc hash from this sigheader > calc hash from this
sigsubs (header+data) / sigsubs (header+data) /
hash hash
signature signature
We use big-endian always. We use big-endian always.
Unlike RC4880 public key exports, we're using Z85 encoding if
armoring have been requested by the user. Armored output has
a header and a footer line, however they are ignored by the
parser and are therefore optional. Newlines, if present, are
optional as well.
http://tools.ietf.org/html/rfc4880#section-5.2.3 http://tools.ietf.org/html/rfc4880#section-5.2.3
*/ The key sig blob will be saved in the Vault if we import a public key
unaltered, so we can verify the signature at will anytime. When exporting
a foreign public key, we will just put out that key sig blob to the
export untouched.
Currently PCP only support self-signed public key exports.
We only support one key signature per key. However, it would be easily
possible to support foreign keysigs as well in the future.
-----------
Secret key are exported in proprietary format. We just encrypt the
whole structure symmetrically and prepend it with a nonce.
*/
/* various helper structs, used internally only */
struct _pcp_rfc_pubkey_header_t { struct _pcp_rfc_pubkey_header_t {
uint8_t version; uint8_t version;
uint32_t ctime; uint32_t ctime;
@@ -127,24 +184,33 @@ typedef struct _pcp_ks_bundle_t pcp_ks_bundle_t;
/* in armored mode, we're using the usual head+foot */ /* in armored mode, we're using the usual head+foot */
#define EXP_PK_HEADER "-----BEGIN ED25519-CURVE29915 PUBLIC KEY-----" #define EXP_PK_HEADER "-----BEGIN ED25519-CURVE29915 PUBLIC KEY-----"
#define EXP_PK_FOOTER "------END ED25519-CURVE29915 PUBLICKEY------" #define EXP_PK_FOOTER "------END ED25519-CURVE29915 PUBLIC KEY------"
#define EXP_SK_HEADER "-----BEGIN ED25519-CURVE29915 PRIVATE KEY-----"
#define EXP_SK_FOOTER "------END ED25519-CURVE29915 PRIVATE KEY------"
/* pubkey export formats */ /* pubkey export formats */
#define EXP_FORMAT_NATIVE 0x01 #define EXP_FORMAT_NATIVE 0x01
#define EXP_FORMAT_PBP 0x03 #define EXP_FORMAT_PBP 0x03
/* export self signed public key from master secret */
/* export public key */
Buffer *pcp_export_rfc_pub (pcp_key_t *sk); Buffer *pcp_export_rfc_pub (pcp_key_t *sk);
/* export foreign public key
Buffer *pcp_export_rfc_pub_foreign (pcp_pubkey_t *pub); */
/* export public key in pbp format */ /* export public key in pbp format */
Buffer *pcp_export_pbp_pub(pcp_key_t *sk); Buffer *pcp_export_pbp_pub(pcp_key_t *sk);
/* export secret key */
Buffer *pcp_export_secret(pcp_key_t *sk, char *passphrase);
/* import public keys */ /* import public keys */
pcp_ks_bundle_t *pcp_import_pub(unsigned char *raw, size_t rawsize); pcp_ks_bundle_t *pcp_import_pub(unsigned char *raw, size_t rawsize);
pcp_ks_bundle_t *pcp_import_pub_rfc(Buffer *blob); pcp_ks_bundle_t *pcp_import_pub_rfc(Buffer *blob);
pcp_ks_bundle_t *pcp_import_pub_pbp(Buffer *blob); pcp_ks_bundle_t *pcp_import_pub_pbp(Buffer *blob);
/* import secret key */
pcp_key_t *pcp_import_secret(Buffer *cipher, char *passphrase);
#endif // _HAVE_PCP_MGMT_H #endif // _HAVE_PCP_MGMT_H

View File

@@ -35,6 +35,7 @@
#include "key.h" #include "key.h"
#include "uthash.h" #include "uthash.h"
#include "buffer.h" #include "buffer.h"
#include "keysig.h"
struct _vault_t { struct _vault_t {
char *filename; char *filename;

View File

@@ -296,28 +296,6 @@ pcp_pubkey_t *pubkey2native(pcp_pubkey_t *k) {
#endif #endif
} }
pcp_keysig_t * keysig2be(pcp_keysig_t *s) {
#ifdef __CPU_IS_BIG_ENDIAN
return s;
#else
uint32_t size = s->size;
unsigned char* p = (unsigned char*)&size;
if(p[0] != 0) {
s->size = htobe32(s->size);
}
return s;
#endif
}
pcp_keysig_t *keysig2native(pcp_keysig_t *s) {
#ifdef __CPU_IS_BIG_ENDIAN
return s;
#else
s->size = be32toh(s->size);
return s;
#endif
}
void pcp_seckeyblob(void *blob, pcp_key_t *k) { void pcp_seckeyblob(void *blob, pcp_key_t *k) {
memcpy(blob, k, PCP_RAW_KEYSIZE); memcpy(blob, k, PCP_RAW_KEYSIZE);
} }
@@ -441,25 +419,3 @@ int pcp_sanitycheck_key(pcp_key_t *key) {
return 0; return 0;
} }
pcp_keysig_t *pcp_keysig_new(Buffer *blob) {
/* FIXME: sanity check before actually loading it */
pcp_keysig_t *sk = ucmalloc(sizeof(pcp_keysig_t));
uint8_t type = buffer_get8(blob);
uint32_t size = buffer_get32na(blob);
byte *checksum = ucmalloc(32);
buffer_get_chunk(blob, checksum, 32);
sk->blob = ucmalloc(size);
buffer_get_chunk(blob, sk->blob, size);
sk->size = size;
sk->type = type;
memcpy(sk->checksum, checksum, 32);
ucfree(checksum, 32);
return sk;
}

View File

@@ -54,7 +54,10 @@ void *urmalloc(size_t s) {
void *ucrealloc(void *d, size_t oldlen, size_t newlen) { void *ucrealloc(void *d, size_t oldlen, size_t newlen) {
newlen = newlen * sizeof(unsigned char); newlen = newlen * sizeof(unsigned char);
void *value = realloc (d, newlen);
/* we're using a 1 byte sized pointer, so that we can
memset(zero) it after resizing */
unsigned char *value = realloc (d, newlen);
if (value == NULL) { if (value == NULL) {
err(errno, "Cannot reallocate %ld bytes of memory", newlen); err(errno, "Cannot reallocate %ld bytes of memory", newlen);
@@ -63,7 +66,7 @@ void *ucrealloc(void *d, size_t oldlen, size_t newlen) {
memset (&value[oldlen], 0, newlen-oldlen); memset (&value[oldlen], 0, newlen-oldlen);
return value; return (void *)value;
} }
void ucfree(void *d, size_t len) { void ucfree(void *d, size_t len) {

View File

@@ -93,6 +93,11 @@ int _check_sigsubs(Buffer *blob, pcp_pubkey_t *p, rfc_pub_sig_s *subheader) {
else if(strncmp(notation, "mail", 4) == 0) { else if(strncmp(notation, "mail", 4) == 0) {
memcpy(p->mail, value, vsize); memcpy(p->mail, value, vsize);
} }
else if(strncmp(notation, "serial", 6) == 0) {
uint32_t serial;
memcpy(&serial, value, 4);
p->serial = htobe32(serial);
}
ucfree(notation, nsize); ucfree(notation, nsize);
ucfree(value, vsize); ucfree(value, vsize);
@@ -194,9 +199,7 @@ pcp_ks_bundle_t *pcp_import_pub(unsigned char *raw, size_t rawsize) {
if(version == PCP_KEY_VERSION) { if(version == PCP_KEY_VERSION) {
/* ah, homerun */ /* ah, homerun */
pcp_ks_bundle_t *b = pcp_import_pub_rfc(blob); return pcp_import_pub_rfc(blob);
pcp_keysig_t *sk = b->s;
return b;
} }
else { else {
/* nope, it's probably pbp */ /* nope, it's probably pbp */
@@ -332,8 +335,8 @@ Buffer *pcp_export_pbp_pub(pcp_key_t *sk) {
Buffer *pcp_export_rfc_pub (pcp_key_t *sk) { Buffer *pcp_export_rfc_pub (pcp_key_t *sk) {
Buffer *out = buffer_new(320, "bo1"); Buffer *out = buffer_new(320, "exportbuf");
Buffer *raw = buffer_new(256, "bs1"); Buffer *raw = buffer_new(256, "keysigbuf");
/* add the header */ /* add the header */
buffer_add8(out, PCP_KEY_VERSION); buffer_add8(out, PCP_KEY_VERSION);
@@ -390,6 +393,15 @@ Buffer *pcp_export_rfc_pub (pcp_key_t *sk) {
buffer_add(raw, sk->mail, strlen(sk->mail)); buffer_add(raw, sk->mail, strlen(sk->mail));
} }
/* add serial number notation sub */
notation_size = 6 + 4 + 4;
buffer_add32be(raw, notation_size);
buffer_add8(raw, EXP_SIG_SUB_NOTATION);
buffer_add16be(raw, 6);
buffer_add16be(raw, 4);
buffer_add(raw, "serial", 6);
buffer_add32be(raw, sk->serial);
/* add key flags */ /* add key flags */
buffer_add32be(raw, 1); buffer_add32be(raw, 1);
buffer_add8(raw, 27); buffer_add8(raw, 27);
@@ -423,3 +435,124 @@ Buffer *pcp_export_rfc_pub (pcp_key_t *sk) {
return out; return out;
} }
Buffer *pcp_export_secret(pcp_key_t *sk, char *passphrase) {
unsigned char *nonce = NULL;
unsigned char *symkey = NULL;
unsigned char *cipher = NULL;
size_t es;
Buffer *raw = buffer_new(512, "secretbuf");
Buffer *out = buffer_new(512, "secretciperblob");
buffer_add(raw, sk->mastersecret, 64);
buffer_add(raw, sk->secret, 32);
buffer_add(raw, sk->edsecret, 64);
buffer_add(raw, sk->masterpub, 32);
buffer_add(raw, sk->pub, 32);
buffer_add(raw, sk->edpub, 32);
if(strlen(sk->owner) > 0) {
buffer_add16be(raw, strlen(sk->owner));
buffer_add(raw, sk->owner, strlen(sk->owner));
}
else
buffer_add16be(raw, 0);
if(strlen(sk->mail) > 0) {
buffer_add16be(raw, strlen(sk->mail));
buffer_add(raw, sk->mail, strlen(sk->mail));
}
else
buffer_add16be(raw, 0);
buffer_add64be(raw, sk->ctime);
buffer_add32be(raw, sk->version);
buffer_add32be(raw, sk->serial);
nonce = ucmalloc(crypto_secretbox_NONCEBYTES);
arc4random_buf(nonce, crypto_secretbox_NONCEBYTES);
symkey = pcp_scrypt(passphrase, strlen(passphrase), nonce, crypto_secretbox_NONCEBYTES);
es = pcp_sodium_mac(&cipher, buffer_get(raw), buffer_size(raw), nonce, symkey);
buffer_add(out, nonce, crypto_secretbox_NONCEBYTES);
buffer_add(out, cipher, es);
buffer_free(raw);
ucfree(nonce, crypto_secretbox_NONCEBYTES);
ucfree(symkey, 64);
ucfree(cipher, es);
return out;
}
pcp_key_t *pcp_import_secret(Buffer *cipher, char *passphrase) {
pcp_key_t *sk = ucmalloc(sizeof(pcp_key_t));
unsigned char *nonce = ucmalloc(crypto_secretbox_NONCEBYTES);
unsigned char *symkey = NULL;
unsigned char *clear = NULL;
size_t cipherlen = 0;
size_t minlen = (64 * 2) * (32 * 4) + 8 + 4 + 4;
uint16_t notationlen = 0;
Buffer *blob = buffer_new(512, "secretdecryptbuf");
if(buffer_get_chunk(cipher, nonce, crypto_secretbox_NONCEBYTES) == 0)
goto impserr1;
symkey = pcp_scrypt(passphrase, strlen(passphrase), nonce, crypto_secretbox_NONCEBYTES);
cipherlen = buffer_left(cipher);
if(cipherlen < minlen) {
fatal("expected decrypted secret key size %ld is less than minimum len %ld\n", cipherlen, minlen);
goto impserr1;
}
if(pcp_sodium_verify_mac(&clear, buffer_get_remainder(cipher),
cipherlen, nonce, symkey) != 0)
goto impserr1;
buffer_add(blob, clear, cipherlen - PCP_CRYPTO_ADD);
buffer_get_chunk(blob, sk->mastersecret, 64);
buffer_get_chunk(blob, sk->secret, 32);
buffer_get_chunk(blob, sk->edsecret, 64);
buffer_get_chunk(blob, sk->masterpub, 32);
buffer_get_chunk(blob, sk->pub, 32);
buffer_get_chunk(blob, sk->edpub, 32);
notationlen = buffer_get16na(blob);
if(notationlen > 0)
buffer_get_chunk(blob, sk->owner, notationlen);
notationlen = buffer_get16na(blob);
if(notationlen > 0)
buffer_get_chunk(blob, sk->mail, notationlen);
if(buffer_done(blob) == 1)
goto impserr2;
sk->ctime = buffer_get64na(blob);
sk->version = buffer_get32na(blob);
sk->serial = buffer_get32na(blob);
/* ready */
ucfree(clear, cipherlen - PCP_CRYPTO_ADD);
ucfree(nonce, crypto_secretbox_NONCEBYTES);
ucfree(sk, sizeof(pcp_key_t));
buffer_free(blob);
return sk;
impserr2:
ucfree(clear, cipherlen - PCP_CRYPTO_ADD);
impserr1:
ucfree(nonce, crypto_secretbox_NONCEBYTES);
ucfree(sk, sizeof(pcp_key_t));
buffer_free(blob);
return NULL;
}

View File

@@ -168,22 +168,13 @@ int pcpvault_addkey(vault_t *vault, void *item, uint8_t type) {
else if(type == PCP_KEYSIG_NATIVE || type == PCP_KEYSIG_NATIVE) { else if(type == PCP_KEYSIG_NATIVE || type == PCP_KEYSIG_NATIVE) {
pcp_keysig_t *sk = (pcp_keysig_t *)item; pcp_keysig_t *sk = (pcp_keysig_t *)item;
itemsize = PCP_RAW_KEYSIGSIZE + sk->size; Buffer *b = pcp_keysig2blob(sk);
size_t blobsize = sk->size; itemsize = buffer_size(b);
blob = ucmalloc(itemsize); blob = ucmalloc(itemsize);
sk = keysig2be(sk);
memcpy(blob, buffer_get(b), buffer_size(b));
buffer_free(b);
/* FIXME: use Buffer or function */
uint8_t t = sk->type;
uint32_t s = sk->size;
memcpy(blob, &t, 1);
memcpy(blob+1, &s, 4);
memcpy(blob+5, sk->belongs, 17);
memcpy(blob+5+17, sk->checksum, 32);
memcpy(blob+5+17+32, sk->blob, blobsize);
sk = keysig2native(sk);
saveitem = (void *)sk; saveitem = (void *)sk;
} }
else { else {

View File

@@ -62,7 +62,7 @@ int pcp_storekey (pcp_key_t *key) {
return 1; return 1;
} }
void pcp_keygen(char *passwd, char *outfile) { void pcp_keygen(char *passwd) {
pcp_key_t *k = pcpkey_new (); pcp_key_t *k = pcpkey_new ();
pcp_key_t *key = NULL; pcp_key_t *key = NULL;
@@ -101,20 +101,11 @@ void pcp_keygen(char *passwd, char *outfile) {
if(key != NULL) { if(key != NULL) {
fprintf(stderr, "Generated new secret key:\n"); fprintf(stderr, "Generated new secret key:\n");
if(outfile != NULL) { if(pcp_storekey(key) == 0) {
pcp_exportsecretkey(key, outfile);
pcpkey_printshortinfo(key); pcpkey_printshortinfo(key);
fprintf(stderr, "key stored to file %s, vault unaltered\n", outfile);
memset(key, 0, sizeof(pcp_key_t)); memset(key, 0, sizeof(pcp_key_t));
free(key); free(key);
} }
else {
if(pcp_storekey(key) == 0) {
pcpkey_printshortinfo(key);
memset(key, 0, sizeof(pcp_key_t));
free(key);
}
}
} }
errkg1: errkg1:
@@ -205,7 +196,7 @@ pcp_key_t *pcp_find_primary_secret() {
return NULL; return NULL;
} }
void pcp_exportsecret(char *keyid, int useid, char *outfile) { void pcp_exportsecret(char *keyid, int useid, char *outfile, int armor) {
pcp_key_t *key = NULL; pcp_key_t *key = NULL;
if(useid == 1) { if(useid == 1) {
@@ -213,7 +204,7 @@ void pcp_exportsecret(char *keyid, int useid, char *outfile) {
HASH_FIND_STR(pcpkey_hash, keyid, key); HASH_FIND_STR(pcpkey_hash, keyid, key);
if(key == NULL) { if(key == NULL) {
fatal("Could not find a secret key with id 0x%s in vault %s!\n", keyid, vault->filename); fatal("Could not find a secret key with id 0x%s in vault %s!\n", keyid, vault->filename);
free(key); goto errexpse1;
} }
} }
else { else {
@@ -221,15 +212,10 @@ void pcp_exportsecret(char *keyid, int useid, char *outfile) {
key = pcp_find_primary_secret(); key = pcp_find_primary_secret();
if(key == NULL) { if(key == NULL) {
fatal("There's no primary secret key in the vault %s!\n", vault->filename); fatal("There's no primary secret key in the vault %s!\n", vault->filename);
goto errexpse1;
} }
} }
if(key != NULL) {
pcp_exportsecretkey(key, outfile);
}
}
void pcp_exportsecretkey(pcp_key_t *key, char *outfile) {
FILE *out; FILE *out;
if(outfile == NULL) { if(outfile == NULL) {
out = stdout; out = stdout;
@@ -237,19 +223,57 @@ void pcp_exportsecretkey(pcp_key_t *key, char *outfile) {
else { else {
if((out = fopen(outfile, "wb+")) == NULL) { if((out = fopen(outfile, "wb+")) == NULL) {
fatal("Could not create output file %s", outfile); fatal("Could not create output file %s", outfile);
out = NULL; goto errexpse1;
} }
} }
if(out != NULL) { if(out != NULL) {
if(debug) if(debug)
pcp_dumpkey(key); pcp_dumpkey(key);
else
pcpkey_print(key, out); if(key->secret[0] == 0) {
/* scip */ /* decrypt the secret key */
/* printf("EXPORT:\n"); */ char *passphrase;
/* pcpprint_bin(stdout, key, PCP_RAW_KEYSIZE); printf("\n"); */ pcp_readpass(&passphrase,
"Enter passphrase to decrypt your secret key", NULL, 1);
key = pcpkey_decrypt(key, passphrase);
if(key == NULL) {
memset(passphrase, 0, strlen(passphrase));
free(passphrase);
goto errexpse1;
}
memset(passphrase, 0, strlen(passphrase));
free(passphrase);
}
char *passphrase;
pcp_readpass(&passphrase,
"Enter passphrase to encrypt the exported secret key", "Repeat passphrase", 1);
Buffer *exported_sk = pcp_export_secret(key, passphrase);
if(exported_sk != NULL) {
if(armor == 1) {
size_t zlen;
char *z85 = pcp_z85_encode(buffer_get(exported_sk), buffer_size(exported_sk), &zlen);
fprintf(out, "%s\r\n%s\r\n%s\r\n", EXP_SK_HEADER, z85, EXP_SK_FOOTER);
free(z85);
}
else {
fwrite(buffer_get(exported_sk), 1, buffer_size(exported_sk), out);
}
buffer_free(exported_sk);
fprintf(stderr, "secret key exported.\n");
}
memset(passphrase, 0, strlen(passphrase));
free(passphrase);
} }
errexpse1:
;
} }
@@ -264,7 +288,7 @@ void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format, int
int is_foreign = 0; int is_foreign = 0;
pcp_pubkey_t *pk = NULL; pcp_pubkey_t *pk = NULL;
pcp_key_t *sk = NULL; pcp_key_t *sk = NULL;
Buffer *exported_pk; Buffer *exported_pk = NULL;
if(outfile == NULL) { if(outfile == NULL) {
out = stdout; out = stdout;
@@ -316,9 +340,9 @@ void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format, int
"Enter passphrase to decrypt your secret key", NULL, 1); "Enter passphrase to decrypt your secret key", NULL, 1);
sk = pcpkey_decrypt(sk, passphrase); sk = pcpkey_decrypt(sk, passphrase);
if(sk == NULL) { if(sk == NULL) {
goto errpcpexpu1;
memset(passphrase, 0, strlen(passphrase)); memset(passphrase, 0, strlen(passphrase));
free(passphrase); free(passphrase);
goto errpcpexpu1;
} }
memset(passphrase, 0, strlen(passphrase)); memset(passphrase, 0, strlen(passphrase));
free(passphrase); free(passphrase);
@@ -333,9 +357,6 @@ void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format, int
size_t zlen; size_t zlen;
char *z85 = pcp_z85_encode(buffer_get(exported_pk), buffer_size(exported_pk), &zlen); char *z85 = pcp_z85_encode(buffer_get(exported_pk), buffer_size(exported_pk), &zlen);
fprintf(out, "%s\r\n%s\r\n%s\r\n", EXP_PK_HEADER, z85, EXP_PK_FOOTER); fprintf(out, "%s\r\n%s\r\n%s\r\n", EXP_PK_HEADER, z85, EXP_PK_FOOTER);
FILE *t = fopen("binexp", "wb+");
fwrite(buffer_get(exported_pk), 1, buffer_size(exported_pk), t);
fclose(t);
free(z85); free(z85);
} }
else else
@@ -376,6 +397,7 @@ errpcpexpu1:
int pcp_importsecret (vault_t *vault, FILE *in) { int pcp_importsecret (vault_t *vault, FILE *in) {
fprintf(stderr, " pcp_importsecret line 400, port to new format\n");exit(1);
size_t clen; size_t clen;
char *z85 = pcp_readz85file(in); char *z85 = pcp_readz85file(in);

View File

@@ -47,11 +47,10 @@
char *pcp_getstdin(const char *prompt); char *pcp_getstdin(const char *prompt);
int pcp_storekey (pcp_key_t *key); int pcp_storekey (pcp_key_t *key);
void pcp_keygen(); void pcp_keygen(char *passwd);
void pcp_listkeys(); void pcp_listkeys();
void pcp_exportsecret(char *keyid, int useid, char *outfile); void pcp_exportsecret(char *keyid, int useid, char *outfile, int armor);
void pcp_exportsecretkey(pcp_key_t *key, char *outfile);
void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format, int armor); void pcp_exportpublic(char *keyid, char *passwd, char *outfile, int format, int armor);
pcp_key_t *pcp_getrsk(pcp_key_t *s, char *recipient, char *passwd); pcp_key_t *pcp_getrsk(pcp_key_t *s, char *recipient, char *passwd);

View File

@@ -366,7 +366,7 @@ int main (int argc, char **argv) {
if(vault != NULL) { if(vault != NULL) {
switch (mode) { switch (mode) {
case PCP_MODE_KEYGEN: case PCP_MODE_KEYGEN:
pcp_keygen(xpass, outfile); pcp_keygen(xpass);
if(xpass != NULL) if(xpass != NULL)
free(xpass); free(xpass);
break; break;
@@ -379,12 +379,12 @@ int main (int argc, char **argv) {
if(useid) { if(useid) {
id = pcp_normalize_id(keyid); id = pcp_normalize_id(keyid);
if(id != NULL) { if(id != NULL) {
pcp_exportsecret(id, useid, outfile); pcp_exportsecret(id, useid, outfile, armor);
free(id); free(id);
} }
} }
else { else {
pcp_exportsecret(NULL, useid, outfile); pcp_exportsecret(NULL, useid, outfile, armor);
} }
break; break;