Skip to content

Commit

Permalink
support CWT proof signer from niscy-eudiw/eudi-lib-jvm-openid4vci-kt@d…
Browse files Browse the repository at this point in the history
  • Loading branch information
vkanellopoulos committed Jun 4, 2024
1 parent e33537b commit c8bb7ca
Show file tree
Hide file tree
Showing 16 changed files with 532 additions and 269 deletions.
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ espresso-contrib = "3.5.1"
espresso-core = "3.5.1"
eudi-document-manager = "0.3.0-SNAPSHOT"
eudi-iso18013-data-transfer = "0.2.0-SNAPSHOT"
eudi-lib-jvm-openid4vci-kt = "0.2.2"
eudi-lib-jvm-openid4vci-kt = "0.3.0-SNAPSHOT"
eudi-lib-jvm-siop-openid4vp-kt = "0.4.0"
gradle-plugin = "7.4.0"
identity-credential = "20231002"
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
* Copyright (c) 2024 European Commission
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package eu.europa.ec.eudi.wallet.document.issue.opeid4vci

import android.app.KeyguardManager
import android.content.Context
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import eu.europa.ec.eudi.openid4vci.*
import eu.europa.ec.eudi.wallet.document.Constants.EU_PID_DOCTYPE
import eu.europa.ec.eudi.wallet.document.CreateIssuanceRequestResult
import eu.europa.ec.eudi.wallet.document.DocumentManager
import eu.europa.ec.eudi.wallet.issue.openid4vci.CWTProofSigner
import eu.europa.ec.eudi.wallet.issue.openid4vci.ProofSigner
import eu.europa.ec.eudi.wallet.issue.openid4vci.UserAuthRequiredException
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.junit.Assert
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Assume.assumeTrue
import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith
import java.io.IOException
import java.security.Security
import java.security.Signature
import java.util.*

