{"action":"created","issue":{"url":"https://api.github.com/repos/google/ExoPlayer/issues/5083","repository_url":"https://api.github.com/repos/google/ExoPlayer","labels_url":"https://api.github.com/repos/google/ExoPlayer/issues/5083/labels{/name}","comments_url":"https://api.github.com/repos/google/ExoPlayer/issues/5083/comments","events_url":"https://api.github.com/repos/google/ExoPlayer/issues/5083/events","html_url":"https://github.com/google/ExoPlayer/issues/5083","id":379144683,"node_id":"MDU6SXNzdWUzNzkxNDQ2ODM=","number":5083,"title":"AesCipherDataSource unable to decrypt file.","user":{"login":"kozmabalazs","id":22748551,"node_id":"MDQ6VXNlcjIyNzQ4NTUx","avatar_url":"https://avatars2.githubusercontent.com/u/22748551?v=4","gravatar_id":"","url":"https://api.github.com/users/kozmabalazs","html_url":"https://github.com/kozmabalazs","followers_url":"https://api.github.com/users/kozmabalazs/followers","following_url":"https://api.github.com/users/kozmabalazs/following{/other_user}","gists_url":"https://api.github.com/users/kozmabalazs/gists{/gist_id}","starred_url":"https://api.github.com/users/kozmabalazs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kozmabalazs/subscriptions","organizations_url":"https://api.github.com/users/kozmabalazs/orgs","repos_url":"https://api.github.com/users/kozmabalazs/repos","events_url":"https://api.github.com/users/kozmabalazs/events{/privacy}","received_events_url":"https://api.github.com/users/kozmabalazs/received_events","type":"User","site_admin":false},"labels":[{"id":106814994,"node_id":"MDU6TGFiZWwxMDY4MTQ5OTQ=","url":"https://api.github.com/repos/google/ExoPlayer/labels/question","name":"question","color":"cc317c","default":true}],"state":"closed","locked":false,"assignee":{"login":"AquilesCanta","id":8539544,"node_id":"MDQ6VXNlcjg1Mzk1NDQ=","avatar_url":"https://avatars1.githubusercontent.com/u/8539544?v=4","gravatar_id":"","url":"https://api.github.com/users/AquilesCanta","html_url":"https://github.com/AquilesCanta","followers_url":"https://api.github.com/users/AquilesCanta/followers","following_url":"https://api.github.com/users/AquilesCanta/following{/other_user}","gists_url":"https://api.github.com/users/AquilesCanta/gists{/gist_id}","starred_url":"https://api.github.com/users/AquilesCanta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AquilesCanta/subscriptions","organizations_url":"https://api.github.com/users/AquilesCanta/orgs","repos_url":"https://api.github.com/users/AquilesCanta/repos","events_url":"https://api.github.com/users/AquilesCanta/events{/privacy}","received_events_url":"https://api.github.com/users/AquilesCanta/received_events","type":"User","site_admin":false},"assignees":[{"login":"AquilesCanta","id":8539544,"node_id":"MDQ6VXNlcjg1Mzk1NDQ=","avatar_url":"https://avatars1.githubusercontent.com/u/8539544?v=4","gravatar_id":"","url":"https://api.github.com/users/AquilesCanta","html_url":"https://github.com/AquilesCanta","followers_url":"https://api.github.com/users/AquilesCanta/followers","following_url":"https://api.github.com/users/AquilesCanta/following{/other_user}","gists_url":"https://api.github.com/users/AquilesCanta/gists{/gist_id}","starred_url":"https://api.github.com/users/AquilesCanta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AquilesCanta/subscriptions","organizations_url":"https://api.github.com/users/AquilesCanta/orgs","repos_url":"https://api.github.com/users/AquilesCanta/repos","events_url":"https://api.github.com/users/AquilesCanta/events{/privacy}","received_events_url":"https://api.github.com/users/AquilesCanta/received_events","type":"User","site_admin":false}],"milestone":null,"comments":3,"created_at":"2018-11-09T12:33:54Z","updated_at":"2018-11-12T18:07:26Z","closed_at":"2018-11-10T16:43:47Z","author_association":"NONE","body":"### Issue description\r\nI try to play encrypted audio content with ExoPlayer, but I am unable to figure out how AesCipherDataSource works. I copied the code from DefaultDataSource and I am wrapping DefaultHttpDataSource or FileDataSource with AesCipherDataSource to decode the stream. All the time I am getting UnrecognizedInputFormatException: None of the available extractors (...) could read the stream. As I read in other issues this is because the decryption failed. If I tried to copy the code from AesCipherDataSource and initialize both the key and IV with <key>.getBytes() than the decoding works, but the seeking is not. \r\n\r\nThese are my changes made to DefaultDataSource:\r\n\r\n```@Override\r\n    public long open(DataSpec dataSpec) throws IOException {\r\n        Assertions.checkState(dataSource == null);\r\n        if (Util.isLocalFileUri(dataSpec.uri)) {\r\n            dataSource = getCryptedDataSource(key, getFileDataSource());\r\n        } else {\r\n            dataSource = getCryptedDataSource(key, baseDataSource);\r\n        }\r\n        // Open the source and return.\r\n        return dataSource.open(dataSpec);\r\n    }\r\n\r\n    private DataSource getCryptedDataSource(String key, DataSource upstreamDataSource) {\r\n        if (aesCipherDataSource == null) {\r\n            aesCipherDataSource = new AesCipherDataSource(key.getBytes(), upstreamDataSource);\r\n            addListenersToDataSource(aesCipherDataSource);\r\n        }\r\n        return aesCipherDataSource;\r\n    }\r\n\r\n```\r\n\r\n### Reproduction steps\r\nDescribe how the issue can be reproduced, ideally using the ExoPlayer demo app.\r\n\r\n### Link to test content\r\nThe content is encrypted with \"AES/CTR/NoPadding\" using CipherOutputStream in java.\r\nkey: passwordpassword\r\nhttps://storage.googleapis.com/bucket_zoli/encrypted.mp3\r\n\r\n### Version of ExoPlayer being used\r\n2.9.0\r\n\r\n### Device(s) and version(s) of Android being used\r\nI tried on emulator and Samsung S7.\r\n\r\n### A full bug report captured from the device\r\n```\r\n2018-11-09 14:07:39.072 16307-16361/*********** E/ExoPlayerImplInternal: Source error.\r\n    com.google.android.exoplayer2.source.UnrecognizedInputFormatException: None of the available extractors (MatroskaExtractor, FragmentedMp4Extractor, Mp4Extractor, Mp3Extractor, AdtsExtractor, Ac3Extractor, TsExtractor, FlvExtractor, OggExtractor, PsExtractor, WavExtractor, AmrExtractor) could read the stream.\r\n        at com.google.android.exoplayer2.source.ExtractorMediaPeriod$ExtractorHolder.selectExtractor(ExtractorMediaPeriod.java:973)\r\n        at com.google.android.exoplayer2.source.ExtractorMediaPeriod$ExtractingLoadable.load(ExtractorMediaPeriod.java:891)\r\n        at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:379)\r\n        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)\r\n        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)\r\n        at java.lang.Thread.run(Thread.java:762)\r\n```\r\n"},"comment":{"url":"https://api.github.com/repos/google/ExoPlayer/issues/comments/437976602","html_url":"https://github.com/google/ExoPlayer/issues/5083#issuecomment-437976602","issue_url":"https://api.github.com/repos/google/ExoPlayer/issues/5083","id":437976602,"node_id":"MDEyOklzc3VlQ29tbWVudDQzNzk3NjYwMg==","user":{"login":"ojw28","id":7881572,"node_id":"MDQ6VXNlcjc4ODE1NzI=","avatar_url":"https://avatars1.githubusercontent.com/u/7881572?v=4","gravatar_id":"","url":"https://api.github.com/users/ojw28","html_url":"https://github.com/ojw28","followers_url":"https://api.github.com/users/ojw28/followers","following_url":"https://api.github.com/users/ojw28/following{/other_user}","gists_url":"https://api.github.com/users/ojw28/gists{/gist_id}","starred_url":"https://api.github.com/users/ojw28/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ojw28/subscriptions","organizations_url":"https://api.github.com/users/ojw28/orgs","repos_url":"https://api.github.com/users/ojw28/repos","events_url":"https://api.github.com/users/ojw28/events{/privacy}","received_events_url":"https://api.github.com/users/ojw28/received_events","type":"User","site_admin":false},"created_at":"2018-11-12T18:07:26Z","updated_at":"2018-11-12T18:07:26Z","author_association":"CONTRIBUTOR","body":"I was able to make it work by changing the `encryptFile` method to:\r\n\r\n```\r\nprivate void encryptFile(File file, String secretKey) {\r\n    try {\r\n        AssetManager am = this.getAssets();\r\n\r\n        // Fully read the input stream.\r\n        InputStream inputStream = am.open(\"sample_audio.mp3\");\r\n        byte[] inputStreamBytes = Util.toByteArray(inputStream);\r\n        inputStream.close();\r\n\r\n        // Create a sink that will encrypt and write to file.\r\n        AesCipherDataSink encryptingDataSink = new AesCipherDataSink(\r\n            Util.getUtf8Bytes(secretKey), new DataSink() {\r\n            FileOutputStream fileOutputStream;\r\n            @Override\r\n            public void open(DataSpec dataSpec) throws IOException {\r\n                fileOutputStream = new FileOutputStream(file);\r\n            }\r\n            @Override\r\n            public void write(byte[] buffer, int offset, int length) throws IOException {\r\n                fileOutputStream.write(buffer, offset, length);\r\n            }\r\n            @Override\r\n            public void close() throws IOException {\r\n                fileOutputStream.close();\r\n            }\r\n        });\r\n\r\n        // Push the data through the sink, and close everything.\r\n        encryptingDataSink.open(new DataSpec(Uri.fromFile(file)));\r\n        encryptingDataSink.write(inputStreamBytes, 0, inputStreamBytes.length);\r\n        encryptingDataSink.close();\r\n\r\n        Toast.makeText(this, \"File encrypted\", Toast.LENGTH_SHORT).show();\r\n    } catch (IOException e) {\r\n        e.printStackTrace();\r\n    }\r\n}\r\n```\r\nand then using the normal `AesCipherDataSource` (i.e. switching lines 105-106 in `CryptedDefaultDataSource`).\r\n\r\nSo the problem was with how you were encrypting. It's easiest to use `CipherDataSink`, since `CipherDataSink` and `CipherDataSource` are designed to be used together.\r\n\r\nIf you want you can also set the `key` in the `DataSpec` passed to `encryptingDataSink.open`. For example:\r\n```\r\nencryptingDataSink.open(\r\n    new DataSpec(Uri.fromFile(file), 0, inputStreamBytes.length, \"someKeyHere\"));\r\n```\r\nIf you do this you need to pass the same key to the `ExtractorMediaSource` for playback, like:\r\n```\r\nMediaSource mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory)\r\n    ....\r\n    .setCustomCacheKey(\"someKeyHere\")\r\n    .createMediaSource(...);\r\n```"}}
{"actor":{"display_login":"ojw28"}}