github devine-dl/pywidevine v1.2.0

latest releases: v1.8.0, v1.7.0, v1.6.0...
23 months ago

Added

  • New CLI command serve that hosts a CDM API that can be externally accessed with authentication. This can be used to
    access and/or share your CDM without exposing your Widevine device private key, or even it's identity by enforcing
    Privacy Mode.
    • Requires installing with the serve extras, i.e., pip install pywidevine[serve].
    • The default host of 127.0.0.1 blocks access outside your network, even if port-forwarded. Use
      -h 0.0.0.0 to allow remote access.
    • Setup requires the use of a config file for configuring the CDM and authentication. An example config file named
      serve.example.yml in the project root folder has verbose documentation on available options.
  • Batch migration of WVD files by passing a folder as the path to the CLI command migrate.
  • Strict mode to PSSH.get_as_box() to raise an Exception if passed data is not already a box, as it has been improved
    to create a new box if not detected as a box already.

Changed

  • Elevated the Development Status Classifier from 4 (Beta) to 5 (Production/Stable).
  • License messages passed to Cdm.parse_license() are now rejected if they are not of LICENSE type.
  • Service Certificates passed to Cdm.set_service_certificate() are now verified. This patches a trivial "exploit"
    that allows an attacker to recover the plaintext Client ID from a license under Privacy Mode. See
    https://gist.github.com/rlaphoenix/74acabdd7269a21845e18b621c5860ef.
  • Data passed to PSSH.get_as_box() now supports arbitrary and box data automatically as it tries to detect if it is a
    valid box, otherwise makes a new box.
  • Renamed the Cdm constructor's parameter pssh to init_data, as that's what the Cdm actually wants and uses,
    whereas a PSSH is an mp4 atom (aka box) containing init_data (a Widevine CENC Header). The full PSSH is never
    kept nor ever used. It still accepts PSSH box data.
  • Service Certificate's Provider ID is now returned by Cdm.set_service_certificate() instead of the passed
    certificate, of which they would already have.
  • The Cdm class now works more closely to the official CDM model. Instead of using one Cdm object per-request having to
    provide device information each time,
    • You now initialize the Cdm with the Widevine device you wish to use and then open sessions with Cdm.open().
    • You will receive a session ID that are then passed to other methods of the same Cdm object.
    • The PSSH/init_data that used to be passed to the constructor is now passed to Cdm.get_license_challenge().
    • This allows initializing one Cdm object with up to 50 sessions open at the same time.
      Session limits seem to fluctuate between libraries and devices. 50 seems like a permissive value.
    • Once you are finished with DRM operations, discard all session (and key) data by calling Cdm.close(session_id).
  • License Keys are no longer returned by Cdm.parse_license() and now must be obtained directly from cdm._sessions.
    • For example, for key in cdm._sessions[session_id].keys: print(f"[{key.type}] {key.kid.hex}:{key.key.hex()}").
    • This is to detach the action of parsing a license as just for getting keys, as it isn't. It can be and should be
      used for a lot more data like security requirements like HDCP, expiration, and more.
    • It is also to detour users from directly using the keys over the Cdm.decrypt() method.
  • Various std-lib exceptions have been replaced with custom exceptions under pywidevine.exceptions.
  • License responses can now only be parsed once by Cdm.parse_license(). Any further attempts will raise an
    InvalidContext exception.
    • This is as license context data is cleared once used to reduce data lingering in memory, otherwise the more license
      requests you make without closing the session, the more and more memory is taken up.
    • Open multiple sessions in the same Cdm object if you need to request and parse multiple licenses on the same device.

Removed

  • Direct DrmCertificates are no longer supported by Cdm.set_service_certificate() as they have no signature.
    See the 3rd Change above. Provide either a SignedDrmCertificate or a SignedMessage containing a
    SignedDrmCertificate. A SignedMessage containing a DrmCertificate will also be rejected.
  • PSSH.from_init_data(), use PSSH.get_as_box().
  • raw parameter of Cdm constructor, as well as CLI commands as it is now handled upstream by the PSSH creation.

Fixed

  • Detection of Widevine CENC Header data encoded as bytes in PSSH.get_as_box().
  • Custom ValueError on missing contexts instead of the generic KeyError in Cdm.parse_license().
  • Typing of type_ parameter in Cdm.get_license_challenge().
  • Value of type_ parameter if is a string in Cdm.get_license_challenge().

Don't miss a new pywidevine release

NewReleases is sending notifications on new releases.