Place Holder

Needs to be reviewed


DPLA audiobook DRM check

The DRM check consists of three main parts.

  1. Valid period check, 
  2. license check and 
  3. signature verification.

Any of the above should be skipped if the required information does not exist in the book manifest.

All the drm check is performed in NYPLAudiobookToolkit - FeedbookDRMProcessor.swift

Valid Period check

  1. Extract the start and end date of the DRM rights valid period.
  2. Check if the current date is in between the dates.

License Check

  1. Extract LicenseCheckURL from the book manifest, then stores within the local property drmData.
  2. Access the LicenseCheckURL while playing the audiobook, a json object containing the DRM status should be returned.

If the status does not equal to ready or active, the check fails.

* If any error(including network error) happens when accessing the LicenseCheckURL, skip the drm check

Signature Verification

  1. Remove the signature part from the book manifest and extract the signature value for later use.
  2. Canonicalize the book manifest (without signature) into a string.
  3. Sign the canonicalized string with the Certificate(JWK) private key, and convert the signed data into a string.
  4. Compare the signature value and the signed data string, they need to match in order to pass the DRM check.

Readium reference on verifying the signature: https://readium.org/lcp-specs/releases/lcp/latest.html#55-validating-the-certificate-and-signature

Implementation Challenges

The Certificate being used in the Signature Verification - JWK private key, is not commonly seen on iOS clients.

In order to sign the data, we need to convert the JWK to SecKey (a form of key supported by Apple’s library).

The best way to do this is using a third-party library that converts JWK to SecKey, or JWK to PEM then we create the SecKey with PEM data.

As a workaround, we converted the JWK to a PEM offline, then embedded in our secret system within our iOS client. We store the PEM data in KeyChain once the app finishes launching.

And NYPLAudiobookToolkit retrieves the PEM data, creates a SecKey and signs the data when performing the DRM check.

Requirement Change

In theory, we should be able to use the API SecItemCopyMatching to retrieve the private key data from Keychain and cast the data to a SecKey object.

Instead of using SecItemCopyMatching and casting the data to SecKey directly, we are now doing it in two parts. First, we retrieve the private key data from KeyChain. Then we use SecKeyCreateWithData to create the SecKey, which gives an error if there are any issues. However, SecKeyCreateWithData has a minimum requirement of iOS 10.

Key Rotation

When/if DPLA decides to do rotation on the Certificate(JWK), we will:

  • Fetch the Certificate from the URL and cache the Certificate from time to time.
  • Fetch and refresh the cache when the response from the URL indicates it is expired.
  • No labels