Android + exoplayer:在本地播放AES加密的视频 [英] Android + exoplayer: play AES encrypted videos, locally
问题描述
在Linux机器上,我有一个用openssl加密的MP4视频:
On a linux box, I have an MP4 video that is encrypted with openssl:
openssl enc -aes-128-ecb -a -in video.mp4 -out video.enc -K `cat aes.key`
请注意,这是一种练习,算法的强度无关紧要.
Please note, this is an exercise, the strength of the algo doesn't matter.
该文件已发送到Android应用,我正在尝试使用ExoPlayer播放它.
That file is sent to an Android app, and I'm trying to play it using ExoPlayer.
我事先对文本文件做了一些测试,以确保解密工作正常
I've done some tests beforehand with text files to make sure the decryption was working properly
fun decrypt(key: ByteArray, data: ByteArray): ByteArray {
val spec = SecretKeySpec(key, "AES")
val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
cipher.init(Cipher.DECRYPT_MODE, spec)
globalCipher.init(Cipher.DECRYPT_MODE, spec)
return cipher.doFinal(data)
}
关于ExoPlayer, AesCipherDataSource
, AesCipherDataSink
, SimpleCache
等之间有点不知所措.播放视频.
Regarding ExoPlayer, it's a bit overwhelming between AesCipherDataSource
, AesCipherDataSink
, SimpleCache
etc. I was not able to put together a simple way to play the video.
fun playVideo() {
val player = SimpleExoPlayer.Builder(this).build()
playerView.player = player
val dataSourceFactory = DefaultDataSourceFactory? // <-- what's the factory?
val dataSource = AesCipherDataSource(globalCipher, ?) // <-- what's the data source?
val extractorsFactory: ExtractorsFactory = DefaultExtractorsFactory()
try {
val uri = Uri.fromFile(File(path, "video.enc"))
val videoSource =
ExtractorMediaSource(uri, dataSourceFactory, extractorsFactory, null, null)
player.prepare(videoSource)
player.playWhenReady = true
} catch (e: Exception) {
e.printStackTrace()
}
}
那么问题:
- 如何实现在本地播放此加密视频?
- 通过HTTP提供视频后,需要进行哪些更改?(需要添加清单吗?标头?)
推荐答案
这是解决方案.可能需要进行一些调整才能处理跳帧,快进等问题,但这会播放 AES/ECB/PKCS5Padding
加密视频
here's the solution. Might need some adjustments to handle skipping frames, fast forward etc, but this plays an AES/ECB/PKCS5Padding
encrypted video
class EncryptedDataSourceFactory(
private val key: String
) : DataSource.Factory {
override fun createDataSource(): EncryptedDataSource =
EncryptedDataSource(key)
}
class EncryptedDataSource(private val key: String) : DataSource {
private var inputStream: CipherInputStream? = null
private lateinit var uri: Uri
override fun addTransferListener(transferListener: TransferListener) {}
override fun open(dataSpec: DataSpec): Long {
uri = dataSpec.uri
try {
val file = File(uri.path)
val skeySpec = SecretKeySpec(key.toByteArray(), KeyProperties.KEY_ALGORITHM_AES)
val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
cipher.init(Cipher.DECRYPT_MODE, skeySpec)
inputStream = CipherInputStream(file.inputStream(), cipher)
} catch (e: Exception) {
}
return dataSpec.length
}
@Throws(IOException::class)
override fun read(buffer: ByteArray, offset: Int, readLength: Int): Int =
if (readLength == 0) {
0
} else {
inputStream?.read(buffer, offset, readLength) ?: 0
}
override fun getUri(): Uri? =
uri
@Throws(IOException::class)
override fun close() {
inputStream?.close()
}
}
private fun playVideo(key: String) {
val player = SimpleExoPlayer.Builder(this).build()
playerView.player = player
val dataSourceFactory: DataSource.Factory = EncryptedDataSourceFactory(key)
val extractorsFactory: ExtractorsFactory = DefaultExtractorsFactory()
try {
val uri = Uri.fromFile(video)
val videoSource: MediaSource = ExtractorMediaSource(uri, dataSourceFactory, extractorsFactory, null, null)
player.prepare(videoSource)
player.playWhenReady = true
} catch (e: Exception) {
e.printStackTrace()
}
}
这篇关于Android + exoplayer:在本地播放AES加密的视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!