mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
@@ -16,7 +16,25 @@
|
|||||||
|
|
||||||
package com.kunzisoft.keepass.credentialprovider.passkey.data
|
package com.kunzisoft.keepass.credentialprovider.passkey.data
|
||||||
|
|
||||||
data class PublicKeyCredentialRpEntity(val name: String, val id: String)
|
import com.kunzisoft.encrypt.Base64Helper
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
data class PublicKeyCredentialRpEntity(
|
||||||
|
val name: String,
|
||||||
|
val id: String
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
fun JSONObject.getPublicKeyCredentialRpEntity(
|
||||||
|
parameterName: String
|
||||||
|
): PublicKeyCredentialRpEntity {
|
||||||
|
val rpJson = this.getJSONObject(parameterName)
|
||||||
|
return PublicKeyCredentialRpEntity(
|
||||||
|
rpJson.getString("name"),
|
||||||
|
rpJson.getString("id")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data class PublicKeyCredentialUserEntity(
|
data class PublicKeyCredentialUserEntity(
|
||||||
val name: String,
|
val name: String,
|
||||||
@@ -42,9 +60,41 @@ data class PublicKeyCredentialUserEntity(
|
|||||||
result = 31 * result + displayName.hashCode()
|
result = 31 * result + displayName.hashCode()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun JSONObject.getPublicKeyCredentialUserEntity(
|
||||||
|
parameterName: String
|
||||||
|
): PublicKeyCredentialUserEntity {
|
||||||
|
val rpUser = this.getJSONObject(parameterName)
|
||||||
|
return PublicKeyCredentialUserEntity(
|
||||||
|
rpUser.getString("name"),
|
||||||
|
Base64Helper.b64Decode(rpUser.getString("id")),
|
||||||
|
rpUser.getString("displayName")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class PublicKeyCredentialParameters(val type: String, val alg: Long)
|
data class PublicKeyCredentialParameters(
|
||||||
|
val type: String,
|
||||||
|
val alg: Long
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
fun JSONObject.getPublicKeyCredentialParametersList(
|
||||||
|
parameterName: String
|
||||||
|
): List<PublicKeyCredentialParameters> {
|
||||||
|
val pubKeyCredParamsJson = this.getJSONArray(parameterName)
|
||||||
|
val pubKeyCredParamsTmp: MutableList<PublicKeyCredentialParameters> = mutableListOf()
|
||||||
|
for (i in 0 until pubKeyCredParamsJson.length()) {
|
||||||
|
val e = pubKeyCredParamsJson.getJSONObject(i)
|
||||||
|
pubKeyCredParamsTmp.add(
|
||||||
|
PublicKeyCredentialParameters(e.getString("type"), e.getLong("alg"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return pubKeyCredParamsTmp.toList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data class PublicKeyCredentialDescriptor(
|
data class PublicKeyCredentialDescriptor(
|
||||||
val type: String,
|
val type: String,
|
||||||
@@ -70,11 +120,97 @@ data class PublicKeyCredentialDescriptor(
|
|||||||
result = 31 * result + transports.hashCode()
|
result = 31 * result + transports.hashCode()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun JSONObject.getPublicKeyCredentialDescriptorList(
|
||||||
|
parameterName: String
|
||||||
|
): List<PublicKeyCredentialDescriptor> {
|
||||||
|
val credentialsJson = this.getJSONArray(parameterName)
|
||||||
|
val credentialsTmp: MutableList<PublicKeyCredentialDescriptor> = mutableListOf()
|
||||||
|
for (i in 0 until credentialsJson.length()) {
|
||||||
|
val credentialJson = credentialsJson.getJSONObject(i)
|
||||||
|
|
||||||
|
val transports: MutableList<String> = mutableListOf()
|
||||||
|
val transportsJson = credentialJson.getJSONArray("transports")
|
||||||
|
for (j in 0 until transportsJson.length()) {
|
||||||
|
transports.add(transportsJson.getString(j))
|
||||||
|
}
|
||||||
|
credentialsTmp.add(
|
||||||
|
PublicKeyCredentialDescriptor(
|
||||||
|
type = credentialJson.getString("type"),
|
||||||
|
id = Base64Helper.b64Decode(credentialJson.getString("id")),
|
||||||
|
transports = transports
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return credentialsTmp.toList()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class AuthenticatorSelectionCriteria(
|
data class AuthenticatorSelectionCriteria(
|
||||||
val authenticatorAttachment: String,
|
val authenticatorAttachment: String? = null,
|
||||||
val residentKey: String,
|
val residentKey: ResidentKeyRequirement? = null,
|
||||||
val requireResidentKey: Boolean = false,
|
val requireResidentKey: Boolean?,
|
||||||
val userVerification: String = "preferred"
|
val userVerification: UserVerificationRequirement? = UserVerificationRequirement.PREFERRED
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
fun JSONObject.getAuthenticatorSelectionCriteria(
|
||||||
|
parameterName: String
|
||||||
|
): AuthenticatorSelectionCriteria {
|
||||||
|
val authenticatorSelection = this.optJSONObject(parameterName)
|
||||||
|
?: return AuthenticatorSelectionCriteria(requireResidentKey = null)
|
||||||
|
val authenticatorAttachment = if (!authenticatorSelection.isNull("authenticatorAttachment"))
|
||||||
|
authenticatorSelection.getString("authenticatorAttachment") else null
|
||||||
|
var residentKey = if (!authenticatorSelection.isNull("residentKey"))
|
||||||
|
ResidentKeyRequirement.fromString(authenticatorSelection.getString("residentKey"))
|
||||||
|
else null
|
||||||
|
val requireResidentKey = authenticatorSelection.optBoolean("requireResidentKey", false)
|
||||||
|
val userVerification = UserVerificationRequirement.fromString(authenticatorSelection.optString("userVerification", "preferred"))
|
||||||
|
// https://www.w3.org/TR/webauthn-3/#enumdef-residentkeyrequirement
|
||||||
|
if (residentKey == null) {
|
||||||
|
residentKey = if (requireResidentKey) {
|
||||||
|
ResidentKeyRequirement.REQUIRED
|
||||||
|
} else {
|
||||||
|
ResidentKeyRequirement.DISCOURAGED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return AuthenticatorSelectionCriteria(
|
||||||
|
authenticatorAttachment = authenticatorAttachment,
|
||||||
|
residentKey = residentKey,
|
||||||
|
requireResidentKey = requireResidentKey,
|
||||||
|
userVerification = userVerification
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webauthn-3/#enumdef-residentkeyrequirement
|
||||||
|
enum class ResidentKeyRequirement(val value: String) {
|
||||||
|
DISCOURAGED("discouraged"),
|
||||||
|
PREFERRED("preferred"),
|
||||||
|
REQUIRED("required");
|
||||||
|
override fun toString(): String {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
companion object {
|
||||||
|
fun fromString(value: String): ResidentKeyRequirement? {
|
||||||
|
return ResidentKeyRequirement.entries.firstOrNull { it.value == value }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webauthn-3/#enumdef-userverificationrequirement
|
||||||
|
enum class UserVerificationRequirement(val value: String) {
|
||||||
|
REQUIRED("required"),
|
||||||
|
PREFERRED("preferred"),
|
||||||
|
DISCOURAGED("discouraged");
|
||||||
|
override fun toString(): String {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
companion object {
|
||||||
|
fun fromString(value: String): UserVerificationRequirement? {
|
||||||
|
return UserVerificationRequirement.entries.firstOrNull { it.value == value }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,51 +20,42 @@
|
|||||||
package com.kunzisoft.keepass.credentialprovider.passkey.data
|
package com.kunzisoft.keepass.credentialprovider.passkey.data
|
||||||
|
|
||||||
import com.kunzisoft.encrypt.Base64Helper
|
import com.kunzisoft.encrypt.Base64Helper
|
||||||
|
import com.kunzisoft.keepass.credentialprovider.passkey.data.AuthenticatorSelectionCriteria.Companion.getAuthenticatorSelectionCriteria
|
||||||
|
import com.kunzisoft.keepass.credentialprovider.passkey.data.PublicKeyCredentialDescriptor.Companion.getPublicKeyCredentialDescriptorList
|
||||||
|
import com.kunzisoft.keepass.credentialprovider.passkey.data.PublicKeyCredentialParameters.Companion.getPublicKeyCredentialParametersList
|
||||||
|
import com.kunzisoft.keepass.credentialprovider.passkey.data.PublicKeyCredentialRpEntity.Companion.getPublicKeyCredentialRpEntity
|
||||||
|
import com.kunzisoft.keepass.credentialprovider.passkey.data.PublicKeyCredentialUserEntity.Companion.getPublicKeyCredentialUserEntity
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
class PublicKeyCredentialCreationOptions(
|
class PublicKeyCredentialCreationOptions(
|
||||||
requestJson: String,
|
requestJson: String,
|
||||||
var clientDataHash: ByteArray?
|
var clientDataHash: ByteArray?
|
||||||
) {
|
) {
|
||||||
val json: JSONObject = JSONObject(requestJson)
|
private val json: JSONObject = JSONObject(requestJson)
|
||||||
|
|
||||||
val relyingPartyEntity: PublicKeyCredentialRpEntity
|
val relyingPartyEntity: PublicKeyCredentialRpEntity =
|
||||||
val userEntity: PublicKeyCredentialUserEntity
|
json.getPublicKeyCredentialRpEntity("rp")
|
||||||
val challenge: ByteArray
|
|
||||||
val pubKeyCredParams: List<PublicKeyCredentialParameters>
|
|
||||||
|
|
||||||
var timeout: Long
|
val userEntity: PublicKeyCredentialUserEntity =
|
||||||
var excludeCredentials: List<PublicKeyCredentialDescriptor>
|
json.getPublicKeyCredentialUserEntity("user")
|
||||||
var authenticatorSelection: AuthenticatorSelectionCriteria
|
|
||||||
var attestation: String
|
|
||||||
|
|
||||||
init {
|
val challenge: ByteArray =
|
||||||
val rpJson = json.getJSONObject("rp")
|
Base64Helper.b64Decode(json.getString("challenge"))
|
||||||
relyingPartyEntity = PublicKeyCredentialRpEntity(rpJson.getString("name"), rpJson.getString("id"))
|
|
||||||
val rpUser = json.getJSONObject("user")
|
|
||||||
userEntity =
|
|
||||||
PublicKeyCredentialUserEntity(
|
|
||||||
rpUser.getString("name"),
|
|
||||||
Base64Helper.b64Decode(rpUser.getString("id")),
|
|
||||||
rpUser.getString("displayName")
|
|
||||||
)
|
|
||||||
challenge = Base64Helper.b64Decode(json.getString("challenge"))
|
|
||||||
val pubKeyCredParamsJson = json.getJSONArray("pubKeyCredParams")
|
|
||||||
val pubKeyCredParamsTmp: MutableList<PublicKeyCredentialParameters> = mutableListOf()
|
|
||||||
for (i in 0 until pubKeyCredParamsJson.length()) {
|
|
||||||
val e = pubKeyCredParamsJson.getJSONObject(i)
|
|
||||||
pubKeyCredParamsTmp.add(
|
|
||||||
PublicKeyCredentialParameters(e.getString("type"), e.getLong("alg"))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
pubKeyCredParams = pubKeyCredParamsTmp.toList()
|
|
||||||
|
|
||||||
timeout = json.optLong("timeout", 0)
|
val pubKeyCredParams: List<PublicKeyCredentialParameters> =
|
||||||
// TODO: Fix excludeCredentials and authenticatorSelection
|
json.getPublicKeyCredentialParametersList("pubKeyCredParams")
|
||||||
excludeCredentials = emptyList()
|
|
||||||
authenticatorSelection = AuthenticatorSelectionCriteria("platform", "required")
|
var timeout: Long =
|
||||||
attestation = json.optString("attestation", "none")
|
json.optLong("timeout", 0)
|
||||||
}
|
|
||||||
|
var excludeCredentials: List<PublicKeyCredentialDescriptor> =
|
||||||
|
json.getPublicKeyCredentialDescriptorList("excludeCredentials")
|
||||||
|
|
||||||
|
var authenticatorSelection: AuthenticatorSelectionCriteria =
|
||||||
|
json.getAuthenticatorSelectionCriteria("authenticatorSelection")
|
||||||
|
|
||||||
|
var attestation: String =
|
||||||
|
json.optString("attestation", "none")
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG = PublicKeyCredentialCreationOptions::class.simpleName
|
private val TAG = PublicKeyCredentialCreationOptions::class.simpleName
|
||||||
|
|||||||
@@ -20,35 +20,33 @@
|
|||||||
package com.kunzisoft.keepass.credentialprovider.passkey.data
|
package com.kunzisoft.keepass.credentialprovider.passkey.data
|
||||||
|
|
||||||
import com.kunzisoft.encrypt.Base64Helper
|
import com.kunzisoft.encrypt.Base64Helper
|
||||||
|
import com.kunzisoft.keepass.credentialprovider.passkey.data.PublicKeyCredentialDescriptor.Companion.getPublicKeyCredentialDescriptorList
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/webauthn-3/#enumdef-residentkeyrequirement
|
||||||
class PublicKeyCredentialRequestOptions(requestJson: String) {
|
class PublicKeyCredentialRequestOptions(requestJson: String) {
|
||||||
private val json: JSONObject = JSONObject(requestJson)
|
private val json: JSONObject = JSONObject(requestJson)
|
||||||
val challenge: ByteArray = Base64Helper.b64Decode(json.getString("challenge"))
|
|
||||||
val timeout: Long = json.optLong("timeout", 0)
|
|
||||||
val rpId: String = json.optString("rpId", "")
|
|
||||||
val allowCredentials: List<PublicKeyCredentialDescriptor>
|
|
||||||
val userVerification: String = json.optString("userVerification", "preferred")
|
|
||||||
|
|
||||||
init {
|
val challenge: ByteArray =
|
||||||
val allowCredentialsJson = json.getJSONArray("allowCredentials")
|
Base64Helper.b64Decode(json.getString("challenge"))
|
||||||
val allowCredentialsTmp: MutableList<PublicKeyCredentialDescriptor> = mutableListOf()
|
|
||||||
for (i in 0 until allowCredentialsJson.length()) {
|
|
||||||
val allowCredentialJson = allowCredentialsJson.getJSONObject(i)
|
|
||||||
|
|
||||||
val transports: MutableList<String> = mutableListOf()
|
val timeout: Long =
|
||||||
val transportsJson = allowCredentialJson.getJSONArray("transports")
|
json.optLong("timeout", 0)
|
||||||
for (j in 0 until transportsJson.length()) {
|
|
||||||
transports.add(transportsJson.getString(j))
|
val rpId: String =
|
||||||
}
|
json.optString("rpId", "")
|
||||||
allowCredentialsTmp.add(
|
|
||||||
PublicKeyCredentialDescriptor(
|
val allowCredentials: List<PublicKeyCredentialDescriptor> =
|
||||||
type = allowCredentialJson.getString("type"),
|
json.getPublicKeyCredentialDescriptorList("allowCredentials")
|
||||||
id = Base64Helper.b64Decode(allowCredentialJson.getString("id")),
|
|
||||||
transports = transports
|
val userVerification: UserVerificationRequirement =
|
||||||
)
|
UserVerificationRequirement.fromString(
|
||||||
)
|
json.optString("userVerification", "preferred"))
|
||||||
}
|
?: UserVerificationRequirement.PREFERRED
|
||||||
allowCredentials = allowCredentialsTmp.toList()
|
|
||||||
}
|
// TODO Hints
|
||||||
|
val hints: List<String> = listOf()
|
||||||
|
|
||||||
|
// TODO Extensions
|
||||||
|
// val extensions: AuthenticationExtensionsClientInputs
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user