fixed building drm key url and AES-128 decoding

This commit is contained in:
Vologhat
2023-05-05 20:48:39 +03:00
committed by gdlbo
parent 683f0346e2
commit 6eae209d04
3 changed files with 25 additions and 25 deletions
@@ -70,7 +70,7 @@ public class M3UDownloader implements ITrackDownloader {
e.printStackTrace();
}
VKM3UParser parser = new VKM3UParser(payload);
VKM3UParser parser = new VKM3UParser(track.D.substring(0,track.D.lastIndexOf("/")+1),payload);
AtomicInteger progress = new AtomicInteger(0);
List<CompletableFuture<Void>> futures = new ArrayList<>(parser.mTransportStreams.size());
@@ -88,19 +88,23 @@ public class M3UDownloader implements ITrackDownloader {
final var ts=tses.get(i);
final var filename=i+".ts";
futures.add(CompletableFuture.runAsync(() -> {
InputStream mediaIs,keyPubIs;
mediaIs=keyPubIs=null;
try {
InputStream is = IOUtils.openStream(ts.getMediaSegmentUri());
mediaIs=IOUtils.openStream(ts.getMediaSegmentUri());
byte[] content;
if (ts.needDecoding()) {
String key = IOUtils.readAllLines(IOUtils.openStream(ts.getKeyURL()));
content = IOUtils.decodeStream(is, key);
keyPubIs=IOUtils.openStream(ts.getKeyURL());
content=IOUtils.decodeStream(mediaIs,IOUtils.readFully(keyPubIs));
} else {
content = IOUtils.readFully(is);
content=IOUtils.readFully(mediaIs);
}
File tsDump = new File(tsesDir,filename);
IOUtils.writeToFile(tsDump, content);
callback.onProgress(10 + Math.round(80.0f * progress.addAndGet(1) / tses.size()));
callback.onSizeReceived((long) content.length * tses.size(), parser.mHeapSize);
mediaIs.close();
keyPubIs.close();
} catch (IOException | NoSuchPaddingException | NoSuchAlgorithmException |
InvalidAlgorithmParameterException | InvalidKeyException e) {
callback.onFailure();
@@ -53,19 +53,19 @@ public class VKM3UParser {
final private String mData;
final public List<TransportStream> mTransportStreams = new ArrayList<>();
public VKM3UParser(String data) {
public VKM3UParser(String baseUri,String data) {
mData=data;
init();
init(baseUri);
}
public static boolean isTS(String str) {
return str.endsWith(".ts")||str.endsWith(".tp")||str.endsWith(".mpeg-ts")||str.endsWith(".m2ts");
return str.matches(".+\\.ts.*");
}
private void init()
private void init(String baseUri)
{
if(TextUtils.isEmpty(mData))throw new NullPointerException("mData==null");
final var scanner=new Scanner(mData);
if(TextUtils.isEmpty(mData))throw new NullPointerException("mData==null");
final var scanner=new Scanner(mData);
var line=scanner.nextLine();
if(!"#EXTM3U".equals(line))throw new IllegalStateException(String.format("Unknown initial M3U tag: %s",line));
//indicators for EXT-X-KEY and EXTINF tags
@@ -75,9 +75,7 @@ public class VKM3UParser {
* VK follows own URI attribute for EXT-X-KEY tag.
* @see <a href="https://datatracker.ietf.org/doc/html/rfc8216#section-4.3.2.4">EXT-X-KEY</a>
**/
String keyUri;
String baseUri;//At least one media segment must be encrypted to get the base uri
keyUri=baseUri="";
String keyUri="";
while(scanner.hasNextLine())
{
line=scanner.nextLine();
@@ -105,12 +103,12 @@ public class VKM3UParser {
else if(line.startsWith("#EXT-X-KEY:"))
{
var substr=line.substring(11);
if((aes128=substr.startsWith("METHOD=AES-128")))
if((aes128=substr.contains("METHOD=AES-128")))
{
substr=substr.substring(20,substr.length()-1);
if(!substr.startsWith("http"))throw new IllegalStateException(String.format("Failed to parse URI: %s",substr));
keyUri=substr;
baseUri=substr.substring(0,substr.lastIndexOf('/')+1);
substr=substr.substring(substr.indexOf('"')+1,substr.lastIndexOf('"'));
//TODO: supposed endpoint
keyUri=substr.startsWith("http")?substr:baseUri+substr;
Log.d("keyURL",keyUri);
}
}
else if(line.startsWith("#EXTINF"))
@@ -127,6 +125,5 @@ public class VKM3UParser {
else throw new RuntimeException(String.format("Failed to parse: %s",line));
mHeapSize+=line.getBytes().length;
}
if(baseUri.isEmpty())throw new NullPointerException("baseUri==null");
}
}
@@ -18,17 +18,16 @@ import java.util.Arrays;
public class IOUtils {
public static final int BUFFER_SIZE = 8192;
public static byte[] decodeStream(InputStream encIs, String keyURL)
public static byte[] decodeStream(InputStream encIs,byte[] aesKey)
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IOException {
CipherInputStream cip = new CipherInputStream(encIs, getCipher(keyURL));
CipherInputStream cip = new CipherInputStream(encIs, getCipher(aesKey));
return readFully(cip);
}
public static Cipher getCipher(String key)
public static Cipher getCipher(byte[] aesKey)
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
Key keySpec = new SecretKeySpec(key.getBytes(), "AES");
// bypassing ecb
Key keySpec = new SecretKeySpec(aesKey, "AES");
byte[] iv = new byte[16];
Arrays.fill(iv, (byte) 0x0);
IvParameterSpec ivps = new IvParameterSpec(iv);