使用 io.ReadFull 分块处理数据会导致文件损坏?

我正在尝试通过io.ReadFull以块的形式处理数据以节省内存来下载和解密 HLS 流:


为简单起见,省略了不相关的代码部分。


func main() {

    f, _ := os.Create(out.ts)


    for _, v := range mediaPlaylist {

        resp, _ := http.Get(v.URI)

        for {

            r, err := decryptHLS(key, iv, resp.Body)

            if err != nil && err == io.EOF {

                break

            else if err != nil && err != io.ErrUnexpectedEOF {

                panic(err)

            }

            io.Copy(f, r)

        }

    }

}


func decryptHLS(key []byte, iv []byte, r io.Reader) (io.Reader, error) {

    block, _ := aes.NewCipher(key)


    buf := make([]byte, 8192)


    mode := cipher.NewCBCDecrypter(block, iv)


        n, err := io.ReadFull(r, buf)

        if err != nil && err != io.ErrUnexpectedEOF {

                return nil, err

        }


    mode.CryptBlocks(buf, buf)


    return bytes.NewReader(buf[:n]), err

}

起初,这似乎可以正常工作,因为文件大小正确且下载过程中没有错误,但视频已损坏。不完全因为该文件仍被识别为视频,但图像和声音失真。


如果我更改要使用的代码ioutil.ReadAll,最终的视频文件将不再损坏:


func main() {

    f, _ := os.Create(out.ts)


    for _, v := range mediaPlaylist {

        resp, _ := http.Get(v.URI)

        segment, _ := ioutil.ReadAll(resp.Body)

        r, _ := decryptHLS(key, iv, &segment)

        io.Copy(f, r)

    }

}


func decryptHLS(key []byte, iv []byte, s *[]byte) io.Reader {

    block, _ := aes.NewCipher(key)


    mode := cipher.NewCBCDecrypter(block, iv)


    mode.CryptBlocks(*s, *s)


    return bytes.NewReader(*s)

}

任何想法为什么它在将整个段读入内存时正常工作,而不是io.ReadFull在块中使用和处理它时?


饮歌长啸
浏览 84回答 1
1回答

忽然笑

在内部, CBCDecrypter 会复制您的iv,因此后续块以初始 IV 开头,而不是由先前解密改变的那个。创建一次解密器,您应该能够继续重复使用它来逐块解密(假设块大小是此加密算法预期的块大小的倍数)。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go