【问题标题】:Getting the signature of a youtube video获取 youtube 视频的签名
【发布时间】:2014-06-01 01:05:34
【问题描述】:

我注意到一些 Youtube 视频有一个加密的签名......我已经用谷歌搜索了这个问题,发现 Youtube 将算法存储在他们的 HTML5 播放器的 Java 脚本中,你可以在这里看到: https://s.ytimg.com/yts/jsbin/html5player-iw_IL-vflC7Zf5J.js

我找到了这些功能:

function zn(a)
{
a=a.split("");
a=a.slice(2);
a=a.reverse();
a=An(a,7);
a=An(a,21);
a=a.reverse();
return a.join("")
}

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

现在,我有几个问题:

首先,如果我有一个加密的签名,我需要将签名通过这两个函数来得到解密的那个,还是我必须写一个与这个相反的函数来解密数据?

第二,有没有办法让它通用,或者每次 youtube 更新他们的加密签名算法时,我都必须重新编写它? (加密函数)

谢谢!!

【问题讨论】:

    标签: javascript c++ http youtube


    【解决方案1】:

    第二,有没有办法让它通用,或者每次 youtube 更新他们的加密签名算法时,我都必须重新编写它? (加密函数)

    您可以传入具有已知不同值的相同长度的字符串,例如字符String.fromCharCode(0), String.fromCharCode(1), ... - 并查看它们在输出字符串中的移动位置:这就是您反转转换所需的所有信息,只要它不是破坏性的(即输出字符串的长度相同,每个字符出现一次)。

    首先,如果我有一个加密的签名,我需要将签名通过这两个函数来得到解密的那个,还是我必须写一个与这个相反的函数来解密数据?

    听起来您可以尝试一下,看看哪个有效...?

    【讨论】:

    • 1) 那么你是否碰巧有一份加密签名和一个解密签名的副本,所以我可以检查我是否编写了解密成功的函数..?我不明白你的答案是 2。传递字符串是什么意思。去哪里?
    • 1) 不...但是你为什么需要一个?如果你解密成功,你看不到视频可以播放吗? 2) 将一个字符串传递给zn(a) - 基本上你用特殊字符串自己调用它,输出字符串是一种字符已移动到的索引列表:例如,如果zn 返回一个带有 3 的字符串作为第一个字符,那么第四个字符肯定已经移到了那里——你知道把它放回哪里......
    • 上述zn函数的参数我要传入什么? zn中的a是什么??
    • @Ars: aString.fromCharCode(0), String.fromCharCode(1), ...
    • 你能告诉我更多关于它的详细信息吗?上述函数的输入是什么??
    【解决方案2】:

    实际上,在一些用于签名解扰的 Javascript 片段中有一对交替的模式,每个模式都不像某些帖子可能建议或期望的那样真正通用。 在一个解决方案中

    /* Java Class SignatureDecoder, Version 2019-01-03 */
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.MalformedURLException;
    import java.net.Proxy;
    import java.net.URL;
    import java.net.URLConnection;
    import java.net.UnknownHostException;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    import javax.script.Invocable;
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    
    public class SignatureDecoder
    {
        String cacheUrl = null;
        String js = null;
    
        public SignatureDecoder()
        {
        }
    
        public String decode(String jsUrl, String rawSignature, Proxy proxy)
        {
            if (!loadJs(jsUrl, proxy))
            {
                return null;
            }
    
            // Get scramble function from script, e.g. ".signature=Aq("
            final String func = getSignFunction();
            if (func == null)
            {
                return null;
            }
            final String fs[] = getFuncScript(func);
            if (fs == null)
            {
                return null;
            }
            String var = null;
            String vs = "";
            final String ident = "[$A-Za-z0-9_]+";
            final String varPat = "(" + ident + ")\\." + ident + "\\([ ]*" + fs[1];
            final Pattern vpt = Pattern.compile(varPat);
            final Matcher vmt = vpt.matcher(fs[0]);
            if (vmt.find(0))
            {
                var = vmt.group(1);
                vs = getVarDef(js, var);
            }
    
            final String extract = vs + "\n" + fs[0];
    
            final ScriptEngineManager mgr = new ScriptEngineManager();
            final ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
            try
            {
                jsEngine.eval(extract);
                final Invocable inv = (Invocable) jsEngine;
                final String enc = (String) inv.invokeFunction(func, rawSignature);
                return enc;
            }
            catch (final ScriptException ex)
            {
                ex.printStackTrace();
            }
            catch (final NoSuchMethodException x)
            {
                x.printStackTrace();
            }
            return rawSignature;
        }
    
        public String decode(String jsUrl, String rawSignature)
        {
            return decode(jsUrl, rawSignature, null);
        }
    
        protected boolean loadJs(String jsUrl, Proxy proxy)
        {
            if (cacheUrl == null || !cacheUrl.equals(jsUrl))
            {
                cacheUrl = null;
                URL jsUrl1;
                try
                {
                    jsUrl1 = new URL(jsUrl);
                }
                catch (final MalformedURLException e1)
                {
                    e1.printStackTrace();
                    return false;
                }
                try
                {
                    BufferedReader in;
                    final StringBuffer buf = new StringBuffer();
                    final URLConnection conn = proxy == null ? jsUrl1.openConnection() : jsUrl1.openConnection(proxy);
                    final InputStream is = conn.getInputStream();
                    in = new BufferedReader(new InputStreamReader(is));
                    String inputLine;
                    while ((inputLine = in.readLine()) != null)
                    {
                        buf.append(inputLine);
                        buf.append('\n');
                    }
                    is.close();
                    this.js = buf.toString();
                    this.cacheUrl = jsUrl;
                }
                catch (final UnknownHostException e)
                {
                    System.err.println("Cannot access script at  " + jsUrl);
                    return false;
                }
                catch (final IOException e)
                {
                    System.err.println("Error loading script from  " + jsUrl);
                    e.printStackTrace();
                    return false;
                }
            }
            return true;
        }
    
        // var zq={ID:function(a,b){a.splice(0,b)},Bd:function(a){a.reverse()},Px:function(a,b){var c=a[0];a[0]=a[b%a.length];a[b]=c}};
        protected String getBlock(String script, int pos1)
        {
            String res = null;
    
            int pos = pos1;
            boolean stop = false;
            int brack = 0;
            boolean containsBlock = false;
    
            while (!stop)
            {
                final char ch = script.charAt(pos);
                pos++;
                switch (ch)
                {
                    case '(':
                        brack++;
                        break;
                    case '{':
                        brack++;
                        break;
                    case '[':
                        brack++;
                        break;
                    case ')':
                        brack--;
                        break;
                    case ']':
                        brack--;
                        break;
                    case '}':
                        brack--;
                        break;
                    case ';':
                        stop = brack == 0;
                        break;
                    case '\n':
                        stop = brack == 0;
                        break;
                    default:
                        ;
                }
                if (brack > 0)
                {
                    containsBlock = true;
                }
                else
                {
                    stop = containsBlock;
                }
            }
            res = script.substring(pos1, pos);
    
            return res;
        }
    
        protected String getVarDef(String script, String var)
        {
            String res = null;
    
            final String varPat = "var[ ]+" + var.replace("$", "\\$") + "[ ]*=";
    
            final Pattern pt = Pattern.compile(varPat);
            final Matcher mt = pt.matcher(script);
            if (mt.find(0))
            {
                res = mt.group(0);
                final int posBlock = mt.end(0);
                final String block = getBlock(script, posBlock);
                res = res + block;
            }
            return res;
        }
    
        protected String[] getFuncScript(String func)
        {
            String res[] = null;
    
            final String funcDollar = func.replace("$", "\\$");
    
            final String paramPat = "[ ]*\\(([^\\)]+)\\)";
            String funcPat = "function[ ]+" + funcDollar + paramPat;
    
            Pattern pt = Pattern.compile(funcPat);
            Matcher mt = pt.matcher(js);
            boolean ok = mt.find(0);
            if (!ok)
            {
                funcPat = funcDollar + "=function" + paramPat;
                pt = Pattern.compile(funcPat);
                mt = pt.matcher(js);
                ok = mt.find(0);
            }
            if (ok)
            {
                res = new String[2];
                String scr = mt.group(0);
                final String arg = mt.group(1);
                final int posBlock = mt.end(0);
                final String block = getBlock(js, posBlock);
                scr = scr + block;
                res[0] = scr;
                res[1] = arg;
            }
            return res;
        }
    
        protected String getSignFunction()
        {
            if (js == null)
            {
                return null;
            }
            // Pattern 1
            String func = null;
            String funcPat = "\\.signature=([^\\(]+)\\(";
            Pattern pt = Pattern.compile(funcPat);
            Matcher mt = pt.matcher(js);
            if (mt.find(0))
            {
                func = mt.group(1);
            }
    
            // Pattern 2
            if (func == null)
            {
                funcPat = "\\(\\\"signature\\\",([^\\(]+)\\(";
            }
            pt = Pattern.compile(funcPat);
            mt = pt.matcher(js);
            if (mt.find(0))
            {
                func = mt.group(1);
            }
    
            // Pattern 3
            if (func == null)
            {
                final int pos = js.indexOf("set(\"alr\",\"yes\")");
                if (pos >= 0)
                {
                    int pos1 = pos;
                    while (pos1 > 0 && js.charAt(pos1) != '\n')
                    {
                        pos1--;
                    }
                    int pos2 = pos;
                    while (pos2 < js.length() && js.charAt(pos2) != '\n')
                    {
                        pos2++;
                    }
                    final String js1 = js.substring(pos1 + 1, pos2);
                    // d.set("alr","yes");c&&(b||(b="signature"),d.set(b,WK(c)));return d};
                    final String ident = "[a-zA-Z0-9]+";
                    funcPat = "(" + ident + ")\\.set\\(\\\"alr\\\",\\\"yes\\\"\\);";
                    pt = Pattern.compile(funcPat);
                    mt = pt.matcher(js1);
                    if (mt.find(0))
                    {
                        final String obj = mt.group(1);
                        final String funcPat2 = obj + "\\.set\\((" + ident + "|\\\"signature\\\"),(" + ident + ")\\(" + ident + "\\)\\)";
                        final Pattern pt2 = Pattern.compile(funcPat2);
                        final Matcher mt2 = pt2.matcher(js1);
                        func = null;
                        if (mt2.find(0))
                        {
                            func = mt2.group(2);
                        }
                        else
                        {
                            final String fp3 = "\\(([A-Za-z]+)\\(\\(0,window.decodeURIComponent";
                            pt = Pattern.compile(fp3);
                            final Matcher mt3 = pt.matcher(js1);
                            if (mt3.find(0))
                            {
                                func = mt3.group(1);
                            }
                        }
                    }
                }
            }
            return func;
        }
    
        // Test
        public static void main(String args[])
        {
            final String rawSignature = "C98C987F29D5CC5C651A6FB867EFC316D09CDF015983.E7C61471A1569DEE963C2FB55B025B2FE63CD32929929";
            final String expRes = "923DC36EF2B520B59BF2C369EED9651A17416C7E.38C510FDC90D613CFE768BF6A156C5CC5D92F785";
            final String jsUrl = "http://s.ytimg.com/yts/jsbin/player-vflI0cIzU/de_DE/base.js";
    
            final String signature = new SignatureDecoder().decode(jsUrl, rawSignature);
    
            System.out.println("\nExpected:  " + expRes);
            System.out.println("Evaluated: " + signature);
    
            System.out.print("Test ");
            if (signature != null && expRes.equals(signature))
            {
                System.out.println("OK");
            }
            else
            {
                System.out.println("FAILED");
            }
    
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-23
      • 2015-03-06
      • 1970-01-01
      • 2013-03-25
      • 2014-11-20
      • 1970-01-01
      • 2012-09-19
      相关资源
      最近更新 更多