Appearance
Supporting Readium LCP DRM
Introduction
This guide details the steps you need to take in order 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 Kotlin Toolkit.
Create an EncryptionMethod capable of decrypting bytes from the publication. Remember to inflate the data if compressed.
kotlin
import 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:
kotlin
readingSystemEngine.loadEpub(
EpubResourceProviderLoadConfig(
resourceProvider,
readingSessionOptions,
hashSignature = publicationHashSignature,
encryptionMethods = listOf(lcpEncryptionMethod)
)
)iOS
Retrieve the LcpLicense from the LCP-protected EPUB publication asset following the guides on Swift Toolkit.
Create an EncryptionMethod capable of decrypting bytes from the publication. Remember to inflate the data if compressed.
swift
import 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:
swift
await readingSystemEngine.loadEpub(
config: EpubResourceProviderLoadConfig(
resourceProvider: resourceProvider,
readingSessionOptions: readingSessionOptions,
hashSignature: publicationHashSignature,
encryptionMethods: [lcpEncryptionMethod]
)
)