Skip to content

Commit

Permalink
feat: verification cross platform tested
Browse files Browse the repository at this point in the history
  • Loading branch information
cristianIOHK committed May 6, 2024
1 parent 1821879 commit 628bb62
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 157 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import io.iohk.atala.prism.walletsdk.prismagent.protocols.proofOfPresentation.Pr
import io.iohk.atala.prism.walletsdk.prismagent.protocols.proofOfPresentation.PresentationDefinitionRequest
import io.iohk.atala.prism.walletsdk.prismagent.protocols.proofOfPresentation.PresentationOptions
import io.iohk.atala.prism.walletsdk.prismagent.protocols.proofOfPresentation.PresentationSubmission
import io.iohk.atala.prism.walletsdk.prismagent.protocols.proofOfPresentation.PresentationSubmission.Submission
import io.iohk.atala.prism.walletsdk.prismagent.protocols.proofOfPresentation.PresentationSubmissionOptionsJWT
import io.iohk.atala.prism.walletsdk.prismagent.protocols.proofOfPresentation.RequestPresentation
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
Expand All @@ -87,8 +88,12 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationException
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive

/**
* Check if the passed URL is valid or not.
Expand Down Expand Up @@ -1076,24 +1081,44 @@ class PrismAgent {
return Presentation(
body = Presentation.Body(),
attachments = arrayOf(attachmentDescriptor),
thid = requestPresentation.thid,
thid = requestPresentation.thid ?: requestPresentation.id,
from = requestPresentation.to,
to = requestPresentation.from
)
}

suspend fun handlePresentation(msg: Message): Boolean {
if (msg.thid == null) {
throw Exception() // TODO: Custom error
throw PrismAgentError.MissingOrNullFieldError("thid", "presentation message")
}
val presentation = Presentation.fromMessage(msg)
val msgAttachmentDescriptor =
presentation.attachments.find { it.data::class == AttachmentBase64::class }
?: throw PrismAgentError.AttachmentTypeNotSupported()
val attachmentBase64 = msgAttachmentDescriptor.data as AttachmentBase64

val presentationSubmission =
Json.decodeFromString<PresentationSubmission>(attachmentBase64.base64.base64UrlDecoded)
val presentationSubmissionJsonObject =
Json.decodeFromString<JsonElement>(attachmentBase64.base64.base64UrlDecoded).jsonObject

val presentationSubmission: PresentationSubmission =
presentationSubmissionJsonObject["presentation_submission"]?.let { presentationSubmissionField ->
val submission = Json.decodeFromJsonElement<Submission>(presentationSubmissionField)
var arrayStrings: Array<String> = arrayOf()

if (submission.descriptorMap.isNotEmpty()) {
val firstDescriptorItem = submission.descriptorMap.first()
// Assume the path denotes a direct key in the JSON and strip out JSONPath or XPath specific characters if any.
val path = firstDescriptorItem.path.removePrefix("$.")
.removeSuffix("[0]") // Adjust based on actual path format
arrayStrings = presentationSubmissionJsonObject[path]?.jsonArray?.map { it.jsonPrimitive.content }
?.toTypedArray()
?: arrayOf()
}
return@let PresentationSubmission(submission, arrayStrings)
} ?: throw PrismAgentError.MissingOrNullFieldError(
"presentation_submission",
"presentation submission message"
)

val presentationDefinitionRequest =
pluto.getMessageByThidAndPiuri(msg.thid, ProtocolType.DidcommRequestPresentation.value).firstOrNull()
Expand All @@ -1102,7 +1127,7 @@ class PrismAgent {
val attachmentDescriptor = requestPresentation.attachments.first()
val base64 = (attachmentDescriptor.data as AttachmentBase64).base64
Json.decodeFromString<PresentationDefinitionRequest>(base64.base64UrlDecoded)
} ?: throw Exception("Message by thid ${msg.thid} not found") // TODO: Custom error
} ?: throw PrismAgentError.MissingOrNullFieldError("thid", "presentation message")
return pollux.verifyPresentationSubmission(
presentationSubmission = presentationSubmission,
options = PresentationSubmissionOptionsJWT(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
@file:Suppress("ktlint:standard:import-ordering")

package io.iohk.atala.prism.walletsdk.prismagent.protocols.proofOfPresentation

import io.iohk.atala.prism.walletsdk.domain.models.AttachmentDescriptor
import io.iohk.atala.prism.walletsdk.domain.models.DID
import io.iohk.atala.prism.walletsdk.domain.models.Message
import io.iohk.atala.prism.walletsdk.prismagent.PrismAgentError
import io.iohk.atala.prism.walletsdk.prismagent.protocols.ProtocolType
import java.util.*
import kotlinx.serialization.EncodeDefault
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.util.UUID

/**
* Data class representing proof types.
Expand All @@ -18,10 +23,13 @@ import java.util.UUID
* @property trustIssuers An optional array of trusted issuers for the proof.
*/
@Serializable
data class ProofTypes(
@OptIn(ExperimentalSerializationApi::class)
data class ProofTypes @JvmOverloads constructor(
val schema: String,
@SerialName("required_fields")
val requiredFields: Array<String>?,
val trustIssuers: Array<String>?
@EncodeDefault
val trustIssuers: Array<String>? = null
) {
/**
* Overrides the equals method from the Any class to compare two ProofTypes objects for equality.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,20 @@ data class PresentationSubmission(
val path: String,
@SerialName("path_nested")
val pathNested: DescriptorItem? = null
)
) {
companion object {
fun replacePathWithVerifiablePresentation(originalPath: String): String {
val start = originalPath.indexOf("$.")
val end = originalPath.indexOf("[")

if (start != -1 && end != -1 && start < end) {
return originalPath.substring(0, start + 2) + "verifiablePresentation" + originalPath.substring(end)
} else {
return originalPath // or handle error
}
}
}
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ import io.iohk.atala.prism.walletsdk.prismagent.protocols.proofOfPresentation.Pr
import io.iohk.atala.prism.walletsdk.prismagent.protocols.proofOfPresentation.PresentationSubmission
import io.iohk.atala.prism.walletsdk.prismagent.protocols.proofOfPresentation.PresentationSubmissionOptionsJWT
import io.ktor.http.HttpStatusCode
import java.text.SimpleDateFormat
import java.util.*
import junit.framework.TestCase.assertTrue
import kotlinx.coroutines.test.runTest
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.encodeToJsonElement
import org.mockito.kotlin.mock
import java.text.SimpleDateFormat
import java.util.*
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
Expand Down Expand Up @@ -350,51 +350,6 @@ class PolluxImplTest {
}
}

@Test
fun testVerifyPresentationSubmission_whenWrongJwtHolder_thenVerifiedFalse() = runTest {
val issuerKeyPair =
Secp256k1KeyPair.generateKeyPair(
Seed(MnemonicHelper.createRandomSeed()),
KeyCurve(Curve.SECP256K1)
)
val holderKeyPair =
Secp256k1KeyPair.generateKeyPair(
Seed(MnemonicHelper.createRandomSeed()),
KeyCurve(Curve.SECP256K1)
)
val wrongHolderKeyPair =
Secp256k1KeyPair.generateKeyPair(
Seed(MnemonicHelper.createRandomSeed()),
KeyCurve(Curve.SECP256K1)
)
val issuerDID = castor.createPrismDID(issuerKeyPair.publicKey, emptyArray())
val holderDID = castor.createPrismDID(wrongHolderKeyPair.publicKey, emptyArray())

val vtc = createVerificationTestCase(
VerificationTestCase(
issuer = issuerDID,
holder = holderDID,
issuerPrv = issuerKeyPair.privateKey,
holderPrv = holderKeyPair.privateKey,
subject = """{"course": "Identus Training course Certification 2024"} """,
claims = PresentationClaims(
claims = mapOf(
"course" to InputFieldFilter(
type = "string",
pattern = "Identus Training course Certification 2024"
)
)
),
)
)
assertFailsWith(PolluxError.VerificationUnsuccessful::class, "Holder signature not valid") {
pollux.verifyPresentationSubmission(
presentationSubmission = vtc.second,
options = PresentationSubmissionOptionsJWT(vtc.first)
)
}
}

@Test
fun testVerifyPresentationSubmission_whenJwtSignaturesOkAndFieldsNot_thenVerifiedFalse() =
runTest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class MessagesFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.sendMessage.setOnClickListener {
viewModel.sendMessage(DID("did:peer:2.Ez6LSkjhgJcoGRTSTpjN5XBSKGpNtDSa55qidsahb1s3ucWkJ.Vz6MkgG8bJA2P2HNhCwh4DGHmBtUbKiCafYwBtDMjKnAihaE9.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6ImRpZDpwZWVyOjIuRXo2TFNnaHdTRTQzN3duREUxcHQzWDZoVkRVUXpTanNIemlucFgzWEZ2TWpSQW03eS5WejZNa2hoMWU1Q0VZWXE2SkJVY1RaNkNwMnJhbkNXUnJ2N1lheDNMZTRONTlSNmRkLlNleUowSWpvaVpHMGlMQ0p6SWpwN0luVnlhU0k2SW1oMGRIQnpPaTh2WTNKcGMzUnBZVzR0YldWa2FXRjBiM0l1YW5KcFltOHVhMmwzYVNJc0ltRWlPbHNpWkdsa1kyOXRiUzkyTWlKZGZYMC5TZXlKMElqb2laRzBpTENKeklqcDdJblZ5YVNJNkluZHpjem92TDJOeWFYTjBhV0Z1TFcxbFpHbGhkRzl5TG1weWFXSnZMbXRwZDJrdmQzTWlMQ0poSWpwYkltUnBaR052YlcwdmRqSWlYWDE5IiwiciI6W10sImEiOltdfX0"))
viewModel.sendMessage(DID("did:peer:2.Ez6LStdwaumgiojDcFwtwVU8W9oddwdUgmtbSfcwd6ZibE9ER.Vz6MkuecQ492kzZ7prfErLJ1KMa6Zen3kxoSEttjUqvxYfWS3.SeyJzIjp7ImEiOltdLCJyIjpbXSwidXJpIjoiZGlkOnBlZXI6Mi5FejZMU2dod1NFNDM3d25ERTFwdDNYNmhWRFVRelNqc0h6aW5wWDNYRnZNalJBbTd5LlZ6Nk1raGgxZTVDRVlZcTZKQlVjVFo2Q3AycmFuQ1dScnY3WWF4M0xlNE41OVI2ZGQuU2V5SjBJam9pWkcwaUxDSnpJanA3SW5WeWFTSTZJbWgwZEhCek9pOHZjMmwwTFhCeWFYTnRMVzFsWkdsaGRHOXlMbUYwWVd4aGNISnBjMjB1YVc4aUxDSmhJanBiSW1ScFpHTnZiVzB2ZGpJaVhYMTkuU2V5SjBJam9pWkcwaUxDSnpJanA3SW5WeWFTSTZJbmR6Y3pvdkwzTnBkQzF3Y21semJTMXRaV1JwWVhSdmNpNWhkR0ZzWVhCeWFYTnRMbWx2TDNkeklpd2lZU0k2V3lKa2FXUmpiMjF0TDNZeUlsMTlmUSJ9LCJ0IjoiZG0ifQ"))
}
binding.sendVerification.setOnClickListener {
InitiateVerificationDialogFragment(viewModel).show(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class MessagesViewModel(application: Application) : AndroidViewModel(application
to = toDID ?: did,
body = "{\"msg\":\"This is a new test message ${time}\"}"
)
sdk.mercury.sendMessage(message)
sdk.agent.sendMessage(message)
}
}

Expand All @@ -98,12 +98,20 @@ class MessagesViewModel(application: Application) : AndroidViewModel(application
toDID = DID(toDID),
presentationClaims = PresentationClaims(
claims = mapOf(
"emailAddress" to InputFieldFilter(
"test" to InputFieldFilter(
type = "string",
pattern = "cristian.castro@iohk.io"
pattern = "aliceTest"
)
),
issuer = "did:prism:e02e8099d50351345c5dd831a9e9112b394a85d0064a2eb59429080734a159b6:CrkBCrYBEjoKBmF1dGgtMRAESi4KCXNlY3AyNTZrMRIhAuVYcorfWnL0fYtA5vgJK4_-ob3bUDc-w2UOHdO3QEvqEjsKB2lzc3VlLTEQAkouCglzZWNwMjU2azESIQLCu9NntqupBj-0NCdMA75zReBeyaCJO1aGYeP4BMQHVBI7CgdtYXN0ZXIwEAFKLgoJc2VjcDI1NmsxEiEDOWgvQx6vRu6wUb4FYcJuaECj9BjPMJvRp8LwM61hET4"
// ),
// "issuer" to InputFieldFilter(
// type = "string",
// pattern = "did:prism:50e6cd35d1d57654af2269e6f4c70f32408c96e75b58c1d5a519b8621aac2413:CscBCsQBEmQKD2F1dGhlbnRpY2F0aW9uMBAEQk8KCXNlY3AyNTZrMRIgtzWR-rgd87zym6fi1LoyUZ4M7RmUlyD0EhTDCrQSNOAaIMe5sR-zMlaJguzP0aVjuLjKJV_-ItAic0lOOP45vjo_ElwKB21hc3RlcjAQAUJPCglzZWNwMjU2azESILc1kfq4HfO88pun4tS6MlGeDO0ZlJcg9BIUwwq0EjTgGiDHubEfszJWiYLsz9GlY7i4yiVf_iLQInNJTjj-Ob46Pw"
// )
// "emailAddress" to InputFieldFilter(
// type = "string",
// pattern = "cristian.castro@iohk.io"
// )
)
),
domain = "domain",
challenge = "challenge"
Expand All @@ -124,7 +132,7 @@ class MessagesViewModel(application: Application) : AndroidViewModel(application
RequestPresentation.fromMessage(message),
credential
)
mercury.sendMessage(presentation.makeMessage())
sdk.agent.sendMessage(presentation.makeMessage())
}
}
}
Expand Down Expand Up @@ -196,7 +204,7 @@ class MessagesViewModel(application: Application) : AndroidViewModel(application
subjectDID,
offer
)
mercury.sendMessage(request.makeMessage())
agent.sendMessage(request.makeMessage())
// }
}
}
Expand Down
1 change: 1 addition & 0 deletions sampleapp/src/main/res/xml/network_security_config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">192.168.68.103</domain>
<domain includeSubdomains="true">10.91.100.126</domain>
</domain-config>
</network-security-config>

0 comments on commit 628bb62

Please sign in to comment.