QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 756|回复: 3

大家帮我看一下,解释一下这个程序

[复制链接]
发表于 2004-10-12 17:58:23 | 显示全部楼层 |阅读模式
在这个程序中,resp_6与resp_96的值是如何得来的?这是yahoo 即时通软件里的验证程序,其中name是用户名,pass是密码,SEED是一组随机的字符串,谢谢大家,

[code:1]
static void yahoo_process_auth_new(GaimConnection *gc, const char *seed)
{
        struct yahoo_packet *pack = NULL;
        GaimAccount *account = gaim_connection_get_account(gc);
        const char *name = gaim_normalize(account, gaim_account_get_username(account));
        const char *pass = gaim_account_get_password(account);
        struct yahoo_data *yd = gc->proto_data;

        md5_byte_t                        result[16];
        md5_state_t                        ctx;

        SHA_CTX                                ctx1;
        SHA_CTX                                ctx2;

        char                                *alphabet1                        = "FBZDWAGHrJTLMNOPpRSKUVEXYChImkwQ";
        char                                *alphabet2                        = "F0E1D2C3B4A59687abcdefghijklmnop";

        char                                *challenge_lookup        = "qzec2tb3um1olpar8whx4dfgijknsvy5";
        char                                *operand_lookup                = "+|&%/*^-";
        char                                *delimit_lookup                = ",;";

        char                                *password_hash                = (char *)g_malloc(25);
        char                                *crypt_hash                = (char *)g_malloc(25);
        char                                *crypt_result                = NULL;

        char                                pass_hash_xor1[64];
        char                                pass_hash_xor2[64];
        char                                crypt_hash_xor1[64];
        char                                crypt_hash_xor2[64];
        char                                resp_6[100];
        char                                resp_96[100];

        unsigned char                digest1[20];
        unsigned char                digest2[20];
        unsigned char                comparison_src[20];
        unsigned char                magic_key_char[4];
        const unsigned char                *magic_ptr;

        unsigned int                magic[64];
        unsigned int                magic_work = 0;
        unsigned int                magic_4 = 0;

        int                                        x;
        int                                        y;
        int                                        cnt = 0;
        int                                        magic_cnt = 0;
        int                                        magic_len;

        memset(password_hash, 0, 25);
        memset(crypt_hash, 0, 25);
        memset(&pass_hash_xor1, 0, 64);
        memset(&pass_hash_xor2, 0, 64);
        memset(&crypt_hash_xor1, 0, 64);
        memset(&crypt_hash_xor2, 0, 64);
        memset(&digest1, 0, 20);
        memset(&digest2, 0, 20);
        memset(&magic, 0, 64);
        memset(&resp_6, 0, 100);
        memset(&resp_96, 0, 100);
        memset(&magic_key_char, 0, 4);
        memset(&comparison_src, 0, 20);

        /*
         * Magic: Phase 1.  Generate what seems to be a 30 byte value (could change if base64
         * ends up differently?  I don't remember and I'm tired, so use a 64 byte buffer.
         */

        magic_ptr = seed;

        while (*magic_ptr != (int)NULL) {
                char   *loc;
               
                /* Ignore parentheses.
                 */
               
                if (*magic_ptr == '(' || *magic_ptr == ')') {
                        magic_ptr++;
                        continue;
                }
               
                /* Characters and digits verify against the challenge lookup.
                 */
               
                if (isalpha(*magic_ptr) || isdigit(*magic_ptr)) {
                        loc = strchr(challenge_lookup, *magic_ptr);
                        if (!loc) {
                          /* SME XXX Error - disconnect here */
                        }
                       
                        /* Get offset into lookup table and shl 3.
                         */
                       
                        magic_work = loc - challenge_lookup;
                        magic_work <<= 3;
                       
                        magic_ptr++;
                        continue;
                } else {
                        unsigned int        local_store;
                       
                        loc = strchr(operand_lookup, *magic_ptr);
                        if (!loc) {
                                /* SME XXX Disconnect */
                        }
                       
                        local_store = loc - operand_lookup;
                       
                        /* Oops; how did this happen?
                         */
                       
                        if (magic_cnt >= 64)
                                break;
                       
                        magic[magic_cnt++] = magic_work | local_store;
                        magic_ptr++;
                        continue;
                }
                        }
       
        magic_len = magic_cnt;
        magic_cnt = 0;
       
        /* Magic: Phase 2.  Take generated magic value and sprinkle fairy dust on the values.
         */

        for (magic_cnt = magic_len-2; magic_cnt >= 0; magic_cnt--) {
                unsigned char        byte1;
                unsigned char        byte2;
               
                /* Bad.  Abort.
                 */
               
                if ((magic_cnt + 1 > magic_len) || (magic_cnt > magic_len))
                        break;
               
                byte1 = magic[magic_cnt];
                byte2 = magic[magic_cnt+1];
               
                byte1 *= 0xcd;
                byte1 ^= byte2;
               
                magic[magic_cnt+1] = byte1;
                        }
       
        /*
         * Magic: Phase 3.  This computes 20 bytes.  The first 4 bytes are used as our magic
         * key (and may be changed later); the next 16 bytes are an MD5 sum of the magic key
         * plus 3 bytes.  The 3 bytes are found by looping, and they represent the offsets
         * into particular functions we'll later call to potentially alter the magic key.
         *
         * %-)
         */
       
        magic_cnt = 1;
        x = 0;
       
        do {
                unsigned int        bl = 0;
                unsigned int        cl = magic[magic_cnt++];
               
                if (magic_cnt >= magic_len)
                        break;
               
                if (cl > 0x7F) {
                        if (cl < 0xe0)
                                bl = cl = (cl & 0x1f) << 6;
                        else {
                                bl = magic[magic_cnt++];
                                cl = (cl & 0x0f) << 6;
                                bl = ((bl & 0x3f) + cl) << 6;
                        }

                        cl = magic[magic_cnt++];
                        bl = (cl & 0x3f) + bl;
                } else
                        bl = cl;
               
                comparison_src[x++] = (bl & 0xff00) >> 8;
                comparison_src[x++] = bl & 0xff;
        } while (x < 20);
       
        /* First four bytes are magic key.
         */
       
        memcpy(&magic_key_char[0], comparison_src, 4);
        magic_4 = magic_key_char[0] | (magic_key_char[1]<<8) | (magic_key_char[2]<<16) | (magic_key_char[3]<<24);
       
        /*
         * Magic: Phase 4.  Determine what function to use later by getting outside/inside
         * loop values until we match our previous buffer.
         */
       
        for (x = 0; x < 65535; x++) {
                int                        leave = 0;

                for (y = 0; y < 5; y++) {
                        md5_byte_t                result[16];
                        md5_state_t                ctx;
                       
                        unsigned char        test[3];
                       
                        memset(&result, 0, 16);
                        memset(&test, 0, 3);
                       
                        /* Calculate buffer.
                         */

                        test[0] = x;
                        test[1] = x >> 8;
                        test[2] = y;
                       
                        md5_init(&ctx);
                        md5_append(&ctx, magic_key_char, 4);
                        md5_append(&ctx, test, 3);
                        md5_finish(&ctx, result);
                       
                        if (!memcmp(result, comparison_src+4, 16)) {
                                leave = 1;
                                break;
                        }
                }
               
                if (leave == 1)
                        break;
        }
       
        /* If y != 0, we need some help.
         */
       
        if (y != 0) {
                unsigned int        updated_key;
               
                /* Update magic stuff.   Call it twice because Yahoo's encryption is super bad ass.
                 */
               
                updated_key = yahoo_auth_finalCountdown(magic_4, 0x60, y, x);
                updated_key = yahoo_auth_finalCountdown(updated_key, 0x60, y, x);
               
                magic_key_char[0] = updated_key & 0xff;
                magic_key_char[1] = (updated_key >> 8) & 0xff;
                magic_key_char[2] = (updated_key >> 16) & 0xff;
                magic_key_char[3] = (updated_key >> 24) & 0xff;
        }
       
/* Get password and crypt hashes as per usual.
         */
       
        md5_init(&ctx);
        md5_append(&ctx, pass, strlen(pass));
        md5_finish(&ctx, result);
        to_y64(password_hash, result, 16);
       
        md5_init(&ctx);
        crypt_result = yahoo_crypt(pass, "$1$_2S43d5f$");  
        md5_append(&ctx, crypt_result, strlen(crypt_result));
        md5_finish(&ctx, result);
        to_y64(crypt_hash, result, 16);

        /* Our first authentication response is based off of the password hash.
         */
       
        for (x = 0; x < (int)strlen(password_hash); x++)
                pass_hash_xor1[cnt++] = password_hash[x] ^ 0x36;
       
        if (cnt < 64)
                memset(&(pass_hash_xor1[cnt]), 0x36, 64-cnt);

        cnt = 0;
       
        for (x = 0; x < (int)strlen(password_hash); x++)
                pass_hash_xor2[cnt++] = password_hash[x] ^ 0x5c;
       
        if (cnt < 64)
                memset(&(pass_hash_xor2[cnt]), 0x5c, 64-cnt);
       
        shaInit(&ctx1);
        shaInit(&ctx2);
       
        /*
         * The first context gets the password hash XORed with 0x36 plus a magic value
         * which we previously extrapolated from our challenge.
         */
       
        shaUpdate(&ctx1, pass_hash_xor1, 64);
        if (y >= 3)
                ctx1.sizeLo = 0x1ff;
        shaUpdate(&ctx1, magic_key_char, 4);
        shaFinal(&ctx1, digest1);
       
        /*
         * The second context gets the password hash XORed with 0x5c plus the SHA-1 digest
         * of the first context.
         */
       
        shaUpdate(&ctx2, pass_hash_xor2, 64);
        shaUpdate(&ctx2, digest1, 20);
        shaFinal(&ctx2, digest2);
       
        /*
         * Now that we have digest2, use it to fetch characters from an alphabet to construct
         * our first authentication response.
         */

        for (x = 0; x < 20; x += 2) {
                unsigned int        val = 0;
                unsigned int        lookup = 0;
               
                char                        byte[6];
                               
                memset(&byte, 0, 6);

                /* First two bytes of digest stuffed together.
                 */

                val = digest2[x];
                val <<= 8;
                val += digest2[x+1];
               
                lookup = (val >> 0x0b);
                lookup &= 0x1f;
                if (lookup >= strlen(alphabet1))
                        break;
                sprintf(byte, "%c", alphabet1[lookup]);
                strcat(resp_6, byte);
                strcat(resp_6, "=");

                lookup = (val >> 0x06);
                lookup &= 0x1f;
                if (lookup >= strlen(alphabet2))
                        break;
                sprintf(byte, "%c", alphabet2[lookup]);
                strcat(resp_6, byte);
               
                lookup = (val >> 0x01);
                lookup &= 0x1f;
                if (lookup >= strlen(alphabet2))
                        break;
                sprintf(byte, "%c", alphabet2[lookup]);
                strcat(resp_6, byte);

                lookup = (val & 0x01);
                if (lookup >= strlen(delimit_lookup))
                        break;
                sprintf(byte, "%c", delimit_lookup[lookup]);
                strcat(resp_6, byte);
        }
       
        /* Our second authentication response is based off of the crypto hash.
         */
       
        cnt = 0;
        memset(&digest1, 0, 20);
        memset(&digest2, 0, 20);
       
        for (x = 0; x < (int)strlen(crypt_hash); x++)
                crypt_hash_xor1[cnt++] = crypt_hash[x] ^ 0x36;
       
        if (cnt < 64)
                memset(&(crypt_hash_xor1[cnt]), 0x36, 64-cnt);

        cnt = 0;
       
        for (x = 0; x < (int)strlen(crypt_hash); x++)
                crypt_hash_xor2[cnt++] = crypt_hash[x] ^ 0x5c;
       
        if (cnt < 64)
                memset(&(crypt_hash_xor2[cnt]), 0x5c, 64-cnt);
       
        shaInit(&ctx1);
        shaInit(&ctx2);
       
        /*
         * The first context gets the password hash XORed with 0x36 plus a magic value
         * which we previously extrapolated from our challenge.
         */
       
        shaUpdate(&ctx1, crypt_hash_xor1, 64);
        if (y >= 3)
                ctx1.sizeLo = 0x1ff;
        shaUpdate(&ctx1, magic_key_char, 4);
        shaFinal(&ctx1, digest1);
       
        /*
         * The second context gets the password hash XORed with 0x5c plus the SHA-1 digest
         * of the first context.
         */
       
        shaUpdate(&ctx2, crypt_hash_xor2, 64);
        shaUpdate(&ctx2, digest1, 20);
        shaFinal(&ctx2, digest2);
       
        /*
         * Now that we have digest2, use it to fetch characters from an alphabet to construct
         * our first authentication response.
         */
       
        for (x = 0; x < 20; x += 2) {
                unsigned int        val = 0;
                unsigned int        lookup = 0;
               
                char                        byte[6];
               
                memset(&byte, 0, 6);
               
                /* First two bytes of digest stuffed together.
                 */
               
                val = digest2[x];
                val <<= 8;
                val += digest2[x+1];

                lookup = (val >> 0x0b);
                lookup &= 0x1f;
                if (lookup >= strlen(alphabet1))
                        break;
                sprintf(byte, "%c", alphabet1[lookup]);
                strcat(resp_96, byte);
                strcat(resp_96, "=");
               
                lookup = (val >> 0x06);
                lookup &= 0x1f;
                if (lookup >= strlen(alphabet2))
                        break;
                sprintf(byte, "%c", alphabet2[lookup]);
                strcat(resp_96, byte);
               
                lookup = (val >> 0x01);
                lookup &= 0x1f;
                if (lookup >= strlen(alphabet2))
                        break;
                sprintf(byte, "%c", alphabet2[lookup]);
                strcat(resp_96, byte);
               
                lookup = (val & 0x01);
                if (lookup >= strlen(delimit_lookup))
                        break;
                sprintf(byte, "%c", delimit_lookup[lookup]);
                strcat(resp_96, byte);
        }
       
        pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP,        YAHOO_STATUS_AVAILABLE, 0);
        yahoo_packet_hash(pack, 0, name);
        yahoo_packet_hash(pack, 6, resp_6);
        yahoo_packet_hash(pack, 96, resp_96);
        yahoo_packet_hash(pack, 1, name);
        yahoo_packet_hash(pack, 135, "6,0,0,1710");
        if (yd->picture_checksum) {
                char *cksum = g_strdup_printf("%d", yd->picture_checksum);
                yahoo_packet_hash(pack, 192, cksum);
                g_free(cksum);
        }
        yahoo_send_packet(yd, pack);
        yahoo_packet_free(pack);

        g_free(password_hash);
        g_free(crypt_hash);
}[/code:1]
发表于 2004-10-12 18:16:32 | 显示全部楼层
好长
回复

使用道具 举报

发表于 2004-10-12 22:39:58 | 显示全部楼层
SHA-1是安全散列算法,不管它怎样算的。
Xored也是加密相关的东西。
digest2这个应该是算出来的数字签名,
digest2两个组成一个16位数,然后把1-5,6-10,12-16位当成字符打印到resp_6里
最后在加上一个终结符,结果像这样 a=b=c;

resp_96是又不知怎么算出一堆签名,有按照前面的算法打出一个字符串,就是这样子。

我也明白什么加密算法,随便看看,呵呵。
回复

使用道具 举报

发表于 2004-10-12 22:42:27 | 显示全部楼层
说错了,是把1-5,6-10,12-16当成索引从alphabet1,alphabet2里面得到字符的。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-7 09:34 , Processed in 0.040792 second(s), 16 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表