+ } else {
+ fatal("key_fingerprint_raw: blob is null");
+ }
+ return retval;
+}
+
+static char *
+key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len)
+{
+ char *retval;
+ int i;
+
+ retval = xmalloc(dgst_raw_len * 3 + 1);
+ retval[0] = '\0';
+ for (i = 0; i < dgst_raw_len; i++) {
+ char hex[4];
+ snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
+ strlcat(retval, hex, dgst_raw_len * 3 + 1);
+ }
+
+ /* Remove the trailing ':' character */
+ retval[(dgst_raw_len * 3) - 1] = '\0';
+ return retval;
+}
+
+static char *
+key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len)
+{
+ char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
+ char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
+ 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
+ u_int i, j = 0, rounds, seed = 1;
+ char *retval;
+
+ rounds = (dgst_raw_len / 2) + 1;
+ retval = xmalloc(sizeof(char) * (rounds*6));
+ retval[j++] = 'x';
+ for (i = 0; i < rounds; i++) {
+ u_int idx0, idx1, idx2, idx3, idx4;
+ if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
+ idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
+ seed) % 6;
+ idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
+ idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
+ (seed / 6)) % 6;
+ retval[j++] = vowels[idx0];
+ retval[j++] = consonants[idx1];
+ retval[j++] = vowels[idx2];
+ if ((i + 1) < rounds) {
+ idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
+ idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
+ retval[j++] = consonants[idx3];
+ retval[j++] = '-';
+ retval[j++] = consonants[idx4];
+ seed = ((seed * 5) +
+ ((((u_int)(dgst_raw[2 * i])) * 7) +
+ ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
+ }
+ } else {
+ idx0 = seed % 6;
+ idx1 = 16;
+ idx2 = seed / 6;
+ retval[j++] = vowels[idx0];
+ retval[j++] = consonants[idx1];
+ retval[j++] = vowels[idx2];
+ }
+ }
+ retval[j++] = 'x';
+ retval[j++] = '\0';
+ return retval;
+}
+
+char *
+key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
+{
+ char *retval = NULL;
+ u_char *dgst_raw;
+ u_int dgst_raw_len;
+
+ dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len);
+ if (!dgst_raw)
+ fatal("key_fingerprint: null from key_fingerprint_raw()");
+ switch (dgst_rep) {
+ case SSH_FP_HEX:
+ retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);
+ break;
+ case SSH_FP_BUBBLEBABBLE:
+ retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
+ break;
+ default:
+ fatal("key_fingerprint_ex: bad digest representation %d",
+ dgst_rep);
+ break;