使用 io.ReadFull 分块处理数据会导致文件损坏?
Processing data in chunks with io.ReadFull results in corrupted file?
我正在尝试下载和解密 HLS 流,方法是使用 io.ReadFull
分块处理数据以节省内存:
为简单起见,省略了不相关的代码部分。
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
并分块处理时却不能正常工作吗?
在内部,CBCDecrypter 会复制您的 iv
,因此后续块以初始 IV 开头,而不是被之前的解密变异的那个。
创建一次解密器,您应该能够re-using它逐块解密(假设块大小是此加密算法预期的块大小的倍数)。
我正在尝试下载和解密 HLS 流,方法是使用 io.ReadFull
分块处理数据以节省内存:
为简单起见,省略了不相关的代码部分。
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
并分块处理时却不能正常工作吗?
在内部,CBCDecrypter 会复制您的 iv
,因此后续块以初始 IV 开头,而不是被之前的解密变异的那个。
创建一次解密器,您应该能够re-using它逐块解密(假设块大小是此加密算法预期的块大小的倍数)。