decryptSegment: no senc box in traf
3052 opened this issue · comments
using this file (106 MB): http://0x0.st/Hwbc.mp4
I can decrypt like this:
> packager-win-x64 --enable_raw_key_decryption `
>> --keys key_id=21b82dc2ebb24d5aa9f8631f04726650:key=602a9289bfb9b1995b75ac63f123fc86 `
>> stream=video,in=enc.mp4,output=dec.mp4
[1121/225104:INFO:demuxer.cc(89)] Demuxer::Run() on file 'enc.mp4'.
[1121/225104:INFO:demuxer.cc(155)] Initialize Demuxer for file 'enc.mp4'.
[1121/225104:WARNING:track_run_iterator.cc(699)] Seeing non-zero composition offset 834167. An EditList is probably missing.
[1121/225104:WARNING:track_run_iterator.cc(703)] Adjusting timestamps by -834167. Please file a bug to https://github.com/google/shaka-packager/issues if you do not think it is right or if you are seeing any problems.
https://github.com/shaka-project/shaka-packager/releases
but these both fail:
mp4ff-decrypt -k 602a9289bfb9b1995b75ac63f123fc86 enc.mp4 dec.mp4
mp4ff-decrypt -k 602a9289bfb9b1995b75ac63f123fc86 -init enc.mp4 `
enc.mp4 dec.mp4
result:
2023/11/21 22:48:36 decryptSegment: no senc box in traf
Thanks for posting this.
For DASH and HLS, the normal place to put the encryption information in the segments is in a senc
box, and this is not the case in this file, but they seem to be placed in a [uuid] box instead. This is allowed, but not supported by mp4ff library at the moment. In principle the data can be put in any place given by the offset in the saio
box, but since I don't have positions on all boxes, it is not so easy to extract in general. I will look a bit more into it, but I cannot promise that it will be supported.
A second look reveals that this is a PIFF encrypted file according to the uuid: a2394f52-5a9b-4f14-a244-6c427c648df4
. In fact, the UUID box is a "Sample Encryption Box" according to the PIFF spec 1.1, which is very close to the structure of the senc
box in the Common Encryption Specification.
I've looked a bit more into this and the uuid box essentially contains a senc
box, and started some work on supporting it by reusing the SencBox
implementation.
The PIFF 1.1 spec describes the boxes. I cannot find it on the net any longer, although it says on page https://learn.microsoft.com/en-us/iis/media/smooth-streaming/protected-interoperable-file-format that it should be available.
I had an old copy so I put it here for reference:
Protected Interoperable File Format (PIFF) 1.1.pdf
OK I had written an implementation of PIFF based on:
https://github.com/yapingcat/gomedia
but I found out that module cannot read a segment file by itself, which means that it must parse init for every single segment, which is really wasteful. I also looked at https://github.com/abema/go-mp4, but it doesnt even support senc
box, never mind PIFF. so I ended up writing my own MP4 module from scratch, that supports CENC with both senc
and uuid
. here is a clip of the code if it helps:
case "uuid":
decode := func() bool {
if head.Extended_Type() == "a2394f525a9b4f14a2446c427c648df4" {
if b.Senc.Sample_Count == 0 {
return true
}
}
return false
}
if decode() {
b.Senc.BoxHeader = head
err := b.Senc.Decode(r)
if err != nil {
return err
}
} else {
value := Box{Header: head}
value.Payload = make([]byte, size)
_, err := io.ReadFull(r, value.Payload)
if err != nil {
return err
}
b.Boxes = append(b.Boxes, value)
}
here is audio init, audio segment, video init, video segment (230 KB total):
https://github.com/Eyevinn/mp4ff/files/13777792/PIFF.zip
also I have the keys if you need
Yes, it would be nice to have the keys. Then I could include both the encrypted and decrypted versions and make a test that the decryption is reproducible.
OK it should be 602a9289bfb9b1995b75ac63f123fc86
for both. I cant test right now, but if its not right let me know
confirmed fixed - thanks