YouTube签名解密,带有VB.Net的工作示例

时间:2015-01-16 09:51:48

标签: vb.net youtube youtube-api youtube-javascript-api encryption

我知道有很多项目,我可以使用它们。但我真的想让它在我的VB.Net项目中没有依赖性地运行。

所以我尝试做的是创建一个 Youtube下载器。它适用于通常的视频。但是像 Vevo https://www.youtube.com/watch?v=9bZkp7q19f0)和其他一些特殊视频不起作用。

他们有另外一个我需要破译的签名。在这里,我需要能够提取的HTMLPlayer JS文件(http://s.ytimg.com/yts/jsbin/html5player-de_DE-vflG4uS_k/html5player.js)。在那个文件中,我需要搜索一个特殊的函数,看看这个函数在做什么,然后在我的代码中做同样的事情。到目前为止这么容易,但在某些例子中,我甚至找不到“sig =”或“signature =”,当我发现它们时,它并没有真正帮助我。

所以我想知道的是如何从html5.player.js文件中提取所需的信息。因此,您可以在此处看到https://superuser.com/questions/773719/how-do-all-of-these-save-video-from-youtube-services-work我有该文件的链接。

我还发现这个https://mytoolkit.codeplex.com/discussions/479171帮助我开始了。但是从 Sign_Decipher 开始,我在js文件中找不到这样的被调用函数。

我发现其他一些链接但是没有帮助我让它运行或者太旧了:

某些 API 也有些不起作用:

2 个答案:

答案 0 :(得分:6)

您提供的链接网站已包含解决此问题所需的全部内容。大多数工作都可以使用一些简单的正则表达式完成。这些是解码这种加扰签名所需的步骤:

  1. 下载您要下载的视频页面使用的 html5player.js
  2. 确定用于解码编码签名的函数的名称。
  3. 使用此名称,从脚本中提取函数定义。
  4. 在JS解释器中运行提取的函数,然后使用它解码签名。
  5. 获取html5player.js

    第一步应该没问题,因为你已经完成了它。大多数脚本URL将始终相同(https://s.ytimg.com/yts/jsbin/html5player-VERSION/html5player.js)。只有版本部分会不时更改(例如 de_DE-vflR89yTY )。这意味着,您只需在视频页面中找到脚本版本并调整默认脚本URL。生成的URL将如下所示:https://s.ytimg.com/yts/jsbin/html5player-de_DE-vflR89yTY/html5player.js

    玩家版本: html5player-([\w\d\-]+)\\\/html5player\.js

    可以在第一个捕获组中找到该版本。

    提取解码函数

    在我们提取函数之前,我们必须知道它的名字。不幸的是,解码函数的名称可能会因版本而异,但使用此函数的代码部分通常不会更改。

    解码 - 功能名称: \.sig\|\|([a-zA-Z0-9$]+)\(

    函数名称将位于第一个捕获组中。

    现在我们知道了名称,我们可以再次使用正则表达式提取函数。只需将 #NAME#替换为函数名称。

    解码 - 功能定义: function #NAME#\([^\)]+\){.*?};


    除了实际的解码函数之外,我们还需要提取解码函数正在使用的一些实用函数。这些函数包含在一个对象中。在我们从 html5player.js 中提取对象定义之前,我们必须确定对象的名称。

    请记住这次使用提取的函数定义作为正则表达式的输入。

    帮助对象名称: ;([A-Za-z0-9]+)\.

    对象名称将位于第一个捕获组中。

    使用对象名称和一些正则表达式,我们可以从播放器脚本中提取对象定义,就像我们之前使用函数定义一样。将 #NAME#替换为最后一步中的对象名称。

    辅助对象定义: var #NAME#={.*?};

    现在我们需要恢复加扰签名。

    解码签名

    最后一步是使用提取的函数解码签名。要在.NET中实现这一点,我们必须解析并执行JavaScript代码。幸运的是,有一些现成的解决方案可以为我们做到这一点。其中一个是JS解释器Jint。另一种选择是使用Windows中可用的Script Engines之一。 Simon Mourier在以下答案中为这些引擎提供了方便的包装:https://stackoverflow.com/a/4748886/1278838


    这是一个结合了上述所有步骤的小示例程序,并使用Simon的包装器解码它在硬编码视频页面中可以找到的第一个签名,并将编码和解码的签名打印到控制台。

    代码是用C#编写的,但很容易将其转换为VB .NET。

    class Program
    {
        private const string PlayerScriptUrlTemplate = "https://s.ytimg.com/yts/jsbin/html5player-{0}/html5player.js";
        private const string DecodeFunctionPatternTemplate = @"function #NAME#\([^\)]+\){.*?};";
        private const string HelperObjectPatternTemplate = @"var #NAME#={.*?};";
    
        private static readonly Regex SignatureRegex = new Regex(@"s=(?<Signature>[A-F0-9]+\.[A-F0-9]+)");
        private static readonly Regex PlayerVersionRegex = new Regex(@"html5player-(?<PlayerVersion>[\w\d\-]+)\\\/html5player\.js");
        private static readonly Regex DecodeFunctionNameRegex = new Regex(@"\.sig\|\|(?<FunctionName>[a-zA-Z0-9$]+)\(");
        private static readonly Regex HelperObjectNameRegex = new Regex(@";(?<ObjectName>[A-Za-z0-9]+)\.");
    
        static void Main()
        {
            const string videoUrl = "https://www.youtube.com/watch?v=6pIyg35wiB4";
    
            var client = new WebClient();
            var videoPageData = client.DownloadString(videoUrl);
    
            var encodedSignature = SignatureRegex.Match(videoPageData).Groups["Signature"].Value;
    
            var playerVersion = PlayerVersionRegex.Match(videoPageData).Groups["PlayerVersion"].Value;
            var playerScriptUrl = string.Format(PlayerScriptUrlTemplate, playerVersion);
            var playerScript = client.DownloadString(playerScriptUrl);
    
            var decodeFunctionName = DecodeFunctionNameRegex.Match(playerScript).Groups["FunctionName"].Value;
            var decodeFunction = Regex.Match(playerScript, DecodeFunctionPatternTemplate.Replace("#NAME#", decodeFunctionName)).Value;
            var helperObjectName = HelperObjectNameRegex.Match((decodeFunction)).Groups["ObjectName"].Value;
            var helperObject = Regex.Match(playerScript, HelperObjectPatternTemplate.Replace("#NAME#", helperObjectName)).Value;
    
            var engine = new ScriptEngine(ScriptEngine.JavaScriptLanguage);
            var decoderScript = engine.Parse(helperObject + decodeFunction);
            var decodedSignature = decoderScript.CallMethod(decodeFunctionName, encodedSignature).ToString();
    
            // Jint variant
            //var engine = new Engine();
            //var decoderScript = engine.Execute(helperObject).Execute(decodeFunction);
            //var decodedSignature = decoderScript.Invoke(decodeFunctionName, encodedSignature).ToString();
    
            Console.WriteLine("Encoded Signature\n{0}.\n{1}", encodedSignature.Split('.').First(), encodedSignature.Split('.').Last());
            Console.WriteLine();
            Console.WriteLine("Decoded Signature\n{0}.\n{1}", decodedSignature.Split('.').First(), decodedSignature.Split('.').Last());
            Console.ReadLine();
        }
    }
    

答案 1 :(得分:2)

对不起人们,但旧的“html5player.js”播放器不再有效,它是404,你现在需要的网址看起来更像https://s.ytimg.com/yts/jsbin/player-en_US-vfl_cdzrt/base.js

你是六人的首发是在javascript中找到一个看起来像这样的函数

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("")
}

之后我有点丢失,因为wr函数的代码看起来一样,我找不到像Youtube过去使用的交换,替换,分割函数的代码。

wr=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("")
}

wr.N0我认为看起来像这样但是javascript然后高于我的薪水等级,让我跟踪发生的事情。

N0=function(a,b){Tb(nga,b)&&tm(H_(a),a.O,b,a.Pq,a)}