• 隐藏侧边栏
  • 展开分类目录
  • 关注微信公众号
  • 我的GitHub
  • QQ:1753970025
Chen Jiehua

优酷用户、视频ID加解密 

优酷作为国内一大在线视频网站,无聊的时候上去看看总能发现一些有趣的视频。然而煲剧也好,看片也罢,我们应该始终遵循我们的口号:搞事!搞事!!搞事!!!这不又碰巧发现了一些有趣的事情……

作为一只程序猿,显然你的注意力不应该仅仅集中在视频本身:

显然,每个视频都有一个ID(比如:id_XMjgxMjkxNjc0MA==),同时也有另一个ID:703229185(在网页源代码中可以找到该videoId)。凭直觉,这两个ID之间存在着某种可逆的计算过程!

同时,继我们上次的爬虫抓取 http://www.youku.com/u/channelRanking 页面,我们发现每一个用户ID也有类似的加解密。

数字ID字符串ID
138846849http://i.youku.com/i/UNTU1Mzg3Mzk2
327921687http://i.youku.com/i/UMTMxMTY4Njc0OA==
680184272http://v.youku.com/v_show/id_XMjcyMDczNzA4OA==
410086641 http://v.youku.com/v_show/id_XMTY0MDM0NjU2NA==

源数据

为了进行下一步的工作,我们需要先获取了一批样本数据用于后续的分析,这里用用户ID为例:

eiduid
UNzAzNg==1759
UMTA3MDg=2677
UODk2ODA=22420
UMTAwMDU1Ng==250139
UNDA0MzcxNg==1010929
UMTAwMDgzNjg=2502092
UNzkwOTQ1NDA=19773635
UMzM3NTIyNjg0MA==843806710

分析

第一步:base64decode,发现随着uid的增大,eid长度也在增大,但两者的位数却无法一一对应:

eideid_b64decodelen(eid_b64decode)uidlen(uid)
UNzAzNg==‘P\xdc\xc0\xcc\xd8’517594
UMTA3MDg=‘P\xc4\xc0\xdc\xc0\xe0’626774
UODk2ODA=‘P\xe0\xe4\xd8\xe0\xc0’6224205
UMTAwMDU1Ng==‘P\xc4\xc0\xc0\xc0\xd4\xd4\xd8’82501396
UNDA0MzcxNg==‘P\xd0\xc0\xd0\xcc\xdc\xc4\xd8’810109297
UMTAwMDgzNjg=‘P\xc4\xc0\xc0\xc0\xe0\xcc\xd8\xe0’925020927
UNzkwOTQ1NDA=‘P\xdc\xe4\xc0\xe4\xd0\xd4\xd0\xc0’9197736358
UMzM3NTIyNjg0MA==‘P\xcc\xcc\xdc\xd4\xc8\xc8\xd8\xe0\xd0\xc0’118438067109

第二步:由于uid是纯数字,考虑将 eid_b64decode 以数字的形式展现出来:

eideid_b64decodeeid_b64decode_numuid
UNzAzNg==‘P\xdc\xc0\xcc\xd8’220-192-204-2161759
UMTA3MDg=‘P\xc4\xc0\xdc\xc0\xe0’196-192-220-192-2242677
UODk2ODA=‘P\xe0\xe4\xd8\xe0\xc0’224-228-216-224-19222420
UMTAwMDU1Ng==‘P\xc4\xc0\xc0\xc0\xd4\xd4\xd8’196-192-192-192-212-212-216250139
UNDA0MzcxNg==‘P\xd0\xc0\xd0\xcc\xdc\xc4\xd8’208-192-208-204-220-196-2161010929
UMTAwMDgzNjg=‘P\xc4\xc0\xc0\xc0\xe0\xcc\xd8\xe0’196-192-192-192-224-204-216-2242502092
UNzkwOTQ1NDA=‘P\xdc\xe4\xc0\xe4\xd0\xd4\xd0\xc0’220-228-192-228-208-212-208-19219773635
UMzM3NTIyNjg0MA==‘P\xcc\xcc\xdc\xd4\xc8\xc8\xd8\xe0\xd0\xc0’204-204-220-212-200-200-216-224-208-192843806710
  • 将各组数据分别进行简单的算术运算,发现仍然无法得到uid;
  • 猜测:aXn + bXn-1 + cXn-2 + … + yXn + z 形式,计算比较麻烦,但最后结果仍然不对;

