{"action":"created","issue":{"url":"https://api.github.com/repos/IDPF/epub-revision/issues/646","repository_url":"https://api.github.com/repos/IDPF/epub-revision","labels_url":"https://api.github.com/repos/IDPF/epub-revision/issues/646/labels{/name}","comments_url":"https://api.github.com/repos/IDPF/epub-revision/issues/646/comments","events_url":"https://api.github.com/repos/IDPF/epub-revision/issues/646/events","html_url":"https://github.com/IDPF/epub-revision/issues/646","id":127244350,"number":646,"title":"OCF encryption.xml - \"compress resources before encrypt\" rule should be optional, and additional 'original size' metadata is needed","user":{"login":"danielweck","id":625201,"avatar_url":"https://avatars.githubusercontent.com/u/625201?v=3","gravatar_id":"","url":"https://api.github.com/users/danielweck","html_url":"https://github.com/danielweck","followers_url":"https://api.github.com/users/danielweck/followers","following_url":"https://api.github.com/users/danielweck/following{/other_user}","gists_url":"https://api.github.com/users/danielweck/gists{/gist_id}","starred_url":"https://api.github.com/users/danielweck/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danielweck/subscriptions","organizations_url":"https://api.github.com/users/danielweck/orgs","repos_url":"https://api.github.com/users/danielweck/repos","events_url":"https://api.github.com/users/danielweck/events{/privacy}","received_events_url":"https://api.github.com/users/danielweck/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/IDPF/epub-revision/labels/Spec-OCF","name":"Spec-OCF","color":"c7def8"}],"state":"open","locked":false,"assignee":{"login":"danielweck","id":625201,"avatar_url":"https://avatars.githubusercontent.com/u/625201?v=3","gravatar_id":"","url":"https://api.github.com/users/danielweck","html_url":"https://github.com/danielweck","followers_url":"https://api.github.com/users/danielweck/followers","following_url":"https://api.github.com/users/danielweck/following{/other_user}","gists_url":"https://api.github.com/users/danielweck/gists{/gist_id}","starred_url":"https://api.github.com/users/danielweck/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danielweck/subscriptions","organizations_url":"https://api.github.com/users/danielweck/orgs","repos_url":"https://api.github.com/users/danielweck/repos","events_url":"https://api.github.com/users/danielweck/events{/privacy}","received_events_url":"https://api.github.com/users/danielweck/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/IDPF/epub-revision/milestones/1","html_url":"https://github.com/IDPF/epub-revision/milestones/EPUB%203.1","labels_url":"https://api.github.com/repos/IDPF/epub-revision/milestones/1/labels","id":1392142,"number":1,"title":"EPUB 3.1","description":"Major revision to the EPUB 3 standard","creator":{"login":"mattgarrish","id":1565164,"avatar_url":"https://avatars.githubusercontent.com/u/1565164?v=3","gravatar_id":"","url":"https://api.github.com/users/mattgarrish","html_url":"https://github.com/mattgarrish","followers_url":"https://api.github.com/users/mattgarrish/followers","following_url":"https://api.github.com/users/mattgarrish/following{/other_user}","gists_url":"https://api.github.com/users/mattgarrish/gists{/gist_id}","starred_url":"https://api.github.com/users/mattgarrish/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattgarrish/subscriptions","organizations_url":"https://api.github.com/users/mattgarrish/orgs","repos_url":"https://api.github.com/users/mattgarrish/repos","events_url":"https://api.github.com/users/mattgarrish/events{/privacy}","received_events_url":"https://api.github.com/users/mattgarrish/received_events","type":"User","site_admin":false},"open_issues":67,"closed_issues":50,"state":"open","created_at":"2015-11-03T20:20:24Z","updated_at":"2016-04-13T16:06:46Z","due_on":"2016-10-01T04:00:00Z","closed_at":null},"comments":11,"created_at":"2016-01-18T15:02:08Z","updated_at":"2016-04-14T13:28:58Z","closed_at":null,"body":"The EPUB3 / OCF specification states:\r\n> When stored in a ZIP container, streams of data **MUST** be compressed before they are encrypted and Deflate compression must be used. Within the ZIP directory, encrypted files should be stored rather than Deflate-compressed.\r\n\r\nhttp://www.idpf.org/epub/301/spec/epub-ocf.html#sec-container-metainf-encryption.xml\r\n\r\nBased on feedback received from several DRM implementors (more precisely, in the context of Readium LCP, see https://github.com/readium/readium-sdk/issues/162 ), there are two significant problems in the OCF specification:\r\n\r\n1. When a file is deflate-compressed, then encrypted, then stored (uncompressed) inside the EPUB zip archive, there is no trivial and efficient method (from a performance standpoint) to retrieve the length of the original file (i.e. inflated/uncompressed, non-encrypted resource). One notable use-case: as HTTP byte-range requests occur during audio/video playback (i.e. media \"streaming\"), responses generated by Readium SDK include decrypted chunks of binary data, and HTTP headers are populated with the full size of original / decoded resources.\r\nA possible solution would be to store additional metadata in `encryption.xml`, using `EncryptionProperty` extensions (more details below).\r\n2. Media codecs already efficiently compress data (audio/video, but also image formats). To require deflate-compression before encryption is not only unnecessary, this also increases production costs (most notably with large audio/video files) and impacts decoding performance in reading systems.\r\nA possible solution would be to make the “deflate-compression before encryption” conformance requirement optional (currently a MUST). Furthermore, some additional metadata in `encryption.xml` would be needed to identify compressed+encrypted files that are stored (uncompressed) in the EPUB archive (note that compression-efficient codecs would also justify stored entries in the zip catalog). Once again, `EncryptionProperty` extensions could be used.\r\n\r\nSo, here is a concrete proposal for `encryption.xml`:\r\n\r\n```xml\r\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n\r\n<encryption xmlns=\"urn:oasis:names:tc:opendocument:xmlns:container\">\r\n    <enc:EncryptedData xmlns:enc=\"http://www.w3.org/2001/04/xmlenc#\">\r\n...\r\n        <enc:CipherData>\r\n            <enc:CipherReference URI=\"OEPBS/video.mp4\"/>\r\n        </enc:CipherData>\r\n        <enc:EncryptionProperties>\r\n            <enc:EncryptionProperty xmlns:ns=\"http://idpf.org/ocf/encryption#compression\">\r\n                <ns:Compression Method=\"8\" OriginalLength=\"0123456789\"/>\r\n            </enc:EncryptionProperty>\r\n        </enc:EncryptionProperties>\r\n...\r\n    </enc:EncryptedData>\r\n</encryption>\r\n```\r\n\r\n\r\nLet’s “zoom” into the relevant parts:\r\n\r\n```xml\r\n<enc:EncryptionProperty xmlns:ns=\"http://idpf.org/ocf/encryption#compression\">\r\n    <ns:Compression Method=\"8\" OriginalLength=\"0123456789\"/>\r\n</enc:EncryptionProperty>\r\n```\r\n\r\nThe suggested `ns` namespace prefix and URI is obviously just an illustration. To be agreed upon.\r\n\r\nBoth proposed attributes would take positive integer values:\r\n\r\n`Compression@Method` = `0` means “no compression prior to encryption”.\r\n`Compression@Method` = `8` means “deflate-compression prior to encryption”.\r\n(other values may be used in the future, e.g. for compression algorithms other than deflate)\r\n\r\n`Compression@OriginalLength` = length in bytes.\r\n"},"comment":{"url":"https://api.github.com/repos/IDPF/epub-revision/issues/comments/209940940","html_url":"https://github.com/IDPF/epub-revision/issues/646#issuecomment-209940940","issue_url":"https://api.github.com/repos/IDPF/epub-revision/issues/646","id":209940940,"user":{"login":"danielweck","id":625201,"avatar_url":"https://avatars.githubusercontent.com/u/625201?v=3","gravatar_id":"","url":"https://api.github.com/users/danielweck","html_url":"https://github.com/danielweck","followers_url":"https://api.github.com/users/danielweck/followers","following_url":"https://api.github.com/users/danielweck/following{/other_user}","gists_url":"https://api.github.com/users/danielweck/gists{/gist_id}","starred_url":"https://api.github.com/users/danielweck/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danielweck/subscriptions","organizations_url":"https://api.github.com/users/danielweck/orgs","repos_url":"https://api.github.com/users/danielweck/repos","events_url":"https://api.github.com/users/danielweck/events{/privacy}","received_events_url":"https://api.github.com/users/danielweck/received_events","type":"User","site_admin":false},"created_at":"2016-04-14T13:28:58Z","updated_at":"2016-04-14T13:28:58Z","body":"\r\nFOR REFERENCE ONLY:\r\n\r\nhttps://github.com/IDPF/epubcheck/blob/master/src/main/resources/com/adobe/epubcheck/schema/30/mod/security/xenc-schema.rnc\r\n\r\n```rng\r\nxenc_EncryptionProperties =\r\n  element EncryptionProperties { xenc_EncryptionPropertiesType }\r\nxenc_EncryptionPropertiesType =\r\n  attribute Id { xenc_IdType }?,\r\n  xenc_EncryptionProperty+\r\nxenc_EncryptionProperty =\r\n  element EncryptionProperty { xenc_EncryptionPropertyType }\r\nxenc_EncryptionPropertyType =\r\n  mixed {\r\n    attribute Target { xsd:anyURI }?,\r\n    attribute Id { xenc_IdType }?,\r\n    attribute xml:* { text }*,\r\n    xenc_anyForeignElement+\r\n  }\r\n```\r\n\r\n\r\nhttps://www.w3.org/TR/xmlenc-core/#sec-EncryptionProperties \r\nhttps://www.w3.org/TR/xmlenc-core/xenc-schema.xsd \r\n\r\n```xsd\r\n<element name=\"EncryptionProperties\" type=\"xenc:EncryptionPropertiesType\"/>\r\n<complexType name=\"EncryptionPropertiesType\">\r\n<sequence>\r\n<element ref=\"xenc:EncryptionProperty\" maxOccurs=\"unbounded\"/>\r\n</sequence>\r\n<attribute name=\"Id\" type=\"ID\" use=\"optional\"/>\r\n</complexType>\r\n\r\n<element name=\"EncryptionProperty\" type=\"xenc:EncryptionPropertyType\"/>\r\n<complexType name=\"EncryptionPropertyType\" mixed=\"true\">\r\n<choice maxOccurs=\"unbounded\">\r\n<any namespace=\"##other\" processContents=\"lax\"/>\r\n</choice>\r\n<attribute name=\"Target\" type=\"anyURI\" use=\"optional\"/>\r\n<attribute name=\"Id\" type=\"ID\" use=\"optional\"/>\r\n<anyAttribute namespace=\"http://www.w3.org/XML/1998/namespace\"/>\r\n</complexType>\r\n```"}}