char* hash_password_v1(const unsigned char* b0 , int b0len , const unsigned char* password , int psdlen) { unsigned char* dst = (unsigned char*)malloc(b0len + psdlen + 1); PurpleCipherContext *context; static gchar digest[41]; memset(dst , 0 , b0len + psdlen + 1); memcpy(dst , b0 , b0len); memcpy(dst + b0len , password , psdlen); /*SHA_CTX ctx;*/ /*SHA1_Init(&ctx);*/ /*SHA1_Update(&ctx , dst , b0len + psdlen );*/ /*SHA1_Final(tmp , &ctx);*/ /*free(dst);*/ /*res = hextostr(tmp , 20);*/ /*return res;*/ /* Hash the data in libpurple's way in SHA-1 */ context = purple_cipher_context_new_by_name("sha1", NULL); if (context == NULL) { purple_debug_error("fetion", "Could not find sha1 cipher\n"); g_return_val_if_reached(NULL); } purple_cipher_context_append(context, dst, b0len + psdlen); if (!purple_cipher_context_digest_to_str(context, sizeof(digest), digest, NULL)) { purple_debug_error("fetion", "Failed to get SHA-1 digest.\n"); g_return_val_if_reached(NULL); } purple_cipher_context_destroy(context); free(dst); return g_strdup(digest); }
char * jabber_calculate_data_hash(gconstpointer data, size_t len, const gchar *hash_algo) { PurpleCipherContext *context; static gchar digest[129]; /* 512 bits hex + \0 */ context = purple_cipher_context_new_by_name(hash_algo, NULL); if (context == NULL) { purple_debug_error("jabber", "Could not find %s cipher\n", hash_algo); g_return_val_if_reached(NULL); } /* Hash the data */ purple_cipher_context_append(context, data, len); if (!purple_cipher_context_digest_to_str(context, sizeof(digest), digest, NULL)) { purple_debug_error("jabber", "Failed to get digest for %s cipher.\n", hash_algo); g_return_val_if_reached(NULL); } purple_cipher_context_destroy(context); return g_strdup(digest); }
static int aim_encode_password_md5(const char *password, size_t password_len, const char *key, guint8 *digest) { PurpleCipherContext *context; context = purple_cipher_context_new_by_name("md5", NULL); purple_cipher_context_append(context, (const guchar *)key, strlen(key)); purple_cipher_context_append(context, (const guchar *)password, password_len); purple_cipher_context_append(context, (const guchar *)AIM_MD5_STRING, strlen(AIM_MD5_STRING)); purple_cipher_context_digest(context, 16, digest, NULL); purple_cipher_context_destroy(context); return 0; }
/** * @return A null-terminated base64 encoded version of the HMAC * calculated using the given key and data. */ static gchar *hmac_sha256(const char *key, const char *message) { PurpleCipherContext *context; guchar digest[32]; context = purple_cipher_context_new_by_name("hmac", NULL); purple_cipher_context_set_option(context, "hash", "sha256"); purple_cipher_context_set_key(context, (guchar *)key); purple_cipher_context_append(context, (guchar *)message, strlen(message)); purple_cipher_context_digest(context, sizeof(digest), digest, NULL); purple_cipher_context_destroy(context); return purple_base64_encode(digest, sizeof(digest)); }
static char * rps_create_key(const char *key, int key_len, const char *data, size_t data_len) { const guchar magic[] = "WS-SecureConversation"; const int magic_len = sizeof(magic) - 1; PurpleCipherContext *hmac; guchar hash1[20], hash2[20], hash3[20], hash4[20]; char *result; hmac = purple_cipher_context_new_by_name("hmac", NULL); purple_cipher_context_set_option(hmac, "hash", "sha1"); purple_cipher_context_set_key_with_len(hmac, (guchar *)key, key_len); purple_cipher_context_append(hmac, magic, magic_len); purple_cipher_context_append(hmac, (guchar *)data, data_len); purple_cipher_context_digest(hmac, sizeof(hash1), hash1, NULL); purple_cipher_context_reset(hmac, NULL); purple_cipher_context_set_option(hmac, "hash", "sha1"); purple_cipher_context_set_key_with_len(hmac, (guchar *)key, key_len); purple_cipher_context_append(hmac, hash1, 20); purple_cipher_context_append(hmac, magic, magic_len); purple_cipher_context_append(hmac, (guchar *)data, data_len); purple_cipher_context_digest(hmac, sizeof(hash2), hash2, NULL); purple_cipher_context_reset(hmac, NULL); purple_cipher_context_set_option(hmac, "hash", "sha1"); purple_cipher_context_set_key_with_len(hmac, (guchar *)key, key_len); purple_cipher_context_append(hmac, hash1, 20); purple_cipher_context_digest(hmac, sizeof(hash3), hash3, NULL); purple_cipher_context_reset(hmac, NULL); purple_cipher_context_set_option(hmac, "hash", "sha1"); purple_cipher_context_set_key_with_len(hmac, (guchar *)key, key_len); purple_cipher_context_append(hmac, hash3, sizeof(hash3)); purple_cipher_context_append(hmac, magic, magic_len); purple_cipher_context_append(hmac, (guchar *)data, data_len); purple_cipher_context_digest(hmac, sizeof(hash4), hash4, NULL); purple_cipher_context_destroy(hmac); result = g_malloc(24); memcpy(result, hash2, sizeof(hash2)); memcpy(result + sizeof(hash2), hash4, 4); return result; }
static void hashSha1(char* input,char* digest) //based on code from purple_util_get_image_filename in the pidgin 2.2.0 source { PurpleCipherContext *context; context = purple_cipher_context_new_by_name("sha1", NULL); if (context == NULL) { purple_debug_error("util", "Could not find sha1 cipher\n"); g_return_val_if_reached(NULL); } purple_cipher_context_append(context, input, strlen(input)); if (!purple_cipher_context_digest_to_str(context, 41, digest, NULL)) { purple_debug_error("util", "Failed to get SHA-1 digest.\n"); g_return_val_if_reached(NULL); } purple_cipher_context_destroy(context); digest[40]=0; }
static char * des3_cbc(const char *key, const char *iv, const char *data, int len, gboolean decrypt) { PurpleCipherContext *des3; char *out; size_t outlen; des3 = purple_cipher_context_new_by_name("des3", NULL); purple_cipher_context_set_key(des3, (guchar *)key); purple_cipher_context_set_batch_mode(des3, PURPLE_CIPHER_BATCH_MODE_CBC); purple_cipher_context_set_iv(des3, (guchar *)iv, 8); out = g_malloc(len); if (decrypt) purple_cipher_context_decrypt(des3, (guchar *)data, len, (guchar *)out, &outlen); else purple_cipher_context_encrypt(des3, (guchar *)data, len, (guchar *)out, &outlen); purple_cipher_context_destroy(des3); return out; }
/* The same as purple_util_get_image_checksum, but guaranteed to remain SHA1 */ char * jabber_calculate_data_sha1sum(gconstpointer data, size_t len) { PurpleCipherContext *context; static gchar digest[41]; context = purple_cipher_context_new_by_name("sha1", NULL); if (context == NULL) { purple_debug_error("jabber", "Could not find sha1 cipher\n"); g_return_val_if_reached(NULL); } /* Hash the data */ purple_cipher_context_append(context, data, len); if (!purple_cipher_context_digest_to_str(context, sizeof(digest), digest, NULL)) { purple_debug_error("jabber", "Failed to get SHA-1 digest.\n"); g_return_val_if_reached(NULL); } purple_cipher_context_destroy(context); return g_strdup(digest); }
void msn_nexus_update_token(MsnNexus *nexus, int id, GSourceFunc cb, gpointer data) { MsnSession *session = nexus->session; MsnNexusUpdateData *ud; MsnNexusUpdateCallback *update; PurpleCipherContext *sha1; PurpleCipherContext *hmac; char *key; guchar digest[20]; struct tm *tm; time_t now; char *now_str; char *timestamp; char *timestamp_b64; char *domain; char *domain_b64; char *signedinfo; gint32 nonce[6]; int i; char *nonce_b64; char *signature_b64; guchar signature[20]; char *request; MsnSoapMessage *soap; update = g_new0(MsnNexusUpdateCallback, 1); update->cb = cb; update->data = data; if (nexus->tokens[id].updates != NULL) { /* Update already in progress. Just add to list and return. */ purple_debug_info("msn", "Ticket update for user '%s' on domain '%s' in progress. Adding request to queue.\n", purple_account_get_username(session->account), ticket_domains[id][SSO_VALID_TICKET_DOMAIN]); nexus->tokens[id].updates = g_slist_prepend(nexus->tokens[id].updates, update); return; } else { purple_debug_info("msn", "Updating ticket for user '%s' on domain '%s'\n", purple_account_get_username(session->account), ticket_domains[id][SSO_VALID_TICKET_DOMAIN]); nexus->tokens[id].updates = g_slist_prepend(nexus->tokens[id].updates, update); } ud = g_new0(MsnNexusUpdateData, 1); ud->nexus = nexus; ud->id = id; sha1 = purple_cipher_context_new_by_name("sha1", NULL); domain = g_strdup_printf(MSN_SSO_RST_TEMPLATE, id, ticket_domains[id][SSO_VALID_TICKET_DOMAIN], ticket_domains[id][SSO_VALID_TICKET_POLICY] != NULL ? ticket_domains[id][SSO_VALID_TICKET_POLICY] : nexus->policy); purple_cipher_context_append(sha1, (guchar *)domain, strlen(domain)); purple_cipher_context_digest(sha1, 20, digest, NULL); domain_b64 = purple_base64_encode(digest, 20); now = time(NULL); tm = gmtime(&now); now_str = g_strdup(purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", tm)); now += 5*60; tm = gmtime(&now); timestamp = g_strdup_printf(MSN_SSO_TIMESTAMP_TEMPLATE, now_str, purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", tm)); purple_cipher_context_reset(sha1, NULL); purple_cipher_context_append(sha1, (guchar *)timestamp, strlen(timestamp)); purple_cipher_context_digest(sha1, 20, digest, NULL); timestamp_b64 = purple_base64_encode(digest, 20); g_free(now_str); purple_cipher_context_destroy(sha1); signedinfo = g_strdup_printf(MSN_SSO_SIGNEDINFO_TEMPLATE, id, domain_b64, timestamp_b64); for (i = 0; i < 6; i++) nonce[i] = rand(); nonce_b64 = purple_base64_encode((guchar *)&nonce, sizeof(nonce)); key = rps_create_key(nexus->secret, 24, (char *)nonce, sizeof(nonce)); hmac = purple_cipher_context_new_by_name("hmac", NULL); purple_cipher_context_set_option(hmac, "hash", "sha1"); purple_cipher_context_set_key_with_len(hmac, (guchar *)key, 24); purple_cipher_context_append(hmac, (guchar *)signedinfo, strlen(signedinfo)); purple_cipher_context_digest(hmac, 20, signature, NULL); purple_cipher_context_destroy(hmac); signature_b64 = purple_base64_encode(signature, 20); request = g_strdup_printf(MSN_SSO_TOKEN_UPDATE_TEMPLATE, nexus->cipher, nonce_b64, timestamp, signedinfo, signature_b64, domain); g_free(nonce_b64); g_free(domain_b64); g_free(timestamp_b64); g_free(timestamp); g_free(key); g_free(signature_b64); g_free(signedinfo); g_free(domain); soap = msn_soap_message_new(NULL, xmlnode_from_str(request, -1)); g_free(request); msn_soap_message_send(session, soap, MSN_SSO_SERVER, SSO_POST_URL, TRUE, nexus_got_update_cb, ud); }
static char * msn_rps_encrypt(MsnNexus *nexus) { char usr_key_base[MSN_USER_KEY_SIZE], *usr_key; const char magic1[] = "SESSION KEY HASH"; const char magic2[] = "SESSION KEY ENCRYPTION"; PurpleCipherContext *hmac; size_t len; guchar *hash; char *key1, *key2, *key3; gsize key1_len; const char *iv; char *nonce_fixed; char *cipher; char *response; usr_key = &usr_key_base[0]; /* Header */ msn_push32le(usr_key, 28); /* Header size */ msn_push32le(usr_key, CRYPT_MODE_CBC); /* Crypt mode */ msn_push32le(usr_key, CIPHER_TRIPLE_DES); /* Cipher type */ msn_push32le(usr_key, HASH_SHA1); /* Hash type */ msn_push32le(usr_key, 8); /* IV size */ msn_push32le(usr_key, 20); /* Hash size */ msn_push32le(usr_key, 72); /* Cipher size */ /* Data */ iv = usr_key; msn_push32le(usr_key, rand()); msn_push32le(usr_key, rand()); hash = (guchar *)usr_key; usr_key += 20; /* Remaining is cipher data */ key1 = (char *)purple_base64_decode((const char *)nexus->tokens[MSN_AUTH_MESSENGER].secret, &key1_len); key2 = rps_create_key(key1, key1_len, magic1, sizeof(magic1) - 1); key3 = rps_create_key(key1, key1_len, magic2, sizeof(magic2) - 1); len = strlen(nexus->nonce); hmac = purple_cipher_context_new_by_name("hmac", NULL); purple_cipher_context_set_option(hmac, "hash", "sha1"); purple_cipher_context_set_key_with_len(hmac, (guchar *)key2, 24); purple_cipher_context_append(hmac, (guchar *)nexus->nonce, len); purple_cipher_context_digest(hmac, 20, hash, NULL); purple_cipher_context_destroy(hmac); /* We need to pad this to 72 bytes, apparently */ nonce_fixed = g_malloc(len + 8); memcpy(nonce_fixed, nexus->nonce, len); memset(nonce_fixed + len, 0x08, 8); cipher = des3_cbc(key3, iv, nonce_fixed, len + 8, FALSE); g_free(nonce_fixed); memcpy(usr_key, cipher, 72); g_free(key1); g_free(key2); g_free(key3); g_free(cipher); response = purple_base64_encode((guchar *)usr_key_base, MSN_USER_KEY_SIZE); return response; }
MsnObject * msn_object_new_from_image (PecanBuffer *image, const char *location, const char *creator, MsnObjectType type) { MsnObject *msnobj; PurpleCipherContext *ctx; char *buf; char *base64; unsigned char digest[20]; msnobj = NULL; if (!image) return msnobj; /* New object */ msnobj = msn_object_new (); msn_object_set_local (msnobj); msn_object_set_type (msnobj, type); msn_object_set_location (msnobj, location); msn_object_set_creator (msnobj, creator); msn_object_set_image (msnobj, image); /* Compute the SHA1D field. */ memset (digest, 0, sizeof (digest)); ctx = purple_cipher_context_new_by_name ("sha1", NULL); purple_cipher_context_append (ctx, (const gpointer) image->data, image->len); purple_cipher_context_digest (ctx, sizeof (digest), digest, NULL); base64 = purple_base64_encode (digest, sizeof (digest)); msn_object_set_sha1d (msnobj, base64); g_free (base64); msn_object_set_size (msnobj, image->len); /* Compute the SHA1C field. */ buf = g_strdup_printf ("Creator%sSize%dType%dLocation%sFriendly%sSHA1D%s", msn_object_get_creator (msnobj), msn_object_get_size (msnobj), msn_object_get_type (msnobj), msn_object_get_location (msnobj), msn_object_get_friendly (msnobj), msn_object_get_sha1d (msnobj)); memset (digest, 0, sizeof (digest)); purple_cipher_context_reset (ctx, NULL); purple_cipher_context_append (ctx, (const guchar *) buf, strlen (buf)); purple_cipher_context_digest (ctx, sizeof (digest), digest, NULL); purple_cipher_context_destroy (ctx); g_free (buf); base64 = purple_base64_encode (digest, sizeof (digest)); msn_object_set_sha1c (msnobj, base64); g_free (base64); return msnobj; }