SILC_LOG_DEBUG(("Registering new hash function `%s'", hash->name));
+ /* Check for existing */
+ if (silc_hash_list) {
+ SilcHashObject *entry;
+ silc_dlist_start(silc_hash_list);
+ while ((entry = silc_dlist_get(silc_hash_list)) != SILC_LIST_END) {
+ if (!strcmp(entry->name, hash->name))
+ return FALSE;
+ }
+ }
+
new = silc_calloc(1, sizeof(*new));
new->name = strdup(hash->name);
new->hash_len = hash->hash_len;
/* Returns the length of the hash digest. */
-uint32 silc_hash_len(SilcHash hash)
+SilcUInt32 silc_hash_len(SilcHash hash)
{
return hash->hash->hash_len;
}
memcpy(list + len, ",", 1);
len++;
}
+ list[len - 1] = 0;
}
- list[len - 1] = 0;
-
return list;
}
/* Creates the hash value and returns it to the return_hash argument. */
void silc_hash_make(SilcHash hash, const unsigned char *data,
- uint32 len, unsigned char *return_hash)
+ SilcUInt32 len, unsigned char *return_hash)
{
hash->hash->init(hash->context);
hash->hash->update(hash->context, (unsigned char *)data, len);
caller. */
char *silc_hash_fingerprint(SilcHash hash, const unsigned char *data,
- uint32 data_len)
+ SilcUInt32 data_len)
{
- char fingerprint[64], *cp;
+ SilcHash new_hash = NULL;
unsigned char h[32];
- int i;
+ char *ret;
- if (!hash)
- silc_hash_alloc("sha1", &hash);
+ if (!hash) {
+ silc_hash_alloc("sha1", &new_hash);
+ hash = new_hash;
+ }
silc_hash_make(hash, data, data_len, h);
-
- memset(fingerprint, 0, sizeof(fingerprint));
- cp = fingerprint;
- for (i = 0; i < hash->hash->hash_len; i++) {
- snprintf(cp, sizeof(fingerprint), "%02X", h[i]);
- cp += 2;
+ ret = silc_fingerprint(h, hash->hash->hash_len);
+
+ if (new_hash != NULL)
+ silc_hash_free(new_hash);
+ return ret;
+}
+
+static const char vo[]= "aeiouy";
+static const char co[]= "bcdfghklmnprstvzx";
+
+/* Creates a babbleprint (Bubble Babble Encoding, developed by Antti
+ Huima (draft-huima-babble-01.txt)), by first computing real fingerprint
+ using `hash' or if NULL, then using SHA1, and then encoding the
+ fingerprint to the babbleprint. */
+
+char *silc_hash_babbleprint(SilcHash hash, const unsigned char *data,
+ SilcUInt32 data_len)
+{
+ SilcHash new_hash = NULL;
+ char *babbleprint;
+ unsigned char hval[32];
+ unsigned int a, b, c, d, e, check;
+ int i, k, out_len;
+
+ if (!hash) {
+ silc_hash_alloc("sha1", &new_hash);
+ hash = new_hash;
+ }
+
+ /* Take fingerprint */
+ silc_hash_make(hash, data, data_len, hval);
+
+ /* Encode babbleprint */
+ out_len = (((hash->hash->hash_len + 1) / 2) + 1) * 6;
+ babbleprint = silc_calloc(out_len, sizeof(*babbleprint));
+ babbleprint[0] = co[16];
+
+ check = 1;
+ for (i = 0, k = 1; i < hash->hash->hash_len - 1; i += 2, k += 6) {
+ a = (((hval[i] >> 6) & 3) + check) % 6;
+ b = (hval[i] >> 2) & 15;
+ c = ((hval[i] & 3) + (check / 6)) % 6;
+ d = (hval[i + 1] >> 4) & 15;
+ e = hval[i + 1] & 15;
+
+ check = ((check * 5) + (hval[i] * 7) + hval[i + 1]) % 36;
- if ((i + 1) % 2 == 0)
- snprintf(cp++, sizeof(fingerprint), " ");
+ babbleprint[k + 0] = vo[a];
+ babbleprint[k + 1] = co[b];
+ babbleprint[k + 2] = vo[c];
+ babbleprint[k + 3] = co[d];
+ babbleprint[k + 4] = '-';
+ babbleprint[k + 5] = co[e];
+ }
- if ((i + 1) % 10 == 0)
- snprintf(cp++, sizeof(fingerprint), " ");
+ if ((hash->hash->hash_len % 2) != 0) {
+ a = (((hval[i] >> 6) & 3) + check) % 6;
+ b = (hval[i] >> 2) & 15;
+ c = ((hval[i] & 3) + (check / 6)) % 6;
+ babbleprint[k + 0] = vo[a];
+ babbleprint[k + 1] = co[b];
+ babbleprint[k + 2] = vo[c];
+ } else {
+ a = check % 6;
+ b = 16;
+ c = check / 6;
+ babbleprint[k + 0] = vo[a];
+ babbleprint[k + 1] = co[b];
+ babbleprint[k + 2] = vo[c];
}
- i--;
- if ((i + 1) % 2 == 0)
- cp[-2] = 0;
- if ((i + 1) % 10 == 0)
- cp[-1] = 0;
-
- return strdup(fingerprint);
+ babbleprint[k + 3] = co[16];
+
+ if (new_hash != NULL)
+ silc_hash_free(new_hash);
+ return babbleprint;
}