From 26ad04af0cef8288789aaec5719d6ea7b0f7db9e Mon Sep 17 00:00:00 2001 From: vkanellopoulos Date: Mon, 10 Jun 2024 17:33:55 +0300 Subject: [PATCH] fix #60; log payload of issuing request; update README.md --- README.md | 18 +++++- changelog.md | 6 ++ gradle.properties | 2 +- ...oofSignerTest.kt => JWSProofSignerTest.kt} | 0 .../openid4vci/DefaultOpenId4VciManager.kt | 4 +- .../wallet/issue/openid4vci/JWSDPoPSigner.kt | 57 +++++-------------- 6 files changed, 41 insertions(+), 46 deletions(-) rename wallet-core/src/androidTest/java/eu/europa/ec/eudi/wallet/document/issue/opeid4vci/{JwsProofSignerTest.kt => JWSProofSignerTest.kt} (100%) diff --git a/README.md b/README.md index 3c4bc22e..6a419e63 100644 --- a/README.md +++ b/README.md @@ -82,12 +82,28 @@ The released software is a initial development release version: ### Dependencies +In order to use snapshot versions add the following to your project's settings.gradle file: + +```groovy + +dependencyResolutionManagement { + repositories { + // ... + maven { + url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/") + mavenContent { snapshotsOnly() } + } + // ... + } +} +``` + To include the library in your project, add the following dependencies to your app's build.gradle file. ```groovy dependencies { - implementation "eu.europa.ec.eudi:eudi-lib-android-wallet-core:0.9.3-SNAPSHOT" + implementation "eu.europa.ec.eudi:eudi-lib-android-wallet-core:0.9.4-SNAPSHOT" implementation "androidx.biometric:biometric-ktx:1.2.0-alpha05" } ``` diff --git a/changelog.md b/changelog.md index e3d1e656..3f26dcb5 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,11 @@ # Changelog +## [0.9.4-SNAPSHOT] + +__10 Jun 2024__ + +- Security improvements for dPoP Signer for OpendI4VCI + ## [0.9.3-SNAPSHOT] _10 Jun 2024_ diff --git a/gradle.properties b/gradle.properties index a8b034b1..643ee915 100644 --- a/gradle.properties +++ b/gradle.properties @@ -42,7 +42,7 @@ systemProp.sonar.host.url=https://sonarcloud.io systemProp.sonar.gradle.skipCompile=true systemProp.sonar.coverage.jacoco.xmlReportPaths=build/reports/jacoco/testDebugUnitTestCoverage/testDebugUnitTestCoverage.xml,build/reports/jacoco/testReleaseUnitTestCoverage/testReleaseUnitTestCoverage.xml systemProp.sonar.projectName=eudi-lib-android-wallet-core -VERSION_NAME=0.9.3-SNAPSHOT +VERSION_NAME=0.9.4-SNAPSHOT SONATYPE_HOST=S01 SONATYPE_AUTOMATIC_RELEASE=false diff --git a/wallet-core/src/androidTest/java/eu/europa/ec/eudi/wallet/document/issue/opeid4vci/JwsProofSignerTest.kt b/wallet-core/src/androidTest/java/eu/europa/ec/eudi/wallet/document/issue/opeid4vci/JWSProofSignerTest.kt similarity index 100% rename from wallet-core/src/androidTest/java/eu/europa/ec/eudi/wallet/document/issue/opeid4vci/JwsProofSignerTest.kt rename to wallet-core/src/androidTest/java/eu/europa/ec/eudi/wallet/document/issue/opeid4vci/JWSProofSignerTest.kt diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DefaultOpenId4VciManager.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DefaultOpenId4VciManager.kt index 9ba7f696..aa3e0bfd 100644 --- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DefaultOpenId4VciManager.kt +++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/DefaultOpenId4VciManager.kt @@ -272,7 +272,9 @@ internal class DefaultOpenId4VciManager( addedDocuments: MutableSet, onEvent: OpenId4VciManager.OnResult ) { - val payload = IssuanceRequestPayload.ConfigurationBased(credentialConfigurationIdentifier, null) + val claimSet = null + val payload = IssuanceRequestPayload.ConfigurationBased(credentialConfigurationIdentifier, claimSet) + Log.d(TAG, "doIssueCredential payload: $payload") when (authRequest) { is AuthorizedRequest.NoProofRequired -> doRequestSingleNoProof( authRequest, diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/JWSDPoPSigner.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/JWSDPoPSigner.kt index 3d0ee819..0c709d74 100644 --- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/JWSDPoPSigner.kt +++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/JWSDPoPSigner.kt @@ -16,9 +16,6 @@ package eu.europa.ec.eudi.wallet.issue.openid4vci -import android.security.keystore.KeyGenParameterSpec -import android.security.keystore.KeyProperties.DIGEST_SHA256 -import android.security.keystore.KeyProperties.PURPOSE_SIGN import com.nimbusds.jose.JOSEException import com.nimbusds.jose.JWSAlgorithm import com.nimbusds.jose.JWSHeader @@ -29,11 +26,12 @@ import com.nimbusds.jose.jwk.JWK import com.nimbusds.jose.util.Base64URL import eu.europa.ec.eudi.openid4vci.JwtBindingKey import eu.europa.ec.eudi.openid4vci.PopSigner +import org.bouncycastle.jce.provider.BouncyCastleProvider +import java.security.KeyPair import java.security.KeyPairGenerator -import java.security.KeyStore import java.security.Signature -import java.time.Instant -import java.util.* +import java.security.spec.ECGenParameterSpec + /** * A [JWSSigner] implementation for DPoP. @@ -45,15 +43,20 @@ import java.util.* */ internal class JWSDPoPSigner private constructor() : JWSSigner { + private val BC by lazy { BouncyCastleProvider() } + private val keyPair: KeyPair by lazy { + val kg: KeyPairGenerator = KeyPairGenerator.getInstance("EC", BC) + val params = ECGenParameterSpec("secp256r1") + kg.initialize(params) + kg.generateKeyPair() + } + private val jcaContext = JCAContext() override fun getJCAContext(): JCAContext = jcaContext - private val keyStore: KeyStore - get() = KeyStore.getInstance("AndroidKeyStore").apply { load(null) } - private val jwk: JWK - get() = JWK.parseFromPEMEncodedObjects(keyStore.getCertificate(KEY_ALIAS).publicKey.pem) + get() = JWK.parseFromPEMEncodedObjects(keyPair.public.pem) val popSigner: PopSigner.Jwt get() = PopSigner.Jwt( @@ -62,13 +65,6 @@ internal class JWSDPoPSigner private constructor() : JWSSigner { jwsSigner = this ) - /** - * Initializes the DPoP signer by generating a key pair. - */ - init { - generateKeyPair() - } - override fun sign(header: JWSHeader, signingInput: ByteArray): Base64URL { val algorithm = SupportedAlgorithms[header.algorithm] ?: throw JOSEException( @@ -77,7 +73,7 @@ internal class JWSDPoPSigner private constructor() : JWSSigner { supportedJWSAlgorithms() ) ) - val privateKey = (keyStore.getEntry(KEY_ALIAS, null) as KeyStore.PrivateKeyEntry).privateKey + val privateKey = keyPair.private val signature = Signature.getInstance(algorithm).apply { initSign(privateKey) update(signingInput) @@ -87,35 +83,10 @@ internal class JWSDPoPSigner private constructor() : JWSSigner { override fun supportedJWSAlgorithms(): MutableSet = SupportedAlgorithms.keys.toMutableSet() - /** - * Generates a key pair for DPoP. - */ - private fun generateKeyPair() { - if (keyStore.containsAlias(KEY_ALIAS)) { - keyStore.deleteEntry(KEY_ALIAS) - } - val now = Instant.now() - val notBefore = Date.from(now) - val notAfter = Date.from(now.plusSeconds(180L)) - val keySpec = KeyGenParameterSpec.Builder(KEY_ALIAS, PURPOSE_SIGN) - .setDigests(DIGEST_SHA256) - .setUserAuthenticationRequired(false) - .setKeyValidityStart(notBefore) - .setKeyValidityEnd(notAfter) - .setCertificateNotBefore(notBefore) - .setCertificateNotAfter(notAfter) - .build() - with(KeyPairGenerator.getInstance("EC", "AndroidKeyStore")) { - initialize(keySpec) - generateKeyPair() - } - } - /** * Companion object for the JWSDPoPSigner class. */ companion object { - private const val KEY_ALIAS = "eu.europa.ec.eudi.wallet.issue.openid4vci.DPoPKey" /** * Supported algorithms for DPoP.