bubblebabble patch

Carsten Raskgaard cara at int.tele.dk
Mon Mar 5 02:42:40 EST 2001


Hi,

Here is a patch that adds the possibility of displaying key fingerprints
in the bubblebabble format used by ssh.com ssh implementations.

I hope it makes its way into the source.

--- ./openssh-2.5.1/key_original.h	Sun Mar  4 00:47:55 2001
+++ ./openssh-2.5.1/key.h	Sun Mar  4 00:57:57 2001
@@ -36,6 +36,17 @@
 	KEY_DSA,
 	KEY_UNSPEC
 };
+
+enum digest_type {
+	DIGEST_TYPE_SHA1,
+	DIGEST_TYPE_MD5
+};
+
+enum digest_representation {
+	DIGEST_REPRESENTATION_HEX,
+	DIGEST_REPRESENTATION_BUBBLEBABBLE
+};
+
 struct Key {
 	int	type;
 	RSA	*rsa;
@@ -46,6 +57,7 @@
 Key	*key_new_private(int type);
 void	key_free(Key *k);
 int	key_equal(Key *a, Key *b);
+char	*key_fingerprint_ex(Key *k, enum digest_type dgst_type, enum
digest_representation dgst_representation);
 char	*key_fingerprint(Key *k);
 char	*key_type(Key *k);
 int	key_write(Key *key, FILE *f);
--- ./openssh-2.5.1/key_original.c	Sun Mar  4 00:48:41 2001
+++ ./openssh-2.5.1/key.c	Sun Mar  4 01:07:21 2001
@@ -153,6 +153,179 @@
 	return 0;
 }
 
