/* * Generate a bignum of a specified length, with the given * high and low 8 bits. "High" is merged into the high 8 bits of the * number. For example, set it to 0x80 to ensure that the number is * exactly "bits" bits long (i.e. 2^(bits-1) <= bn < 2^bits). * "Low" is merged into the low 8 bits. For example, set it to * 1 to ensure that you generate an odd number. * * The bignum is generated using the given seed string. The * technique is from David Kravitz (of the NSA)'s "kosherizer". * The string is hashed, and that (with the low bit forced to 1) * is used for the low 160 bits of the number. Then the string, * considered as a big-endian array of bytes, is incremented * and the incremented value is hashed to produce the next most * significant 160 bits, and so on. The increment is performed * modulo the size of the seed string. * * The most significant *two* bits are forced to 1, the first to * ensure that the number is long enough, and the second just to * place the prime in the high half of the range to make breaking * it slightly more difficult, since it makes essentially no * difference to the use of the number. */ static int genRandBn(struct BigNum *bn, unsigned bits, unsigned char high, unsigned char low, unsigned char *seed, unsigned len) { unsigned char buf[SHA_DIGESTSIZE]; unsigned bytes; unsigned l = 0; /* Current position */ unsigned i; struct SHAContext sha; bnSetQ(bn, 0); bytes = (bits+7) / 8; /* Number of bytes to use */ shaInit(&sha); shaUpdate(&sha, seed, len); shaFinal(&sha, buf); buf[SHA_DIGESTSIZE-1] |= low; while (bytes > SHA_DIGESTSIZE) { bytes -= SHA_DIGESTSIZE; /* Merge in low half of high bits, if necessary */ if (bytes == 1 && (bits & 7)) buf[0] |= high << (bits & 7); if (bnInsertBigBytes(bn, buf, l, SHA_DIGESTSIZE) < 0) return -1; l += SHA_DIGESTSIZE; /* Increment the seed, ignoring carry out. */ i = len; while (i--) { if (++seed[i] & 255) break; /* Didn't wrap; done */ } shaInit(&sha); shaUpdate(&sha, seed, len); shaFinal(&sha, buf); } /* Do the final "bytes"-long section, using the tail bytes in buf */ /* Mask off excess high bits */ buf[SHA_DIGESTSIZE-bytes] &= 255 >> (-bits & 7); /* Merge in specified high bits */ buf[SHA_DIGESTSIZE-bytes] |= high >> (-bits & 7); if (bytes > 1 && (bits & 7)) buf[SHA_DIGESTSIZE-bytes+1] |= high << (bits & 7); /* Merge in the appropriate bytes of the buffer */ if (bnInsertBigBytes(bn, buf+SHA_DIGESTSIZE-bytes, l, bytes) < 0) return -1; return 0; }
void msn_user_set_buddy_icon(MsnUser *user, const char *filename) { struct stat st; FILE *fp; MsnObject *msnobj = msn_user_get_object(user); g_return_if_fail(user != NULL); if (filename == NULL || g_stat(filename, &st) == -1) { msn_user_set_object(user, NULL); } else if ((fp = g_fopen(filename, "rb")) != NULL) { unsigned char *buf; SHA_CTX ctx; gsize len; char *base64; unsigned char digest[20]; if (msnobj == NULL) { msnobj = msn_object_new(TRUE); msn_object_set_local(msnobj); msn_object_set_type(msnobj, MSN_OBJECT_USERTILE); msn_object_set_location(msnobj, "TFR2C2.tmp"); msn_object_set_creator(msnobj, msn_user_get_passport(user)); msn_user_set_object(user, msnobj); } msn_object_set_real_location(msnobj, filename); buf = g_malloc(st.st_size); len = fread(buf, 1, st.st_size, fp); fclose(fp); /* Compute the SHA1D field. */ memset(digest, 0, sizeof(digest)); shaInit(&ctx); shaUpdate(&ctx, buf, st.st_size); shaFinal(&ctx, digest); g_free(buf); base64 = gaim_base64_encode(digest, sizeof(digest)); msn_object_set_sha1d(msnobj, base64); g_free(base64); msn_object_set_size(msnobj, st.st_size); /* 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)); shaInit(&ctx); shaUpdate(&ctx, buf, strlen(buf)); shaFinal(&ctx, digest); g_free(buf); base64 = gaim_base64_encode(digest, sizeof(digest)); msn_object_set_sha1c(msnobj, base64); g_free(base64); } else { gaim_debug_error("msn", "Unable to open buddy icon %s!\n", filename); msn_user_set_object(user, NULL); } }