第三步:留意到 eid_b64decode 的每一位出现的频率,推测其为枚举值,故统计多组eid-uid计算其分布:

出现次数
‘\xc0’1590
‘\xc4’1920
‘\xc8’1788
‘\xcc’1715
‘\xd0’1557
‘\xd4’1163
‘\xd8’1580
‘\xdc’1137
‘\xe0’1562
‘\xe4’1163

发现枚举为10个值,推测其分别对应0~9。

第四步:以0~9分别替代上面的字符:

eideid_b64decodeeid_numuid
UNzAzNg==‘P\xdc\xc0\xcc\xd8’70361759
UMTA3MDg=‘P\xc4\xc0\xdc\xc0\xe0’107082677
UODk2ODA=‘P\xe0\xe4\xd8\xe0\xc0’8968022420
UMTAwMDU1Ng==‘P\xc4\xc0\xc0\xc0\xd4\xd4\xd8’1000556250139
UNDA0MzcxNg==‘P\xd0\xc0\xd0\xcc\xdc\xc4\xd8’40437161010929
UMTAwMDgzNjg=‘P\xc4\xc0\xc0\xc0\xe0\xcc\xd8\xe0’100083682502092
UNzkwOTQ1NDA=‘P\xdc\xe4\xc0\xe4\xd0\xd4\xd0\xc0’7909454019773635
UMzM3NTIyNjg0MA==‘P\xcc\xcc\xdc\xd4\xc8\xc8\xd8\xe0\xd0\xc0’3375226840843806710

发现 eid_num 与 uid 存在 × 4倍关系。

第五步:数据校验,部分数据发现其虽然形式类似 base64,但却无法decode:

UMjc4MTA0MDM269526009
UMTMyNTE3MTcy33129293
UNTEwMTgyMzY0127545591
UMzIzOTM0NTAw80983625
UNDkwNzkyODY4122698217

统计大量数据后,发现其末位字符为 “wy024” 时无法decode。

进一步发现,”wy024″情况下需要进行补位,其对应关系为:

末位最后结果补位
w0
y2
04
26
48

至此,分析过程完成。

实现

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import base64


char = "\xc0\xc4\xc8\xcc\xd0\xd4\xd8\xdc\xe0\xe4"
char_map = {char[i]: str(i) for i in range(len(char))}

suffix = "wy024"
suffix_map = {suffix[i]: str(i*2) for i in range(len(suffix))}


def uid2eid(uid):
    """ 用户数字ID 加密为 字符串ID"""
    return encrypt(uid, prefix="P")


def uid2vid(uid):
    """ 视频数字ID 加密为 字符串ID """
    return encrypt(uid, prefix="\\")


def eid2uid(eid):
    """ 字符串ID 解密为 数字ID """
    # 判断最后一位是否需要进行fix
    fix = suffix_map[eid[-1]] if eid[-1] in suffix else ""
    # 去掉最后一位
    eid = eid[:-1]
    ss = base64.b64decode(eid)[1:]
    num = []
    for s in ss:
        num.append(char_map[s])

    num.append(fix)
    uid = int("".join(num)) / 4
    return uid


def encrypt(id, prefix):
    num = str(int(id)*4)
    fix = "="
    if len(num) % 3 == 0:
        fix = suffix[int(num[-1])/2]
        num = num[:-1]

    ss = prefix
    for s in str(num):
        ss += char[int(s)]

    eid = base64.b64encode(ss) + fix
    return eid

结尾

当然,在实际分析过程中,也走了一些弯路,分析过程并非从头到尾都很顺畅。另外,最后对数据进行校验,其实也才逐步发现id在加密时的特殊处理等。

码字很辛苦,转载请注明来自ChenJiehua《优酷用户、视频ID加解密》

评论