Supporting Readium LCP DRM
Introduction
This guide details the steps you need to take in order to to load publications protected with the Readium LCP DRM in your app.
The guide assumes that you have included the Readium LCP package, and the private library you obtain by contacting EDRLab.
Android
Retrieve the
LcpLicense
from the LCP-protected EPUB publication asset following the guides on https://github.com/readium/kotlin-toolkit:Create an
EncryptionMethod
capable of decrypting bytes from the publication. Remember to inflate the data if compressed.KOTLINimport com.colibrio.core.drm.XmlEncryptionEntry import com.colibrio.core.io.base.ResourceMetadata import com.colibrio.readingsystem.base.EncryptionMethod import kotlinx.coroutines.runBlocking import org.readium.r2.lcp.LcpLicense import java.io.ByteArrayOutputStream import java.util.zip.Inflater class LcpEncryptionMethod(private val lcpLicense: LcpLicense) : EncryptionMethod { override val name: String = "http://www.w3.org/2001/04/xmlenc#aes256-cbc" override fun decrypt( encryptedBytes: ByteArray, encryptedResourceMetadata: ResourceMetadata, xmlEncryptionEntry: XmlEncryptionEntry ): ByteArray { val decryptedByteArray = runBlocking { lcpLicense.decrypt(encryptedBytes).getOrNull() } requireNotNull(decryptedByteArray) return if (xmlEncryptionEntry.encryptionProperties?.compressionMethod == DEFLATE_ALGORITHM) { inflateData( decryptedByteArray ) } else { decryptedByteArray } } private fun inflateData(deflatedData: ByteArray): ByteArray { val inflater = Inflater(true) inflater.setInput(deflatedData) val outputStream = ByteArrayOutputStream() val buffer = ByteArray(1024) try { while (!inflater.finished()) { val count = inflater.inflate(buffer) outputStream.write(buffer, 0, count) } } finally { inflater.end() } return outputStream.toByteArray() } companion object { private const val DEFLATE_ALGORITHM = 8 } }
Pass the encryption method when loading the EPUB file using the
ReadingSystemEngine
:KOTLINreadingSystemEngine.loadEpub( EpubResourceProviderLoadConfig( resourceProvider, readingSessionOptions, hashSignature = publicationHashSignature, encryptionMethods = listOf(lcpEncryptionMethod) ) )
iOS
Retrieve the
LcpLicense
from the LCP-protected EPUB publication asset following the guides on https://github.com/readium/swift-toolkit:Create an
EncryptionMethod
capable of decrypting bytes from the publication. Remember to inflate the data if compressed.SWIFTimport ColibrioReader import Foundation import ReadiumLCP enum EncryptionMethodError: Error { case decryptionFailed case inflationFailed } class LcpEncryptionMethod: EncryptionMethod { private static let deflateAlgorithm = 8 var name: String = "http://www.w3.org/2001/04/xmlenc#aes256-cbc" private let lcpLicense: LCPLicense init(lcpLicense: LCPLicense) { self.lcpLicense = lcpLicense } func decrypt( data: Data, resourceMetadata: ColibrioReader.ResourceMetadata, xmlEncryptionEntry: ColibrioReader.XmlEncryptionEntry, completion: @escaping (Result<Data, any Error>) -> Void ) { guard let decryptedData = try? lcpLicense.decipher(data) else { print("decryptionFailed") completion(.failure(EncryptionMethodError.decryptionFailed)) return } if xmlEncryptionEntry.encryptionProperties?.compressionMethod == LcpEncryptionMethod.deflateAlgorithm { guard let inflatedData = inflate(data: decryptedData) else { print("inflationFailed") completion(.failure(EncryptionMethodError.inflationFailed)) return } completion(.success(inflatedData)) } else { completion(.success(decryptedData)) } } func inflate(data: Data) -> Data? { return data.decompress(withAlgorithm: .zlib) } }
Pass the encryption method when loading the EPUB file using the
ReadingSystemEngine
:SWIFTreadingSystemEngine.loadEpub( EpubResourceProviderLoadConfig( resourceProvider, readingSessionOptions, hashSignature = publicationHashSignature, encryptionMethods = listOf(lcpEncryptionMethod) ) ) await readingSystemEngine.loadEpub( config: EpubResourceProviderLoadConfig( resourceProvider: resourceProvider, readingSessionOptions: readingSessionOptions, hashSignature: publicationHashSignature, encryptionMethods: [lcpEncryptionMethod] ) )