cscvs to tla changeset 1
[onak.git] / keyid.c
1 /*
2  * keyid.c - Routines to calculate key IDs.
3  *
4  * Jonathan McDowell <noodles@earth.li>
5  *
6  * Copyright 2002 Project Purple
7  */
8
9 #include <sys/types.h>
10
11 #include "keyid.h"
12 #include "keystructs.h"
13 #include "md5.h"
14 #include "sha.h"
15
16 /**
17  *      get_keyid - Given a public key returns the keyid.
18  *      @publickey: The key to calculate the fingerprint for.
19  */
20 uint64_t get_keyid(struct openpgp_publickey *publickey)
21 {
22         SHA1_CONTEXT sha_ctx;
23         uint64_t keyid = 0;
24         int offset = 0;
25         int i = 0;
26         unsigned char c;
27         unsigned char *buff = NULL;
28
29         switch (publickey->publickey->data[0]) {
30         case 2:
31         case 3:
32                 /*
33                  * For a type 2 or 3 key the keyid is the last 64 bits of the
34                  * public modulus n, which is stored as an MPI from offset 8
35                  * onwards.
36                  *
37                  * We need to ensure it's an RSA key.
38                  */
39                 if (publickey->publickey->data[7] == 1) {
40                         offset = (publickey->publickey->data[8] << 8) +
41                                 publickey->publickey->data[9];
42                         offset = ((offset + 7) / 8) + 2;
43
44                         for (keyid = 0, i = 0; i < 8; i++) {
45                                 keyid <<= 8;
46                                 keyid += publickey->publickey->data[offset++];
47                         }
48                 } else {
49                         fputs("Type 2 or 3 key, but not RSA.\n", stderr);
50                 }
51                 break;
52         case 4:
53                 /*
54                  * For a type 4 key the keyid is the last 64 bits of the
55                  * fingerprint, which is the 160 bit SHA-1 hash of the packet
56                  * tag, 2 octet packet length and the public key packet
57                  * including version field.
58                  */
59                 sha1_init(&sha_ctx);
60                 /*
61                  * TODO: Can this be 0x99? Are all public key packets old
62                  * format with 2 bytes of length data?
63                  */
64                 c = 0x99;
65                 sha1_write(&sha_ctx, &c, sizeof(c));
66                 c = publickey->publickey->length >> 8;
67                 sha1_write(&sha_ctx, &c, sizeof(c));
68                 c = publickey->publickey->length & 0xFF;
69                 sha1_write(&sha_ctx, &c, sizeof(c));
70                 sha1_write(&sha_ctx, publickey->publickey->data,
71                         publickey->publickey->length);
72                 sha1_final(&sha_ctx);
73                 buff = sha1_read(&sha_ctx);
74
75                 assert(buff != NULL);
76                 
77                 for (keyid = 0, i = 12; i < 20; i++) {
78                         keyid <<= 8;
79                         keyid += buff[i];
80                 }
81
82                 break;
83         default:
84                 printf("Unknown key type: %d\n", publickey->publickey->data[0]);
85         }
86
87         return keyid;
88 }