Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issues with Credential Response Encryption. #203

Merged
Show file tree
Hide file tree
Changes from 2 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 @@ -128,7 +128,7 @@ sealed interface RequestedResponseEncryption {
) : RequestedResponseEncryption {
init {
require(!encryptionJwk.isPrivate) { "encryptionJwk must not contain a private key" }
require(KeyUse.ENCRYPTION == encryptionJwk.keyUse) {
require(encryptionJwk.keyUse == KeyUse.ENCRYPTION) {
"encryptionJwk cannot be used for encryption"
}
require(encryptionAlgorithm in JWEAlgorithm.Family.ASYMMETRIC) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ class IssueCredential(
when (unresolvedRequest) {
is UnresolvedCredentialRequest.ByFormat ->
unresolvedRequest.credentialRequest to null

is UnresolvedCredentialRequest.ByCredentialIdentifier ->
resolve(unresolvedRequest) to unresolvedRequest.credentialIdentifier
}
Expand Down Expand Up @@ -370,8 +371,8 @@ private fun CredentialRequestTO.toDomain(
supported: CredentialResponseEncryption,
): UnresolvedCredentialRequest {
val proof = ensureNotNull(proof) { MissingProof }.toDomain()
val credentialResponseEncryption =
credentialResponseEncryption?.toDomain(supported) ?: RequestedResponseEncryption.NotRequired
val credentialResponseEncryption = credentialResponseEncryption?.toDomain() ?: RequestedResponseEncryption.NotRequired
credentialResponseEncryption.ensureIsSupported(supported)

fun credentialRequestByFormat(format: FormatTO): UnresolvedCredentialRequest.ByFormat =
when (format) {
Expand Down Expand Up @@ -459,54 +460,63 @@ private fun ProofTo.toDomain(): UnvalidatedProof = when (type) {
}

/**
* Gets the [RequestedResponseEncryption] that corresponds to the provided values.
* Verifies this [RequestedResponseEncryption] is supported by the provided [CredentialResponseEncryption], otherwise
* raises an [InvalidEncryptionParameters].
*/
context(Raise<InvalidEncryptionParameters>)
private fun CredentialResponseEncryptionTO.toDomain(supported: CredentialResponseEncryption): RequestedResponseEncryption.Required =
withError({ InvalidEncryptionParameters(it) }) {
fun RequestedResponseEncryption.ensureIsSupported() {
when (supported) {
is CredentialResponseEncryption.NotSupported -> {
if (this is RequestedResponseEncryption.Required) {
// credential response encryption not supported by issuer but required by client
raise(IllegalArgumentException("credential response encryption is not supported"))
}
}

is CredentialResponseEncryption.Optional -> {
if (this is RequestedResponseEncryption.Required) {
// credential response encryption supported by issuer and required by client
// ensure provided parameters are supported
if (encryptionAlgorithm !in supported.parameters.algorithmsSupported) {
raise(IllegalArgumentException("jwe encryption algorithm '${encryptionAlgorithm.name}' is not supported"))
}
if (encryptionMethod !in supported.parameters.methodsSupported) {
raise(IllegalArgumentException("jwe encryption method '${encryptionMethod.name}' is not supported"))
}
}
private fun RequestedResponseEncryption.ensureIsSupported(supported: CredentialResponseEncryption) {
try {
when (supported) {
is CredentialResponseEncryption.NotSupported -> {
if (this is RequestedResponseEncryption.Required) {
// credential response encryption not supported by issuer but required by client
throw IllegalArgumentException("credential response encryption is not supported")
}
}

is CredentialResponseEncryption.Required -> {
if (this !is RequestedResponseEncryption.Required) {
// credential response encryption required by issuer but not required by client
raise(IllegalArgumentException("credential response encryption is required"))
}

is CredentialResponseEncryption.Optional -> {
if (this is RequestedResponseEncryption.Required) {
// credential response encryption supported by issuer and required by client
// ensure provided parameters are supported
if (encryptionAlgorithm !in supported.parameters.algorithmsSupported) {
raise(IllegalArgumentException("jwe encryption algorithm '${encryptionAlgorithm.name}' is not supported"))
throw IllegalArgumentException("jwe encryption algorithm '${encryptionAlgorithm.name}' is not supported")
}
if (encryptionMethod !in supported.parameters.methodsSupported) {
raise(IllegalArgumentException("jwe encryption method '${encryptionMethod.name}' is not supported"))
throw IllegalArgumentException("jwe encryption method '${encryptionMethod.name}' is not supported")
}
}
}
}

RequestedResponseEncryption.Required(Json.encodeToString(key), algorithm, method)
.bind()
.also { it.ensureIsSupported() }
is CredentialResponseEncryption.Required -> {
if (this !is RequestedResponseEncryption.Required) {
// credential response encryption required by issuer but not required by client
throw IllegalArgumentException("credential response encryption is required")
dzarras marked this conversation as resolved.
Show resolved Hide resolved
}

// ensure provided parameters are supported
if (encryptionAlgorithm !in supported.parameters.algorithmsSupported) {
throw IllegalArgumentException("jwe encryption algorithm '${encryptionAlgorithm.name}' is not supported")
}
if (encryptionMethod !in supported.parameters.methodsSupported) {
throw IllegalArgumentException("jwe encryption method '${encryptionMethod.name}' is not supported")
}
}
}
} catch (error: Exception) {
raise(InvalidEncryptionParameters(error))
}
}

/**
* Gets the [RequestedResponseEncryption] that corresponds to the provided values.
*/
context(Raise<InvalidEncryptionParameters>)
private fun CredentialResponseEncryptionTO.toDomain(): RequestedResponseEncryption.Required =
RequestedResponseEncryption.Required(
Json.encodeToString(key),
algorithm,
method,
).getOrElse { raise(InvalidEncryptionParameters(it)) }

fun CredentialResponse<JsonElement>.toTO(nonce: CNonce): IssueCredentialResponse.PlainTO =
when (this) {
Expand Down
Loading
Loading