}
/**
- * get_packetid - Given a PGP packet returns the keyid.
- * @packet: The packet to calculate the id for.
+ * get_fingerprint - Given a public key returns the fingerprint.
+ * @publickey: The key to calculate the id for.
+ * @fingerprint: The fingerprint (must be at least 20 bytes of space).
+ * @len: The length of the returned fingerprint.
+ *
+ * This function returns the fingerprint for a given public key. As Type 3
+ * fingerprints are 16 bytes and Type 4 are 20 the len field indicates
+ * which we've returned.
*/
-uint64_t get_packetid(struct openpgp_packet *packet)
+unsigned char *get_fingerprint(struct openpgp_packet *packet,
+ unsigned char *fingerprint,
+ size_t *len)
{
SHA1_CONTEXT sha_ctx;
- uint64_t keyid = 0;
- int offset = 0;
- int i = 0;
+ MD5_CONTEXT md5_ctx;
unsigned char c;
unsigned char *buff = NULL;
+ size_t modlen, explen;
+
+ assert(fingerprint != NULL);
+ assert(len != NULL);
+
+ *len = 0;
+
+ switch (packet->data[0]) {
+ case 2:
+ case 3:
+ md5_init(&md5_ctx);
+
+ /*
+ * MD5 the modulus and exponent.
+ */
+ modlen = ((packet->data[8] << 8) +
+ packet->data[9] + 7) >> 3;
+ md5_write(&md5_ctx, &packet->data[10], modlen);
+
+ explen = ((packet->data[10+modlen] << 8) +
+ packet->data[11+modlen] + 7) >> 3;
+ md5_write(&md5_ctx, &packet->data[12 + modlen], explen);
+
+ md5_final(&md5_ctx);
+ buff = md5_read(&md5_ctx);
+
+ *len = 16;
+ memcpy(fingerprint, buff, *len);
+
+ break;
+
+ case 4:
+ sha1_init(&sha_ctx);
+ /*
+ * TODO: Can this be 0x99? Are all public key packets old
+ * format with 2 bytes of length data?
+ */
+ c = 0x99;
+ sha1_write(&sha_ctx, &c, sizeof(c));
+ c = packet->length >> 8;
+ sha1_write(&sha_ctx, &c, sizeof(c));
+ c = packet->length & 0xFF;
+ sha1_write(&sha_ctx, &c, sizeof(c));
+ sha1_write(&sha_ctx, packet->data,
+ packet->length);
+ sha1_final(&sha_ctx);
+ buff = sha1_read(&sha_ctx);
+
+ *len = 20;
+ memcpy(fingerprint, buff, *len);
+ break;
+ default:
+ fprintf(stderr, "Unknown key type: %d\n",
+ packet->data[0]);
+ }
+
+ return fingerprint;
+}
+
+
+/**
+ * get_packetid - Given a PGP packet returns the keyid.
+ * @packet: The packet to calculate the id for.
+ */
+uint64_t get_packetid(struct openpgp_packet *packet)
+{
+ uint64_t keyid = 0;
+ int offset = 0;
+ int i = 0;
+ size_t length = 0;
+ unsigned char buff[20];
assert(packet != NULL);
}
break;
case 4:
- /*
- * For a type 4 key the keyid is the last 64 bits of the
- * fingerprint, which is the 160 bit SHA-1 hash of the packet
- * tag, 2 octet packet length and the public key packet
- * including version field.
- */
- sha1_init(&sha_ctx);
- /*
- * TODO: Can this be 0x99? Are all public key packets old
- * format with 2 bytes of length data?
- */
- c = 0x99;
- sha1_write(&sha_ctx, &c, sizeof(c));
- c = packet->length >> 8;
- sha1_write(&sha_ctx, &c, sizeof(c));
- c = packet->length & 0xFF;
- sha1_write(&sha_ctx, &c, sizeof(c));
- sha1_write(&sha_ctx, packet->data,
- packet->length);
- sha1_final(&sha_ctx);
- buff = sha1_read(&sha_ctx);
-
- assert(buff != NULL);
+ get_fingerprint(packet, buff, &length);
for (keyid = 0, i = 12; i < 20; i++) {
keyid <<= 8;
*/
uint64_t get_keyid(struct openpgp_publickey *publickey);
+/**
+ * get_fingerprint - Given a public key returns the fingerprint.
+ * @publickey: The key to calculate the id for.
+ * @fingerprint: The fingerprint (must be at least 20 bytes of space).
+ * @len: The length of the returned fingerprint.
+ *
+ * This function returns the fingerprint for a given public key. As Type 3
+ * fingerprints are 16 bytes and Type 4 are 20 the len field indicates
+ * which we've returned.
+ */
+unsigned char *get_fingerprint(struct openpgp_packet *packet,
+ unsigned char *fingerprint,
+ size_t *len);
+
/**
* get_packetid - Given a PGP packet returns the keyid.
* @packet: The packet to calculate the id for.
return 0;
}
+void display_fingerprint(struct openpgp_publickey *key)
+{
+ int i = 0;
+ size_t length = 0;
+ unsigned char fp[20];
+
+ get_fingerprint(key->publickey, fp, &length);
+ printf(" Key fingerprint =");
+ for (i = 0; i < length; i++) {
+ if ((length == 16) ||
+ (i % 2 == 0)) {
+ printf(" ");
+ }
+ printf("%02X", fp[i]);
+ if ((i * 2) == length) {
+ printf(" ");
+ }
+ }
+ printf("\n");
+
+ return;
+}
+
/**
* key_index - List a set of OpenPGP keys.
* @keys: The keys to display.
(int) curuid->packet->length,
curuid->packet->data);
printf("%s\n", (html) ? txt2html(buf) : buf);
+ if (fingerprint) {
+ display_fingerprint(keys);
+ }
if (verbose) {
list_sigs(curuid->sigs, html);
}
curuid = curuid->next;
} else {
putchar('\n');
+ if (fingerprint) {
+ display_fingerprint(keys);
+ }
}
list_uids(curuid, verbose, html);
bool verbose = false;
bool update = false;
bool binary = false;
+ bool fingerprint = false;
int optchar;
- while ((optchar = getopt(argc, argv, "buv")) != -1 ) {
+ while ((optchar = getopt(argc, argv, "bfuv")) != -1 ) {
switch (optchar) {
case 'b':
binary = true;
break;
+ case 'f':
+ fingerprint = true;
+ break;
case 'u':
update = true;
break;
}
initdb();
if (!strcmp("index", argv[optind])) {
- find_keys(search, keyid, ishex, false, false, false);
+ find_keys(search, keyid, ishex, fingerprint,
+ false, false);
} else if (!strcmp("vindex", argv[optind])) {
- find_keys(search, keyid, ishex, false, false, true);
+ find_keys(search, keyid, ishex, fingerprint,
+ false, true);
} else if (!strcmp("delete", argv[optind])) {
delete_key(getfullkeyid(keyid), false);
} else if (!strcmp("get", argv[optind])) {