Skip to content
This repository has been archived by the owner on Jul 29, 2022. It is now read-only.

Check hashed passphrase returned by LCPAuthenticating #64

Merged
merged 2 commits into from
Apr 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ interface LCPAuthenticating {
* @param license Information to show to the user about the license being opened.
* @param reason Reason why the passphrase is requested. It should be used to prompt the user.
* @param completion Used to return the retrieved passphrase. If the user cancelled, send nil.
* The passphrase may be already hashed.
*/
fun requestPassphrase(license: LCPAuthenticatedLicense, reason: LCPAuthenticationReason, completion: (String?) -> Unit)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,12 @@ internal class LCPLLicenseContainer(private val lcpl: String? = null, private va

var publication: String? = null

override fun read() : ByteArray {
return lcpl?.let {
URL(Uri.parse(it).toString()).openStream().readBytes()
} ?: run {
byteArray?.let {
it
} ?:run {
ByteArray(0)
}
override fun read() : ByteArray =
if (lcpl != null) {
URL(Uri.parse(lcpl).toString()).openStream().readBytes()
} else {
byteArray ?: ByteArray(0)
}
}

override fun write(license: LicenseDocument) {
publication?.let {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ internal class DeviceService(private val repository: DeviceRepository, private v
completion(null)
} else {
// TODO templated url
val url = link.url(asQueryParameters).toString() ?: throw LCPError.licenseInteractionNotAvailable
val url = link.url(asQueryParameters).toString()

network.fetch(url, method = NetworkService.Method.post, params = asQueryParameters) { status, data ->
if (status != 200) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ package org.readium.r2.lcp.service
import com.mcxiaoke.koi.HASH
import kotlinx.coroutines.runBlocking
import org.readium.lcp.sdk.Lcp
import org.readium.r2.lcp.LCPAuthenticatedLicense
import org.readium.r2.lcp.LCPAuthenticating
import org.readium.r2.lcp.LCPAuthenticationReason
import org.readium.r2.lcp.license.model.LicenseDocument
import org.readium.r2.lcp.public.LCPAuthenticatedLicense
import org.readium.r2.lcp.public.LCPAuthenticating
import org.readium.r2.lcp.public.LCPAuthenticationReason

internal class PassphrasesService(private val repository: PassphrasesRepository) {

Expand All @@ -40,16 +40,23 @@ internal class PassphrasesService(private val repository: PassphrasesRepository)
private fun authenticate(license: LicenseDocument, reason: LCPAuthenticationReason, authentication: LCPAuthenticating, completion: (String?) -> Unit) {
val authenticatedLicense = LCPAuthenticatedLicense(document = license)
authentication.requestPassphrase(authenticatedLicense, reason) { clearPassphrase ->
clearPassphrase?.let {
if (clearPassphrase != null) {
val hashedPassphrase = HASH.sha256(clearPassphrase)
val passphrases = mutableListOf(hashedPassphrase)
// Note: The C++ LCP lib crashes if we provide a passphrase that is not a valid
// SHA-256 hash. So we check this beforehand.
if (sha256Regex.matches(clearPassphrase)) {
passphrases.add(clearPassphrase)
}

try {
val passphrase = Lcp().findOneValidPassphrase(license.json.toString(), listOf(hashedPassphrase).toTypedArray())
val passphrase = Lcp().findOneValidPassphrase(license.json.toString(), passphrases.toTypedArray())
this.repository.addPassphrase(passphrase, license.id, license.provider, license.user.id)
completion(passphrase)
} catch (e: Exception) {
authenticate(license, LCPAuthenticationReason.invalidPassphrase, authentication, completion)
}
} ?: run {
} else {
completion(null)
}
}
Expand All @@ -68,4 +75,9 @@ internal class PassphrasesService(private val repository: PassphrasesRepository)
}
return passphrases
}

companion object {
private val sha256Regex = "^([a-f0-9]{64})$".toRegex(RegexOption.IGNORE_CASE)
}

}