Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

decryptSegment: no senc box in traf #298

Closed
3052 opened this issue Nov 22, 2023 · 10 comments
Closed

decryptSegment: no senc box in traf #298

3052 opened this issue Nov 22, 2023 · 10 comments

Comments

@3052
Copy link

3052 commented Nov 22, 2023

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
@tobbee
Copy link
Collaborator

tobbee commented Nov 22, 2023

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.

@tobbee
Copy link
Collaborator

tobbee commented Nov 22, 2023

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.

@tobbee
Copy link
Collaborator

tobbee commented Nov 30, 2023

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

@3052
Copy link
Author

3052 commented Dec 27, 2023

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)
   }

@tobbee
Copy link
Collaborator

tobbee commented Dec 27, 2023

@3052 There is now a PR handling this which produces a decrypted video, #310.
Could you provide a short file that I could include as a test case in the repo?

@3052
Copy link
Author

3052 commented Dec 27, 2023

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

@tobbee
Copy link
Collaborator

tobbee commented Dec 27, 2023

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.

@3052
Copy link
Author

3052 commented Dec 27, 2023

OK it should be 602a9289bfb9b1995b75ac63f123fc86 for both. I cant test right now, but if its not right let me know

@tobbee
Copy link
Collaborator

tobbee commented Dec 29, 2023

@3052 I consider this solved with #310 including tests with the new files provided. Thanks for reporting and helping out with test content.

@tobbee tobbee closed this as completed Dec 29, 2023
@3052
Copy link
Author

3052 commented Dec 29, 2023

confirmed fixed - thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants