function Decrypt($data, $pos, $opt = array()) { /** @var cURL $cc */ $auth = ""; $baseUrl = ""; $cc = null; extract($opt, EXTR_IF_EXISTS); $debug = $this->debug; if ($this->decryptorTest) { $debug = false; } LogDebug("\n----- Akamai Decryption Start -----", $debug); // Parse packet header $byte = ReadByte($data, $pos++); $this->ecmVersion = $byte >> 4; if ($this->ecmVersion != 11) { $this->ecmVersion = $byte; } $this->ecmID = ReadInt32($data, $pos); $this->ecmTimestamp = ReadInt32($data, $pos + 4); $this->kdfVersion = ReadInt16($data, $pos + 8); $pos += 10; $this->dccAccReserved = ReadByte($data, $pos++); LogDebug("ECM Version : " . $this->ecmVersion . ", ECM ID: " . $this->ecmID . ", ECM Timestamp: " . $this->ecmTimestamp . ", KDF Version: " . $this->kdfVersion . ", DccAccReserved: " . $this->dccAccReserved, $debug); $byte = ReadByte($data, $pos++); $iv = ($byte & 2) > 0 ? true : false; $key = ($byte & 4) > 0 ? true : false; if ($iv) { $this->packetIV = substr($data, $pos, 16); $pos += 16; LogDebug("PacketIV : " . hexlify($this->packetIV), $debug); } if ($key) { $this->sessionKeyUrl = ReadString($data, $pos); LogDebug("SessionKeyUrl: " . $this->sessionKeyUrl, $debug); $keyUrl = substr($this->sessionKeyUrl, strrpos($this->sessionKeyUrl, '/')); $this->sessionID = "_" . substr($keyUrl, strlen("/key_")); $keyUrl = JoinUrl($baseUrl, $keyUrl) . $auth; // Download key file if required if ($this->sessionKeyUrl !== $this->lastKeyUrl) { if ($baseUrl == "") { LogDebug("Unable to download session key without manifest url. you must specify it manually using 'adkey' switch.", $debug); } else { if ($cc->get($keyUrl) != 200) { LogError("Failed to download akamai session decryption key"); } $this->sessionKey = $cc->response; LogInfo("SessionKey: " . hexlify($this->sessionKey), $debug); $this->lastKeyUrl = $this->sessionKeyUrl; } } } LogDebug("SessionKey : " . hexlify($this->sessionKey), $debug); $reserved = ReadByte($data, $pos++); $this->packetSalt = substr($data, $pos, 32); $pos += 32; $reservedBlock1 = substr($data, $pos, 20); $reservedBlock2 = substr($data, $pos + 20, 20); $pos += 40; LogDebug("ReservedByte : " . $reserved . ", ReservedBlock1: " . hexlify($reservedBlock1) . ", ReservedBlock2: " . hexlify($reservedBlock2), $debug); // Generate packet decryption key if ($this->sessionKey == "") { LogError("Fragments can't be decrypted properly without corresponding session key.", 2); } $this->KDF(); // Decrypt packet data $encryptedData = substr($data, $pos); LogDebug("EncryptedData: " . hexlify(substr($encryptedData, 0, 64)), $debug); $lastBlockData = substr($encryptedData, $this->decryptBytes); $encryptedData = substr($encryptedData, 0, $this->decryptBytes); $decryptedData = ""; if ($this->decryptBytes > 0) { mcrypt_generic_init($this->aes_cbc, $this->packetKey, $this->packetIV); $decryptedData = mdecrypt_generic($this->aes_cbc, $encryptedData); mcrypt_generic_deinit($this->aes_cbc); } $decryptedData .= $lastBlockData; LogDebug("DecryptedData: " . hexlify(substr($decryptedData, 0, 64)), $debug); LogDebug("----- Akamai Decryption End -----\n", $debug); return $decryptedData; }
$file = false; if (file_exists($beatFile)) { $file = file_get_contents($beatFile); } if ($file === false) { LogError("Failed to open input file"); } $fileLen = filesize($beatFile); $filePos = 0; $fileSize = $fileLen / (1024 * 1024); $pFilePos = 0; // Parse beat file header $flags = ReadByte($file, 0); $quality = $flags & 15; $version = $flags >> 4; $lookupSize = ReadInt16($file, 1); $encTable = substr($file, 3, $lookupSize); $filePos = $filePos + 3 + $lookupSize; LogDebug("Version: {$version}, Quality: {$quality}, LookupSize: {$lookupSize}"); // Retrieve encryption key and iv $key = ""; $iv = ""; for ($i = 0; $i < 32; $i += 2) { $key .= $file[$filePos + $i]; $iv .= $file[$filePos + $i + 1]; } $filePos += 32; LogDebug("Key: " . hexlify($key)); LogDebug("IV : " . hexlify($iv)); // Decrypt lookup table $td = mcrypt_module_open('rijndael-128', '', 'cbc', '');