+u_char*
+key_fingerprint_raw(Key *k, enum digest_type dgst_type, size_t
*dgst_raw_length)
+{
+        u_char *blob = NULL;
+	u_char* retval = NULL;
+        int len = 0;
+        int nlen, elen;
+
+        switch (k->type) {
+        case KEY_RSA1:
+                nlen = BN_num_bytes(k->rsa->n);
+                elen = BN_num_bytes(k->rsa->e);
+                len = nlen + elen;
+                blob = xmalloc(len);
+                BN_bn2bin(k->rsa->n, blob);
+                BN_bn2bin(k->rsa->e, blob + nlen);
+                break;
+        case KEY_DSA:
+        case KEY_RSA:
+                key_to_blob(k, &blob, &len);
+                break;
+        case KEY_UNSPEC:
+                fatal("key_fingerprint_raw: bad key type %d",k->type);
+                break;
+        default:
+                fatal("key_fingerprint_raw: bad key type %d", k->type);
+                break;
+        }
+
+        if (blob != NULL) {
+                EVP_MD *md = NULL;
+                EVP_MD_CTX ctx;
+
+		retval = xmalloc(EVP_MAX_MD_SIZE);
+
+                switch (dgst_type) {
+                        case DIGEST_TYPE_MD5:
+                                md = EVP_md5();
+                                break;
+                        case DIGEST_TYPE_SHA1:
+                                md = EVP_sha1();
+                                break;
+                        default:
+                                fatal("key_fingerprint_raw: bad digest
type %d", dgst_type);
+		}
+
+                EVP_DigestInit(&ctx, md);
+                EVP_DigestUpdate(&ctx, blob, len);
+                EVP_DigestFinal(&ctx, retval, NULL);
+
+		*dgst_raw_length = md->md_size;
+
+                memset(blob, 0, len);
+                xfree(blob);
+        } else
+		fatal("key_fingerprint_raw: blob is null");
+
+        return retval;
+}
+
+char*
+key_fingerprint_hex(u_char* dgst_raw, size_t dgst_raw_len) 
+{
+	char *retval;
+	int i;
+
+	retval = xmalloc(dgst_raw_len*3);
+	
+	for(i = 0; i < dgst_raw_len; i++) {
+
+		char hex[4];
+
+		snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
+		strcat(retval, hex);
+	}
+
+	retval[(dgst_raw_len * 3) - 1] = '\0';
+	return retval;
+}
+
+char*
+key_fingerprint_bubblebabble(u_char* dgst_raw, size_t 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' };
+  	unsigned int rounds, idx, retval_idx, seed;
+  	char *retval;
+
+  	rounds = (dgst_raw_len / 2) + 1;
+
+  	retval = xmalloc(sizeof(char)*(rounds*6));
+
+  	seed = 1;
+
+  	retval_idx = 0;
+
+  	retval[retval_idx++] = 'x';
+
+	for (idx=0;idx<rounds;idx++) {
+
+		unsigned int idx0, idx1, idx2, idx3, idx4;
+
+		if ((idx + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
+
+			idx0 = (((((unsigned int)(dgst_raw[2*idx])) >> 6) & 3) + seed) % 6;
+			idx1 = (((unsigned int)(dgst_raw[2*idx])) >> 2) & 15;
+			idx2 = ((((unsigned int)(dgst_raw[2*idx])) & 3) + (seed / 6)) % 6;
+
+			retval[retval_idx++] = vowels[idx0];
+			retval[retval_idx++] = consonants[idx1];
+			retval[retval_idx++] = vowels[idx2];
+
+			if ((idx + 1) < rounds) {
+
+				idx3 = (((unsigned int)(dgst_raw[(2*idx) + 1])) >> 4) & 15;
+				idx4 = (((unsigned int)(dgst_raw[(2*idx) + 1]))) & 15;
+
+				retval[retval_idx++] = consonants[idx3];
+				retval[retval_idx++] = '-';
+				retval[retval_idx++] = consonants[idx4];
+
+				seed = ((seed * 5) + ((((unsigned int)(dgst_raw[2*idx])) * 7) +
((unsigned int)(dgst_raw[(2*idx) + 1])))) % 36;
+		        }
+		} else {
+
+			idx0 = seed % 6;
+			idx1 = 16;
+			idx2 = seed / 6;
+
+			retval[retval_idx++] = vowels[idx0];
+			retval[retval_idx++] = consonants[idx1];
+			retval[retval_idx++] = vowels[idx2];
+
+		}
+	}
+
+	retval[retval_idx++] = 'x';
+	retval[retval_idx++] = '\0';
+
+	return retval;
+}
+
+char*
+key_fingerprint_ex(Key *k, enum digest_type dgst_type, enum
digest_representation dgst_representation)
+{
+	char *retval = NULL; 
+	u_char *dgst_raw;
+	size_t dgst_raw_len; 
+	
+	dgst_raw = key_fingerprint_raw(k,dgst_type,&dgst_raw_len);
+
+	if (!dgst_raw)
+		fatal("key_fingerprint_ex: null value returned from
key_fingerprint_raw()");
+
+	switch(dgst_representation) {
+		case DIGEST_REPRESENTATION_HEX:
+			retval = key_fingerprint_hex(dgst_raw,dgst_raw_len);
+			break;
+
+		case DIGEST_REPRESENTATION_BUBBLEBABBLE:
+			retval = key_fingerprint_bubblebabble(dgst_raw,dgst_raw_len);
+			break;
+		default:
+			fatal("key_fingerprint_ex: bad digest representation
%d",dgst_representation);
+			break;
+	}
+
+        memset(dgst_raw, 0, dgst_raw_len);
+        xfree(dgst_raw);
+	
+	return retval;
+}
+
 /*
  * Generate key fingerprint in ascii format.
  * Based on ideas and code from Bjoern Groenvall <bg at sics.se>
--- ./openssh-2.5.1/ssh-keygen_original.c	Sun Mar  4 00:49:31 2001
+++ ./openssh-2.5.1/ssh-keygen.c	Sun Mar  4 00:52:56 2001
@@ -346,9 +346,22 @@
 			debug("try_load_public_key KEY_UNSPEC failed");
 	}
 	if (success) {
+
+		char *digest_sha1, *digest_bubblebabble;
+
+		digest_sha1 =
key_fingerprint_ex(public,DIGEST_TYPE_SHA1,DIGEST_REPRESENTATION_HEX);
+		digest_bubblebabble =
key_fingerprint_ex(public,DIGEST_TYPE_SHA1,DIGEST_REPRESENTATION_BUBBLEBABBLE);
+
 		printf("%d %s %s\n", key_size(public), key_fingerprint(public),
comment);
+		printf("Alternative digests:\n");
+		printf(" sha1         : %s\n",digest_sha1);
+		printf(" bubblebabble : %s\n",digest_bubblebabble);
+
 		key_free(public);
 		xfree(comment);
+		xfree(digest_sha1);
+		xfree(digest_bubblebabble);
+
 		exit(0);
 	}
 

-- 
Carsten Raskgaard





More information about the openssh-unix-dev mailing list