no commit message

This commit is contained in:
niandeng
2020-09-17 18:40:01 +08:00
parent 4382915d09
commit d957abceaa
283 changed files with 86935 additions and 63 deletions
+175
View File
@@ -0,0 +1,175 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mangui.hls.utils {
import flash.utils.getTimer;
import flash.display.DisplayObject;
import flash.utils.ByteArray;
import flash.events.Event;
/**
* Contains Utility functions for AES-128 CBC Decryption
*/
public class AES {
private var _key : FastAESKey;
//private var _keyArray : ByteArray;
private var iv0 : uint;
private var iv1 : uint;
private var iv2 : uint;
private var iv3 : uint;
/* callback function upon decrypt progress */
private var _progress : Function;
/* callback function upon decrypt complete */
private var _complete : Function;
/** Byte data to be decrypt **/
private var _data : ByteArray;
/** read position **/
private var _readPosition : uint;
/** write position **/
private var _writePosition : uint;
/** chunk size to avoid blocking **/
private static const CHUNK_SIZE : uint = 2048;
/** is bytearray full ? **/
private var _dataComplete : Boolean;
/** display object used for ENTER_FRAME listener */
private var _displayObject : DisplayObject;
public function AES(displayObject : DisplayObject, key : ByteArray, iv : ByteArray, notifyprogress : Function, notifycomplete : Function) {
// _keyArray = key;
_key = new FastAESKey(key);
iv.position = 0;
iv0 = iv.readUnsignedInt();
iv1 = iv.readUnsignedInt();
iv2 = iv.readUnsignedInt();
iv3 = iv.readUnsignedInt();
_data = new ByteArray();
_dataComplete = false;
_progress = notifyprogress;
_complete = notifycomplete;
_readPosition = 0;
_writePosition = 0;
_displayObject = displayObject;
}
public function append(data : ByteArray) : void {
// CONFIG::LOGGING {
// Log.info("notify append");
// }
_data.position = _writePosition;
_data.writeBytes(data);
if (_writePosition == 0) {
_displayObject.addEventListener(Event.ENTER_FRAME, _decryptTimer);
}
_writePosition += data.length;
}
public function notifycomplete() : void {
// CONFIG::LOGGING {
// Log.info("notify complete");
// }
_dataComplete = true;
}
public function cancel() : void {
_displayObject.removeEventListener(Event.ENTER_FRAME, _decryptTimer);
}
private function _decryptTimer(e : Event) : void {
var start_time : int = getTimer();
var decrypted : Boolean;
do {
decrypted = _decryptChunk();
// dont spend more than 10ms in the decrypt timer to avoid blocking/freezing video
// if frame rate is 60fps, we have 1000/60 = 16.6ms budget total per frame
} while (decrypted && (getTimer() - start_time) < 10);
}
/** decrypt a small chunk of packets each time to avoid blocking **/
private function _decryptChunk() : Boolean {
_data.position = _readPosition;
var decryptdata : ByteArray;
if (_data.bytesAvailable) {
if (_data.bytesAvailable <= CHUNK_SIZE) {
if (_dataComplete) {
// CONFIG::LOGGING {
// Log.info("data complete, last chunk");
// }
_readPosition += _data.bytesAvailable;
decryptdata = _decryptCBC(_data, _data.bytesAvailable);
unpad(decryptdata);
} else {
// data not complete, and available data less than chunk size, return
return false;
}
} else {
_readPosition += CHUNK_SIZE;
decryptdata = _decryptCBC(_data, CHUNK_SIZE);
}
_progress(decryptdata);
return true;
} else {
if (_dataComplete) {
CONFIG::LOGGING {
Log.debug("AES:data+decrypt completed, callback");
}
// callback
_complete();
_displayObject.removeEventListener(Event.ENTER_FRAME, _decryptTimer);
}
return false;
}
}
/* Cypher Block Chaining Decryption, refer to
* http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher-block_chaining_
* for algorithm description
*/
private function _decryptCBC(crypt : ByteArray, len : uint) : ByteArray {
var src : Vector.<uint> = new Vector.<uint>(4);
var dst : Vector.<uint> = new Vector.<uint>(4);
var decrypt : ByteArray = new ByteArray();
decrypt.length = len;
for (var i : uint = 0; i < len / 16; i++) {
// read src byte array
src[0] = crypt.readUnsignedInt();
src[1] = crypt.readUnsignedInt();
src[2] = crypt.readUnsignedInt();
src[3] = crypt.readUnsignedInt();
// AES decrypt src vector into dst vector
_key.decrypt128(src, dst);
// CBC : write output = XOR(decrypted,IV)
decrypt.writeUnsignedInt(dst[0] ^ iv0);
decrypt.writeUnsignedInt(dst[1] ^ iv1);
decrypt.writeUnsignedInt(dst[2] ^ iv2);
decrypt.writeUnsignedInt(dst[3] ^ iv3);
// CBC : next IV = (input)
iv0 = src[0];
iv1 = src[1];
iv2 = src[2];
iv3 = src[3];
}
decrypt.position = 0;
return decrypt;
}
public function unpad(a : ByteArray) : void {
var c : uint = a.length % 16;
if (c != 0) throw new Error("PKCS#5::unpad: ByteArray.length isn't a multiple of the blockSize");
c = a[a.length - 1];
for (var i : uint = c; i > 0; i--) {
var v : uint = a[a.length - 1];
a.length--;
if (c != v) throw new Error("PKCS#5:unpad: Invalid padding value. expected [" + c + "], found [" + v + "]");
}
}
public function destroy() : void {
_key.dispose();
// _key = null;
}
}
}