Лучший подход к декодированию сигнатуры шифрования Youtube с использованием PHP или JS
Youtube использует сигнатуру шифрования для некоторых видео, когда use_cipher_signature = true
в словаре, возвращаемом через
http://www.youtube.com/get_video_info?&video_id=Video_Id
Пример id: _JQH3G0cCtY
Шифрованная подпись - это фактически скремблированная подпись, которую любой может отлаживать несколькими наборами работающих подписей. Но Youtube продолжает менять скремблирующий алгоритм.
Я видел несколько загрузчиков видео Youtube, которые работают плавно, не затрагивая эту меняющуюся игру. Я думаю, что они проверяют игрока и извлекают декодер script из файла игрока, и, следовательно, он удерживает их.
Мне нужна некоторая помощь в использовании этой техники. Я знаю о программе "youtube-dl" - программе python для загрузки видео. Поскольку я не очень хорош в python, я думаю, что они используют один и тот же подход.
Также есть файл user-script JS, доступный здесь:
http://userscripts.org/scripts/show/25105, который делает то же самое.
Любая помощь по разумному подходу к расшифровке кода шифрования в PHP или JS будет оценена.
Ответы
Ответ 1
Структура URL и код шифрования продолжают меняться на Youtube. В настоящее время наилучший подход к декодированию сигнатуры шифрования объясняется ниже:
Шифрованная подпись в Youtube - это просто "скремблированная" подпись, которую вы должны переставить в соответствии с Алгоритмом, присутствующим в файле игрока (проигрыватель HTML5 или Flash Player).
Например, 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
};
Выше код расшифровки.
Но имейте в виду, что он продолжает меняться, когда они меняют файл плеера, поэтому вам нужно продолжать использовать файл проигрывателя.
Кроме того, чтобы загружать видео с помощью шифрованной подписи, вы должны позаботиться о отправке одинаковых файлов cookie, используя один и тот же заголовок пользовательского агента, отправив запрос с того же IP-адреса и отправив запрос вскоре после извлечения. Все это или требуется в какой-то момент
Если вас интересует алгоритм шифрования шифрования, посетите CipherAPI
Еще один классный API: TYstream API
Ответ 2
Ye old s.ytimg.com/yts/jsbin/html5player-vfltdb6U3.js
теперь 404, и новый URL-адрес, который, я думаю, немного похож на 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 и могу сделать с собой немного помощи, но, говоря об этом, в проекте кода вы попадаете в troube.
Ответ 3
Я перевел на Swift 3 ответ Akhilesh для людей iOS:
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 script (youtubedown от Jamie Zawinski), алгоритм меняется каждый раз, а script собирает список правил и алгоритмы в течение дней!. До сих пор в шифрах использовались только три команды, поэтому мы можем их компактно представить:
# - 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