Android + exoplayer:本地播放AES加密视频
Posted
技术标签:
【中文标题】Android + exoplayer:本地播放AES加密视频【英文标题】:Android + exoplayer: play AES encrypted videos, locally 【发布时间】:2020-10-15 08:26:31 【问题描述】:在一个 linux 机器上,我有一个用 openssl 加密的 MP4 视频:
openssl enc -aes-128-ecb -a -in video.mp4 -out video.enc -K `cat aes.key`
请注意,这是一个练习,算法的强度并不重要。
该文件已发送到 android 应用程序,我正在尝试使用 ExoPlayer 播放它。
我事先对文本文件进行了一些测试,以确保解密工作正常
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
等之间有点压倒性。我无法组合一个简单的播放视频的方法。
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 提供视频后,需要进行哪些更改? (需要添加清单吗?标头?)
【问题讨论】:
【参考方案1】:这是解决方案。可能需要一些调整来处理跳帧、快进等,但这会播放AES/ECB/PKCS5Padding
加密视频
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加密视频的主要内容,如果未能解决你的问题,请参考以下文章