【问题标题】:Golang AES decrypt video before streaming it though httpGolang AES 在通过 http 流式传输之前解密视频
【发布时间】:2017-04-08 20:49:55
【问题描述】:

我正在尝试流式传输 AES 加密的视频文件;但是我们需要在通过 http 流式传输之前动态解密它

如何将解密数据的输出写入http writer

 package main

        import (
            "crypto/aes"
            "crypto/cipher"
            "io"
            "log"
            "net/http"
            "os"
        )

        var key []byte = []byte("yourAESPrivateKey")

        func ServeHTTP(w http.ResponseWriter, r *http.Request) {
            inFile, err := os.Open("2.ts")
            if err != nil {
                log.Fatal(err)
            }
            defer inFile.Close()

            block, err := aes.NewCipher(key)
            if err != nil {
                log.Fatal(err)
                return
            }
            var iv [aes.BlockSize]byte
            stream := cipher.NewOFB(block, iv[:])
            w.Header().Set("Content-type", "video/mp4")
            writer := &cipher.StreamWriter{S: stream, W: w}

            if _, err := io.Copy(writer, inFile); err != nil {
                log.Fatal(err)
                return
            }

            //http.ServeContent(w, r, "video.mp4", time.Now(), inFile)
        }

        func main() {
            http.HandleFunc("/", ServeHTTP)
            http.ListenAndServe(":2020", nil)
        }

【问题讨论】:

  • 有人反对我,为什么?
  • 因为即使你做了解密,它也不行。你可以只读取一个 ts,解密它并告诉浏览器它的 mp4。你需要转换成可流式的分片格式,生成清单等。
  • 你的解密有问题吗?你的流媒体有问题吗?您预计会发生什么以及实际会发生什么?
  • 解密没问题,我的问题是:“如何将解密数据的输出写入http.ResponseWriter”

标签: go video-streaming aes


【解决方案1】:

我已经增强了我的代码

所以如果我请求一个加密文件,服务器将解密它并正确提供它,但是我有另一个问题如下

现在的问题是如果文件超过一定大小,我会得到损坏的文件。

出于调试目的,我对文本文件进行了一些测试,因此我可以在此处发布数据结果 (big corrupted file) 检查文件末尾

package main

        import (
            "crypto/aes"
            "crypto/cipher"
            "log"
            "net/http"
            "os"
            "time"
        )

        type cipherHttpWriter struct {
            http.ResponseWriter
        }

        func (c cipherHttpWriter) Write(b []byte) (int, error) {
            var key []byte = []byte("we!@09bsa$.a-ala.HJOqweK45aghf&A")
            block, err := aes.NewCipher(key)
            if err != nil {
                return 0, err
            }
            var iv [aes.BlockSize]byte
            stream := cipher.NewOFB(block, iv[:])
            streamWriter := &cipher.StreamWriter{S: stream, W: c.ResponseWriter}
            defer streamWriter.Close()
            return streamWriter.Write(b)
        }

        func ServeHTTP(w http.ResponseWriter, r *http.Request) {
            inFile, err := os.Open(string(r.URL.Path[1:]))
            if err != nil {
                log.Fatal(err)
            }
            defer inFile.Close()
            writer := cipherHttpWriter{}
            writer.ResponseWriter = w

            http.ServeContent(writer, r, "", time.Now(), inFile)
        }

        func main() {
            http.HandleFunc("/", ServeHTTP)
            http.ListenAndServe(":2020", nil)
        }

【讨论】:

  • 这行不通。解密的内容大小与 AES 加密的内容大小不匹配(由于 IV 和随机数,这取决于 aes 加密模式)。加密文件直接传递给 http.ServeContent,因此 http 内容范围请求(例如恢复下载)和报告给浏览器的文件大小都是加密文件大小,而不是解密文件大小。我已经编写了一个专有的 io.ReaderWriter,它可以在磁盘上的原始文件和加密文件之间进行自动 reader.seek(fileOffset int64) 转换。这将是一个可能的解决方案的开始。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-25
  • 2017-02-10
  • 1970-01-01
  • 2019-01-26
  • 1970-01-01
  • 1970-01-01
  • 2016-01-28
相关资源
最近更新 更多