#go #encryption #http-live-streaming
#Вперед #шифрование #http-прямая трансляция
Вопрос:
Я пытаюсь загружать и расшифровывать потоки 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 amp;amp; err == io.EOF {
break
else if err != nil amp;amp; 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 amp;amp; 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, amp;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
и обработке его порциями?
Комментарии:
1. Вы запускаете новый
CBCDecrypter
с начальнымIV
значением для каждого блока 8K. Это не так, как работает CBC ,IV
forblock n
— это зашифрованный текст fromblock n-1
. У вас должен быть только одинBlockMode
объект для всего файла. Вам также необходимо проверить, что у вас есть полные блоки.2. Я бы сказал, что основной причиной может быть то, что прочитанные фрагменты не обязательно соответствуют размеру блока. Я не вижу кода, обрабатывающего это. . кроме того (как уже отмечалось), вы должны управлять правильным IV и состоянием
Ответ №1:
Внутренне CBCDecrypter создает вашу копию iv
, поэтому последующие блоки начинаются с начального IV, а не с того, который был изменен предыдущими расшифровками.
Создайте дешифратор один раз, и вы сможете продолжать повторно использовать его для дешифрования блока за блоком (при условии, что размер блока кратен размеру блока, ожидаемому этим криптоалгоритмом).