From 579715f5602fb8f22971e403d8af375500c9a951 Mon Sep 17 00:00:00 2001 From: TLINDEN Date: Wed, 8 Jul 2015 01:24:25 +0200 Subject: [PATCH] added full json support for -p, -s, -t and -K (though only pubs for the latter at the moment) --- include/pcp/mgmt.h | 24 ++- libpcp/mgmt.c | 475 ++++++++++++++++++++++++++++++--------------- src/keyprint.c | 215 ++++++++++++++------ 3 files changed, 497 insertions(+), 217 deletions(-) diff --git a/include/pcp/mgmt.h b/include/pcp/mgmt.h index 6563ff9..70457c7 100644 --- a/include/pcp/mgmt.h +++ b/include/pcp/mgmt.h @@ -228,7 +228,7 @@ Buffer *pcp_export_pbp_pub(pcp_key_t *sk); Buffer *pcp_export_secret(PCPCTX *ptx, pcp_key_t *sk, char *passphrase); #ifdef HAVE_JSON -/** Export public key in JSON format +/** Export public key from a secret key in JSON format \param[in] sk a secret key structure of type pcp_key_t. The secret keys in there have to be already decrypted. @@ -237,7 +237,7 @@ Buffer *pcp_export_secret(PCPCTX *ptx, pcp_key_t *sk, char *passphrase); \return the function returns a Buffer object containing the binary blob containing a JSON string. */ -Buffer *pcp_export_json_pub(PCPCTX *ptx, pcp_key_t *sk, byte *sig); +Buffer *pcp_export_json_pub(PCPCTX *ptx, pcp_key_t *sk, byte *sig, size_t siglen); /** Export secret key in JSON format @@ -252,14 +252,30 @@ Buffer *pcp_export_json_pub(PCPCTX *ptx, pcp_key_t *sk, byte *sig); */ Buffer *pcp_export_json_secret(PCPCTX *ptx, pcp_key_t *sk, byte *nonce, byte *cipher, size_t clen); -json_t *pcp_pub2jsont(pcp_key_t *sk, byte *sig); +/** Convert secret key struct into JSON struct + \param[in] sk a secret key structure of type pcp_key_t. + \param[in] sig the keysig blob, maybe NULL. + + \return returns a json_t structure (see libjansson docs for details) +*/ +json_t *pcp_sk2json(pcp_key_t *sk, byte *sig,size_t siglen); + +/** Convert public key struct into JSON struct + + \param[in] pk a public key structure of type pcp_key_t. + \param[in] sig the keysig blob, maybe NULL. + + \return returns a json_t structure (see libjansson docs for details) +*/ +json_t *pcp_pk2json(pcp_pubkey_t *pk); + +pcp_ks_bundle_t *pcp_import_pub_json(PCPCTX *ptx, byte *raw, size_t rawsize); #endif pcp_ks_bundle_t *pcp_import_binpub(PCPCTX *ptx, byte *raw, size_t rawsize); -pcp_ks_bundle_t *pcp_import_pub(PCPCTX *ptx, byte *raw, size_t rawsize); /* FIXME: deprecate */ pcp_ks_bundle_t *pcp_import_pub_rfc(PCPCTX *ptx, Buffer *blob); pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob); diff --git a/libpcp/mgmt.c b/libpcp/mgmt.c index 2da4582..e9ebda7 100644 --- a/libpcp/mgmt.c +++ b/libpcp/mgmt.c @@ -154,11 +154,13 @@ int _check_hash_keysig(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, pcp_keysig_t /* everything minus version, ctime and cipher, 1st 3 fields */ sk->size = blobstop - phead; + memcpy(sk->id, p->id, 17); /* put the whole signature blob into our keysig */ blob->offset = phead; sk->blob = ucmalloc(sk->size); + buffer_get_chunk(blob, sk->blob, sk->size); /* verify the signature */ @@ -208,67 +210,36 @@ pcp_ks_bundle_t *pcp_import_binpub(PCPCTX *ptx, byte *raw, size_t rawsize) { Buffer *blob = buffer_new(512, "importblob"); pcp_ks_bundle_t *bundle = NULL; - buffer_add(blob, raw, rawsize); - - /* now, try to disassemble, if it fails, assume pbp format */ - uint8_t version = buffer_get8(blob); - - if(version == PCP_KEY_VERSION) { - /* ah, homerun */ - bundle = pcp_import_pub_rfc(ptx, blob); +#ifdef HAVE_JSON + if(ptx->json) { + bundle = pcp_import_pub_json(ptx, raw, rawsize); } else { - /* nope, it's probably pbp */ - bundle = pcp_import_pub_pbp(ptx, blob); - } +#endif + + buffer_add(blob, raw, rawsize); + /* now, try to disassemble, if it fails, assume pbp format */ + uint8_t version = buffer_get8(blob); + + if(version == PCP_KEY_VERSION) { + /* ah, homerun */ + bundle = pcp_import_pub_rfc(ptx, blob); + } + else { + /* nope, it's probably pbp */ + bundle = pcp_import_pub_pbp(ptx, blob); + } + +#ifdef HAVE_JSON + } +#endif + buffer_free(blob); return bundle; } -pcp_ks_bundle_t *pcp_import_pub(PCPCTX *ptx, byte *raw, size_t rawsize) { - size_t clen; - byte *bin = NULL; - char *z85 = NULL; - - if(rawsize == 0) { - fatal(ptx, "Input file is empty!\n"); - return NULL; - } - - Buffer *blob = buffer_new(512, "importblob"); - - /* first, try to decode the input */ - z85 = pcp_readz85string(ptx, raw, rawsize); - - if(z85 != NULL) - bin = pcp_z85_decode(ptx, z85, &clen); - - if(bin == NULL) { - /* treat as binary blob */ - fatals_reset(ptx); - buffer_add(blob, raw, rawsize); - } - else { - /* use decoded */ - buffer_add(blob, bin, clen); - ucfree(bin, clen); - } - - /* now, try to disassemble, if it fails, assume pbp format */ - uint8_t version = buffer_get8(blob); - - if(version == PCP_KEY_VERSION) { - /* ah, homerun */ - return pcp_import_pub_rfc(ptx, blob); - } - else { - /* nope, it's probably pbp */ - return pcp_import_pub_pbp(ptx, blob); - } -} - pcp_ks_bundle_t *pcp_import_pub_rfc(PCPCTX *ptx, Buffer *blob) { pcp_keysig_t *sk = NULL; pcp_ks_bundle_t *b = NULL; @@ -443,109 +414,6 @@ pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob) { return NULL; } -#ifdef HAVE_JSON - -json_t *pcp_pub2jsont(pcp_key_t *sk, byte *sig) { - json_t *jout; - char *cryptpub, *sigpub, *masterpub, *ssig; - - char *jformat = "{sssssssisisisissssssssssss}"; - - - cryptpub = _bin2hex(sk->pub, 32); - sigpub = _bin2hex(sk->edpub, 32); - masterpub= _bin2hex(sk->masterpub, 32); - - if(sig != NULL) { - ssig = _bin2hex(sig, crypto_sign_BYTES + crypto_generichash_BYTES_MAX); - } - else { - ssig = malloc(1); - ssig[0] = '\0'; - jformat = "{sssssssisisisissssssssss}"; - } - - jout = json_pack(jformat, - "id", sk->id, - "owner", sk->owner, - "mail", sk->mail, - "ctime", (int)sk->ctime, - "expire", (int)sk->ctime+31536000, - "version", (int)sk->version, - "serial", (int)sk->serial, - "type", "public", - "cipher", EXP_PK_CIPHER_NAME, - "cryptpub", cryptpub, - "sigpub", sigpub, - "masterpub", masterpub, - "signature", ssig - ); - - free(cryptpub); - free(sigpub); - free(masterpub); - if(sig != NULL) - free(ssig); - - return jout; -} - -Buffer *pcp_export_json_secret(PCPCTX *ptx, pcp_key_t *sk, byte *nonce, byte *cipher, size_t clen) { - Buffer *b = buffer_new_str("jsonbuf"); - char *jdump, *xcipher, *xnonce; - json_t *jout; - json_error_t jerror; - - assert(ptx->json); - - jout = pcp_pub2jsont(sk, NULL); - - xcipher = _bin2hex(cipher, clen); - xnonce = _bin2hex(nonce, crypto_secretbox_NONCEBYTES); - - json_object_set(jout, "type", json_string("secret")); - json_object_set(jout, "secrets", json_string(xcipher)); - json_object_set(jout, "nonce", json_string(xnonce)); - - jdump = json_dumps(jout, JSON_INDENT(4) | JSON_PRESERVE_ORDER); - - if(jdump != NULL) { - buffer_add_str(b, jdump); - free(jdump); - } - else { - fatal(ptx, "JSON encoding error: %s", jerror); - } - - json_decref(jout); - - return b; -} - -Buffer *pcp_export_json_pub(PCPCTX *ptx, pcp_key_t *sk, byte *sig) { - Buffer *b = buffer_new_str("jsonbuf"); - char *jdump; - json_t *jout; - json_error_t jerror; - - assert(ptx->json); - - jout = pcp_pub2jsont(sk, sig); - jdump = json_dumps(jout, JSON_INDENT(4) | JSON_PRESERVE_ORDER); - - if(jdump != NULL) { - buffer_add_str(b, jdump); - free(jdump); - } - else { - fatal(ptx, "JSON encoding error: %s", jerror); - } - - json_decref(jout); - - return b; -} -#endif Buffer *pcp_export_pbp_pub(pcp_key_t *sk) { struct tm *v, *c; @@ -603,7 +471,6 @@ Buffer *pcp_export_pbp_pub(pcp_key_t *sk) { Buffer *pcp_export_rfc_pub (PCPCTX *ptx, pcp_key_t *sk) { Buffer *out = buffer_new(320, "exportbuf"); Buffer *raw = buffer_new(256, "keysigbuf"); - /* add the header */ buffer_add8(out, PCP_KEY_VERSION); @@ -700,11 +567,19 @@ Buffer *pcp_export_rfc_pub (PCPCTX *ptx, pcp_key_t *sk) { /* append the signed hash */ buffer_add(out, sig, crypto_sign_BYTES + crypto_generichash_BYTES_MAX); - #ifdef HAVE_JSON if(ptx->json) { - Buffer *jout = pcp_export_json_pub(ptx, sk, sig); + /* FIXME FIXME + buffer_dump(out); + buffer_info(out); + size_t siglen = buffer_size(out) - 10; + byte *sh = ucmalloc(siglen); + + buffer_extract(out, sh, 10, siglen); + */ + Buffer *jout = pcp_export_json_pub(ptx, sk, NULL, 0); buffer_free(out); + out = jout; } #endif @@ -933,3 +808,285 @@ pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher, char *passphras free(clear); return NULL; } + + + + + + + + +#ifdef HAVE_JSON + +json_t *pcp_pk2json(pcp_pubkey_t *pk) { + /* somewhat ugly, map the pub parts of a sk into + a fake pk so that we don't have to write pcp_sk2json() + for both key types. FIXME: 'd be better to have just 1 + struct for both types... */ + json_t *out; + + pcp_key_t *sk = malloc(sizeof(pcp_key_t)); + + memcpy(sk->masterpub, pk->masterpub, 32); + memcpy(sk->pub, pk->pub, 32); + memcpy(sk->edpub, pk->edpub, 32); + memcpy(sk->owner, pk->owner, 255); + memcpy(sk->mail, pk->mail, 255); + memcpy(sk->id, pk->id, 17); + sk->ctime = pk->ctime; + sk->version = pk->version; + sk->serial = pk->serial; + sk->type = pk->type; + + out = pcp_sk2json(sk, NULL, 0); + ucfree(sk, sizeof(pcp_key_t)); + + return out; +} + +json_t *pcp_sk2json(pcp_key_t *sk, byte *sig, size_t siglen) { + json_t *jout; + char *cryptpub, *sigpub, *masterpub, *ssig; + + char *jformat = "{sssssssisisisissssssssssss}"; + + + cryptpub = _bin2hex(sk->pub, 32); + sigpub = _bin2hex(sk->edpub, 32); + masterpub= _bin2hex(sk->masterpub, 32); + + if(sig != NULL) { + ssig = _bin2hex(sig, siglen); + } + else { + ssig = malloc(1); + ssig[0] = '\0'; + jformat = "{sssssssisisisissssssssss}"; + } + + jout = json_pack(jformat, + "id", sk->id, + "owner", sk->owner, + "mail", sk->mail, + "ctime", (int)sk->ctime, + "expire", (int)sk->ctime+31536000, + "version", (int)sk->version, + "serial", (int)sk->serial, + "type", "public", + "cipher", EXP_PK_CIPHER_NAME, + "cryptpub", cryptpub, + "sigpub", sigpub, + "masterpub", masterpub, + "signature", ssig + ); + + free(cryptpub); + free(sigpub); + free(masterpub); + if(sig != NULL) + free(ssig); + + return jout; +} + +Buffer *pcp_export_json_secret(PCPCTX *ptx, pcp_key_t *sk, byte *nonce, byte *cipher, size_t clen) { + Buffer *b = buffer_new_str("jsonbuf"); + char *jdump, *xcipher, *xnonce; + json_t *jout; + json_error_t jerror; + + assert(ptx->json); + + jout = pcp_sk2json(sk, NULL, 0); + + xcipher = _bin2hex(cipher, clen); + xnonce = _bin2hex(nonce, crypto_secretbox_NONCEBYTES); + + json_object_set(jout, "type", json_string("secret")); + json_object_set(jout, "secrets", json_string(xcipher)); + json_object_set(jout, "nonce", json_string(xnonce)); + + jdump = json_dumps(jout, JSON_INDENT(4) | JSON_PRESERVE_ORDER); + + if(jdump != NULL) { + buffer_add_str(b, jdump); + free(jdump); + } + else { + fatal(ptx, "JSON encoding error: %s", jerror.text); + } + + json_decref(jout); + + return b; +} + +Buffer *pcp_export_json_pub(PCPCTX *ptx, pcp_key_t *sk, byte *sig, size_t siglen) { + Buffer *b = buffer_new_str("jsonbuf"); + char *jdump; + json_t *jout; + json_error_t jerror; + + assert(ptx->json); + + jout = pcp_sk2json(sk, sig, siglen); + jdump = json_dumps(jout, JSON_INDENT(4) | JSON_PRESERVE_ORDER); + + if(jdump != NULL) { + buffer_add_str(b, jdump); + free(jdump); + } + else { + fatal(ptx, "JSON encoding error: %s", jerror.text); + } + + json_decref(jout); + + return b; +} + +pcp_ks_bundle_t *pcp_import_pub_json(PCPCTX *ptx, byte *raw, size_t rawsize) { + pcp_ks_bundle_t *b = NULL; + pcp_keysig_t *s = NULL; + pcp_pubkey_t *p = NULL; + json_error_t jerror; + json_t *jin, *jtmp; + byte *blob; + size_t maxblob = 2048; + const char *stmp; + char *hexerr = "failed to decode hex string"; + + jin = json_loadb((char *)raw, rawsize, JSON_DISABLE_EOF_CHECK, &jerror); + if(jin == NULL) + goto jerr1; + + p = ucmalloc(sizeof(pcp_pubkey_t)); + s = ucmalloc(sizeof(pcp_keysig_t)); + b = ucmalloc(sizeof(pcp_ks_bundle_t)); + blob = ucmalloc(maxblob); + + jtmp = json_object_get(jin, "id"); + if(jtmp == NULL) + goto jerr2; + memcpy(p->id, json_string_value(jtmp), 17); + + jtmp = json_object_get(jin, "cryptpub"); + if(jtmp == NULL) + goto jerr2; + if(_hex2bin(json_string_value(jtmp), blob, maxblob) == 32) + memcpy(p->pub, blob, 32); + else { + strcpy(jerror.text, hexerr); + goto jerr2; + } + + jtmp = json_object_get(jin, "sigpub"); + if(jtmp == NULL) + goto jerr2; + if(_hex2bin(json_string_value(jtmp), blob, maxblob) == 32) + memcpy(p->edpub, blob, 32); + else { + strcpy(jerror.text, hexerr); + goto jerr2; + } + + jtmp = json_object_get(jin, "masterpub"); + if(jtmp == NULL) + goto jerr2; + if(_hex2bin(json_string_value(jtmp), blob, maxblob) == 32) + memcpy(p->masterpub, blob, 32); + else { + strcpy(jerror.text, hexerr); + goto jerr2; + } + + jtmp = json_object_get(jin, "owner"); + if(jtmp == NULL) + goto jerr2; + stmp = json_string_value(jtmp); + if(stmp != NULL) + strcpy(p->owner, stmp); + else + goto jerr2; + + jtmp = json_object_get(jin, "mail"); + if(jtmp == NULL) + goto jerr2; + stmp = json_string_value(jtmp); + if(stmp != NULL) + strcpy(p->mail, stmp); + else + goto jerr2; + + jtmp = json_object_get(jin, "ctime"); + if(jtmp == NULL) + goto jerr2; + p->ctime = (uint64_t)json_integer_value(jtmp); + + jtmp = json_object_get(jin, "version"); + if(jtmp == NULL) + goto jerr2; + p->version = (uint32_t)json_integer_value(jtmp); + + jtmp = json_object_get(jin, "serial"); + if(jtmp == NULL) + goto jerr2; + p->serial = (uint32_t)json_integer_value(jtmp); + + jtmp = json_object_get(jin, "type"); + if(jtmp == NULL) + goto jerr2; + if(json_string_value(jtmp)[0] == 'p') + p->type = PCP_KEY_TYPE_PUBLIC; + else { + strcpy(jerror.text, "key type is not public"); + goto jerr2; + } + + /* + FIXME FIXME + jtmp = json_object_get(jin, "signature"); + if(jtmp == NULL) + goto jerr2; + size_t siglen = _hex2bin(json_string_value(jtmp), blob, maxblob); + if(siglen > 1) { + Buffer *btmp = buffer_new_buf("btmp", blob, siglen); + buffer_dump(btmp); + buffer_info(btmp); + if(_check_hash_keysig(ptx, btmp, p, s) != 0) { + b->p = p; + b->s = NULL; + } + else { + b->p = p; + b->s = s; + } + buffer_free(btmp); + } + else { + strcpy(jerror.text, "sigerr"); + goto jerr2; + } + */ + + + pcp_dumppubkey(p); + + b->p = p; + b->s = NULL; + + return b; + + jerr2: + free(p); + free(s); + free(b); + free(blob); + json_decref(jin); + + jerr1: + fatal(ptx, "JSON decoding error: %s", jerror.text); + fprintf(stderr, "JSON decoding error: %s\n", jerror.text); + return NULL; +} +#endif diff --git a/src/keyprint.c b/src/keyprint.c index 7bebecb..b4f0f11 100644 --- a/src/keyprint.c +++ b/src/keyprint.c @@ -102,6 +102,46 @@ void pcptext_key(char *keyid) { } void pcptext_vault(vault_t *vault) { +#ifdef HAVE_JSON + + if(ptx->json) { + json_t *jout, *jkeys, *jtmp; + char *checksum, *jdump; + pcp_key_t *k; + pcp_pubkey_t *p; + + checksum = _bin2hex(vault->checksum, 32); + jout = json_pack("{sssisssisi}", + "keyvaultfile", vault->filename, + "version", vault->version, + "checksum", checksum, + "secretkeys", pcphash_count(ptx), + "publickey", pcphash_countpub(ptx)); + + jkeys = json_array(); + + pcphash_iterate(ptx, k) { + jtmp = pcp_sk2json(k, NULL, 0); + json_object_set(jtmp, "type", json_string("secret")); + json_array_append(jkeys, jtmp); + } + + pcphash_iteratepub(ptx, p) { + jtmp = pcp_pk2json(p); + json_array_append(jkeys, jtmp); + } + + json_object_set(jout, "keys", jkeys); + + jdump = json_dumps(jout, JSON_INDENT(4) | JSON_PRESERVE_ORDER); + printf(jdump); + json_decref(jout); + free(jdump); + } + else { + +#endif + printf(" Key vault: %s\n", vault->filename); printf("Vault version: %08X\n", vault->version); printf(" Checksum: "); @@ -116,6 +156,10 @@ void pcptext_vault(vault_t *vault) { printf(" Secret keys: %d\n", pcphash_count(ptx)); printf(" Public keys: %d\n", pcphash_countpub(ptx) ); + +#ifdef HAVE_JSON + } +#endif } void pcpkey_printlineinfo(pcp_key_t *key) { @@ -193,71 +237,134 @@ void pcppubkey_printlineinfo(pcp_pubkey_t *key) { } void pcppubkey_print(pcp_pubkey_t *key, FILE* out) { - size_t zlen; - struct tm *c; - time_t t = (time_t)key->ctime; - c = localtime(&t); - - 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, 1)); - - /* 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); - - byte *hash = pcppubkey_getchecksum(key); - fprintf(out, " Checksum: "); - - size_t 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: "); - size_t rlen = strlen(r); - for (i=0; ijson) { + json_t *jout; + char *jdump; + + jout = pcp_pk2json(key); + json_object_set(jout, "random-art-id", json_string(r)); + + jdump = json_dumps(jout, JSON_INDENT(4) | JSON_PRESERVE_ORDER); + fprintf(out, jdump); + json_decref(jout); + free(jdump); } - fprintf(out, "\n"); + else { + + #endif + + size_t zlen; + struct tm *c; + time_t t = (time_t)key->ctime; + c = localtime(&t); + + fprintf(out, " Cipher: %s\n", EXP_PK_CIPHER_NAME); + + 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, 1)); + + /* 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); + + byte *hash = pcppubkey_getchecksum(key); + fprintf(out, " Checksum: "); + + size_t 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, " Random Art ID: "); + size_t rlen = strlen(r); + for (i=0; ictime; - c = localtime(&t); + char *r = pcpkey_get_art(key); + +#ifdef HAVE_JSON - fprintf(out, " Cipher: %s\n", PCP_KEY_PRIMITIVE); + if(ptx->json) { + json_t *jout; + char *jdump; + + jout = pcp_sk2json(key, NULL, 0); + json_object_set(jout, "type", json_string("secret")); + json_object_set(jout, "random-art-id", json_string(r)); + + jdump = json_dumps(jout, JSON_INDENT(4) | JSON_PRESERVE_ORDER); + fprintf(out, jdump); + json_decref(jout); + free(jdump); + } + else { + + #endif - fprintf(out, " Key-ID: 0x%s\n", key->id); + size_t i; + struct tm *c; + time_t t = (time_t)key->ctime; + c = localtime(&t); - /* 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); + fprintf(out, " Cipher: %s\n", EXP_PK_CIPHER_NAME); + 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, " Serial Number: 0x%08X\n", key->serial); - fprintf(out, " Key Version: 0x%08X\n", key->version); - + /* 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); + + fprintf(out, " Serial Number: 0x%08X\n", key->serial); + fprintf(out, " Key Version: 0x%08X\n", key->version); + + fprintf(out, " Random Art ID: "); + size_t rlen = strlen(r); + for (i=0; i