static void test_sha256hash(gchar *data, gchar *digest) { PurpleHash *hash = NULL; gchar cdigest[65]; gboolean ret = FALSE; hash = purple_sha256_hash_new(); if(data) { purple_hash_append(hash, (guchar *)data, strlen(data)); } else { gint j; guchar buff[1000]; memset(buff, 'a', 1000); for(j = 0; j < 1000; j++) purple_hash_append(hash, buff, 1000); } ret = purple_hash_digest_to_str(hash, cdigest, sizeof(cdigest)); g_assert(ret); g_assert_cmpstr(digest, ==, cdigest); }
char * skypeweb_hmac_sha256(char *input) { PurpleHash *hash; const guchar productKey[] = SKYPEWEB_LOCKANDKEY_SECRET; const guchar productID[] = SKYPEWEB_LOCKANDKEY_APPID; const char hexChars[] = "0123456789abcdef"; char buf[BUFSIZE]; unsigned char sha256Hash[32]; unsigned char *newHash; unsigned int *sha256Parts; unsigned int *chlStringParts; unsigned int newHashParts[5]; gchar *output; long long nHigh = 0, nLow = 0; int len; int i; hash = purple_sha256_hash_new(); purple_hash_append(hash, (guchar *)input, strlen(input)); purple_hash_append(hash, productKey, sizeof(productKey) - 1); purple_hash_digest(hash, (guchar *)sha256Hash, sizeof(sha256Hash)); purple_hash_destroy(hash); /* Split it into four integers */ sha256Parts = (unsigned int *)sha256Hash; for (i = 0; i < 4; i++) { /* adjust endianess */ sha256Parts[i] = GUINT_TO_LE(sha256Parts[i]); /* & each integer with 0x7FFFFFFF */ /* and save one unmodified array for later */ newHashParts[i] = sha256Parts[i]; sha256Parts[i] &= 0x7FFFFFFF; } /* make a new string and pad with '0' to length that's a multiple of 8 */ snprintf(buf, BUFSIZE - 5, "%s%s", input, productID); len = strlen(buf); if ((len % 8) != 0) { int fix = 8 - (len % 8); memset(&buf[len], '0', fix); buf[len + fix] = '\0'; len += fix; } /* split into integers */ chlStringParts = (unsigned int *)buf; /* this is magic */ for (i = 0; i < (len / 4); i += 2) { long long temp; chlStringParts[i] = GUINT_TO_LE(chlStringParts[i]); chlStringParts[i + 1] = GUINT_TO_LE(chlStringParts[i + 1]); temp = (0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF; temp = (sha256Parts[0] * (temp + nLow) + sha256Parts[1]) % 0x7FFFFFFF; nHigh += temp; temp = ((long long)chlStringParts[i + 1] + temp) % 0x7FFFFFFF; nLow = (sha256Parts[2] * temp + sha256Parts[3]) % 0x7FFFFFFF; nHigh += nLow; } nLow = (nLow + sha256Parts[1]) % 0x7FFFFFFF; nHigh = (nHigh + sha256Parts[3]) % 0x7FFFFFFF; newHashParts[0] ^= nLow; newHashParts[1] ^= nHigh; newHashParts[2] ^= nLow; newHashParts[3] ^= nHigh; /* adjust endianness */ for(i = 0; i < 4; i++) newHashParts[i] = GUINT_TO_LE(newHashParts[i]); /* make a string of the parts */ newHash = (unsigned char *)newHashParts; /* convert to hexadecimal */ output = g_new0(gchar, 33); for (i = 0; i < 16; i++) { output[i * 2] = hexChars[(newHash[i] >> 4) & 0xF]; output[(i * 2) + 1] = hexChars[newHash[i] & 0xF]; } output[32] = '\0'; return output; }
static void cipher_test_pbkdf2(void) { PurpleCipher *cipher; PurpleHash *hash; int i = 0; gboolean fail = FALSE; purple_debug_info("cipher-test", "Running PBKDF2 tests\n"); while (!fail && pbkdf2_tests[i].answer) { pbkdf2_test *test = &pbkdf2_tests[i]; gchar digest[2 * 32 + 1 + 10]; gchar *digest_nss = NULL; gboolean ret, skip_nss = FALSE; i++; purple_debug_info("cipher-test", "Test %02d:\n", i); purple_debug_info("cipher-test", "\tTesting '%s' with salt:'%s' hash:%s iter_count:%d \n", test->passphrase, test->salt, test->hash, test->iter_count); if (!strcmp(test->hash, "sha1")) hash = purple_sha1_hash_new(); else if (!strcmp(test->hash, "sha256")) hash = purple_sha256_hash_new(); else hash = NULL; cipher = purple_pbkdf2_cipher_new(hash); g_object_set(G_OBJECT(cipher), "iter_count", GUINT_TO_POINTER(test->iter_count), NULL); g_object_set(G_OBJECT(cipher), "out_len", GUINT_TO_POINTER(test->out_len), NULL); purple_cipher_set_salt(cipher, (const guchar*)test->salt, test->salt ? strlen(test->salt): 0); purple_cipher_set_key(cipher, (const guchar*)test->passphrase, strlen(test->passphrase)); ret = purple_cipher_digest_to_str(cipher, digest, sizeof(digest)); purple_cipher_reset(cipher); if (!ret) { purple_debug_info("cipher-test", "\tfailed\n"); fail = TRUE; g_object_unref(cipher); g_object_unref(hash); continue; } if (g_strcmp0(test->hash, "sha1") != 0) skip_nss = TRUE; if (test->out_len != 16 && test->out_len != 32) skip_nss = TRUE; #ifdef HAVE_NSS if (!skip_nss) { digest_nss = cipher_pbkdf2_nss_sha1(test->passphrase, test->salt, test->iter_count, test->out_len); } #else skip_nss = TRUE; #endif purple_debug_info("cipher-test", "\tGot: %s\n", digest); if (digest_nss) purple_debug_info("cipher-test", "\tGot from NSS: %s\n", digest_nss); purple_debug_info("cipher-test", "\tWanted: %s\n", test->answer); if (g_strcmp0(digest, test->answer) == 0 && (skip_nss || g_strcmp0(digest, digest_nss) == 0)) { purple_debug_info("cipher-test", "\tTest OK\n"); } else { purple_debug_info("cipher-test", "\twrong answer\n"); fail = TRUE; } g_object_unref(cipher); g_object_unref(hash); } if (fail) purple_debug_info("cipher-test", "PBKDF2 tests FAILED\n\n"); else purple_debug_info("cipher-test", "PBKDF2 tests completed successfully\n\n"); }