使用PHP或JS解码Youtube密码签名的最佳方法

时间:2014-02-02 12:59:00

标签: javascript php ios youtube

当字典中的use_cipher_signature = true返回时,Youtube正在为某些视频使用密码签名 http://www.youtube.com/get_video_info?&video_id=Video_Id

示例id:_JQH3G0cCtY

加密签名实际上是加密签名,任何人都可以通过几组工作签名进行调试。但是Youtube继续改变争夺战的算法。 我见过很少的Youtube视频下载器,它可以顺利运行而不会受到这种变化游戏的影响。我认为他们正在检查播放器并从播放器文件中提取解码脚本,因此它会让它们继续运行。

我需要一些关于在这种情况下使用的实际技术的帮助。我知道'youtube-dl' - 一个下载视频的python程序。由于我不擅长python,我认为他们使用相同的方法。

此处还有一个用户脚本JS文件: http://userscripts.org/scripts/show/25105,这是做同样的事情。

任何有关在PHP或JS中解码密码的理智方法的帮助都将受到赞赏。

3 个答案:

答案 0 :(得分:22)

网址结构和密码不断改变Youtube。目前,解密密码签名的最佳方法解释如下:

Youtube中的加密签名只是“加密”签名,您必须根据播放器文件(HTML5播放器或Flash播放器)中的算法重新排列它们。

例如http://www.youtube.com/watch?v=UxxajLWwzqY目前正在使用以下HTML5播放器文件://s.ytimg.com/yts/jsbin/html5player-vfltdb6U3.js

在此文件中,您可以通过搜索“sig”轻松搜索签名解密代码。在这种情况下,Algo是:

function bz(a) {
    a = a.split("");
    a = cz(a, 61);
    a = cz(a, 5);
    a = a.reverse();
    a = a.slice(2);
    a = cz(a, 69);
    a = a.slice(2);
    a = a.reverse();
    return a.join("")
}

function cz(a, b) {
    var c = a[0];
    a[0] = a[b % a.length];
    a[b] = c;
    return a
};

以上是解密代码。

但请注意,它会在更改播放器文件时不断更改,因此您必须点击正在使用的播放器文件。

另外,要下载带有密码签名的视频,您必须使用相同的用户代理标头,发送相同的IP地址请求以及提取后不久发送请求来处理相同的cookie。所有这些在某些时候都是必需的

如果对密码解密算法感兴趣,请访问CipherAPI

另一个很酷的API:TYstream API

答案 1 :(得分:2)

旧的s.ytimg.com/yts/jsbin/html5player-vfltdb6U3.js现在是404,我觉得新的网址看起来更像hxxps://s.ytimg.com/yts/jsbin/player-en_US-vfl_cdzrt/base.js

如果你搜索JavaScript,你会发现一些看起来像这样的代码

function(a,b,c)
{
a=new Mr(a);
a.set("alr","yes");a.set("keepalive","yes");a.set("ratebypass","yes");a.set("mime",(0,window.encodeURIComponent)(b.mimeType.split(";")[0]));c&&a.set("signature",xr(c));return a},Jt=function(a,b){var c=Yr(b,"id"),c=c.replace(":",";");..............
}

上面代码调用的xr函数看起来像这个

xr=function(a)
{
a=a.split("");
wr.rF(a,54);
wr.fs(a,75);
wr.N0(a,1);
wr.rF(a,52);
wr.N0(a,3);
wr.fs(a,31);
wr.rF(a,16);
wr.fs(a,38);
return a.join("")
}

之后我开始迷失了javascript并且可以自己做一些帮助,但在代码项目中谈论这个问题会让你陷入困境。

答案 2 :(得分:1)

我已经为iOS人员翻译了 Swift 3 Akhilesh的答案:

func decryptSignature(signature:String)->String {
    return bz(signature)
}
func bz(_ a:String)->String {
    var arrayA = Array(a.characters)
    arrayA = cz(arrayA, 61)
    arrayA = cz(arrayA, 5)
    arrayA = arrayA.reversed()
    arrayA = Array(arrayA[2..<arrayA.count])
    arrayA = cz(arrayA, 69)
    arrayA = Array(arrayA[2..<arrayA.count])
    arrayA = arrayA.reversed()
    return String(arrayA)
}
func cz(_ a:Array<Character>, _ b:Int)->Array<Character> {
    var arrayA = a
    let c = a[0]
    arrayA[0] = a[b % a.count];
    arrayA[b] = c
    return arrayA
}

但我认为这个算法不够,它会根据特定规则解密签名。实际上,根据this perl脚本(来自Jamie Zawinski的youtubedown),算法每次都会更改,并且脚本会在几天内收集规则和算法列表!到目前为止,密码中只使用了三个命令,因此我们可以紧凑地表示它们:

# - r  = reverse the string;
# - sN = slice from character N to the end;
# - wN = swap 0th and Nth character.

我认为最好的方法是实现以下目标:

func decryptChiper(_ commands:String, signature:String)->String {
    var a = Array(signature.characters)
    let cmdArray:[String]! = commands.components(separatedBy: " ")
    for cmd in cmdArray {
        var value:Int!
        if cmd.characters.count>1 {
            let secondChar = cmd.index(cmd.startIndex, offsetBy: 1)
            value = Int(cmd.substring(from:secondChar))
        }

        switch cmd[cmd.startIndex] {
        case "r": a = a.reversed()
        case "s":
            if let sliceFrom = value {
                a = Array(a[sliceFrom..<a.count])
            }
        case "w":
            if let swapValue = value {
                a = swap(a,swapValue)
            }
        default:break
        }
    }
    return String(a)
}

func swap(_ a:Array<Character>, _ b:Int)->Array<Character> {
    var arrayA = a
    let c = a[0]
    arrayA[0] = a[b % a.count];
    arrayA[b] = c
    return arrayA
}

用法:

Akhilesh回答之后做一个例子:

let signature = "D3D3434498D70C3080D9B084E48350F6519A9E9A71094.25F300BB180DDDD918EE0EBEDD174EE5D874EFEFF"
let decryptedSign = decryptChiper("w61 w5 r s2 w69 s2 r", signature: signature )
print(decryptedSign)

输出

33D3494498D70C3E80D9B084E48350F6519A9E9A71094.25F300BB180DDDDD18EE0EBEDD174EE5D874E