@RunWith(AndroidJUnit4::class)
class CWTProofSignerTest {

companion object {
private lateinit var context: Context
val BC = BouncyCastleProvider()

@JvmStatic
@BeforeClass
@Throws(IOException::class)
fun setUp() {
Security.insertProviderAt(BC, 1)
context = InstrumentationRegistry.getInstrumentation().targetContext
}
}

@Test
fun test_userAuthRequired_is_set_to_Yes_when_needed() {
assumeTrue(
"Device is not secure. So cannot run this test",
context.getSystemService(KeyguardManager::class.java).isDeviceSecure
)
val documentManager = DocumentManager.Builder(context)
.enableUserAuth(true)
.build()


val issuanceRequestResult = documentManager.createIssuanceRequest(EU_PID_DOCTYPE, false)
assertTrue(issuanceRequestResult is CreateIssuanceRequestResult.Success)

val issuanceRequest =
(issuanceRequestResult as CreateIssuanceRequestResult.Success).issuanceRequest

val proofSigner = CWTProofSigner(issuanceRequest, CoseAlgorithm.ES256, CoseCurve.P_256)
assertEquals(CoseAlgorithm.ES256, proofSigner.popSigner.algorithm)
assertEquals(CoseCurve.P_256, proofSigner.popSigner.curve)

assertTrue(proofSigner.popSigner.bindingKey is CwtBindingKey.CoseKey)

val payload = "some random bytes".toByteArray()
try {
proofSigner.sign(payload)
Assert.fail("Expected UserAuthRequiredException")
} catch (e: UserAuthRequiredException) {
assertTrue(proofSigner.userAuthStatus is ProofSigner.UserAuthStatus.Required)
} finally {
documentManager.deleteDocumentById(issuanceRequest.documentId)
}
}

@Test
fun test_sign_method_creates_a_valid_signature() {
val documentManager = DocumentManager.Builder(context)
.enableUserAuth(false)
.build()


val issuanceRequestResult = documentManager.createIssuanceRequest(EU_PID_DOCTYPE, false)
assertTrue(issuanceRequestResult is CreateIssuanceRequestResult.Success)

val issuanceRequest =
(issuanceRequestResult as CreateIssuanceRequestResult.Success).issuanceRequest

val proofSigner = CWTProofSigner(issuanceRequest, CoseAlgorithm.ES256, CoseCurve.P_256)
assertEquals(CoseAlgorithm.ES256, proofSigner.popSigner.algorithm)
assertEquals(CoseCurve.P_256, proofSigner.popSigner.curve)

assertTrue(proofSigner.popSigner.bindingKey is CwtBindingKey.CoseKey)

val payload = "some random bytes".toByteArray()
val proofSignature = proofSigner.sign(payload)
val publicKey = (proofSigner.popSigner.bindingKey as CwtBindingKey.CoseKey).jwk.toECKey().toPublicKey()

val result = Signature.getInstance("SHA256withECDSA", BC).apply {
initVerify(publicKey)
update(payload)
}.verify(proofSignature)
assertTrue(result)
documentManager.deleteDocumentById(issuanceRequest.documentId)
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2024 European Commission
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package eu.europa.ec.eudi.wallet.document.issue.opeid4vci

import androidx.test.ext.junit.runners.AndroidJUnit4
import com.nimbusds.jose.JOSEException
import com.nimbusds.jose.JWSAlgorithm
import com.nimbusds.jose.JWSHeader
import com.nimbusds.jose.crypto.ECDSAVerifier
import eu.europa.ec.eudi.openid4vci.JwtBindingKey
import eu.europa.ec.eudi.openid4vci.PopSigner
import eu.europa.ec.eudi.wallet.issue.openid4vci.JWSDPoPSigner
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class JWSDPoPSignerTest {

@Test
fun factoryInvokeCreatesDPoPSigner() {
val signer = JWSDPoPSigner().getOrNull()
Assert.assertTrue(signer is PopSigner.Jwt)
}

@Test
fun signerSupportedJWSAlgorithmsIsES256() {
val signer = JWSDPoPSigner().getOrThrow()
Assert.assertEquals(JWSAlgorithm.ES256, signer.algorithm)
Assert.assertEquals(1, signer.jwsSigner.supportedJWSAlgorithms().size)
Assert.assertEquals(JWSAlgorithm.ES256, signer.jwsSigner.supportedJWSAlgorithms().first())
}

@Test
fun bindingKeyIsJwtBindingKey_Jwk() {
val signer = JWSDPoPSigner().getOrThrow()
Assert.assertTrue(signer.bindingKey is JwtBindingKey.Jwk)
}

@Test(expected = JOSEException::class)
fun signThrowsWhenUnsupportedAlgorithmInHeader() {
val signer = JWSDPoPSigner().getOrThrow()
val header = JWSHeader(JWSAlgorithm.ES384)
val signingInput = "test".toByteArray()
signer.jwsSigner.sign(header, signingInput)
}

@Test
fun signReturnsValidSignature() {
val signer = JWSDPoPSigner().getOrThrow()
val header = JWSHeader(JWSAlgorithm.ES256)
val signingInput = "test".toByteArray()
val signature = signer.jwsSigner.sign(header, signingInput)
val jwk = (signer.bindingKey as JwtBindingKey.Jwk).jwk
val verifier = ECDSAVerifier(jwk.toECKey())
val result = verifier.verify(header, signingInput, signature)
Assert.assertTrue(result)
}

@Test
fun instantiatingDPoPSignerUsesDifferentKeyPair() {
val firstSigner = JWSDPoPSigner().getOrThrow()
val firstJwk = (firstSigner.bindingKey as JwtBindingKey.Jwk).jwk
val secondSigner = JWSDPoPSigner().getOrThrow()
val secondJwk = (secondSigner.bindingKey as JwtBindingKey.Jwk).jwk
Assert.assertNotEquals(firstJwk, secondJwk)
}
}
Loading

0 comments on commit c8bb7ca

Please sign in to comment.