From 0681480ed2ff229971ef62affc58e58b3efba277 Mon Sep 17 00:00:00 2001 From: vkanellopoulos Date: Mon, 10 Jun 2024 15:30:29 +0300 Subject: [PATCH] fix use Concat instead of DER for signature in CWT proof signer; add extensive logging for DefaultOpenId4VciManager --- gradle/libs.versions.toml | 2 +- wallet-core/build.gradle | 6 ++ .../issue/opeid4vci/CWTProofSignerTest.kt | 50 +-------- .../wallet/issue/openid4vci/CWTProofSigner.kt | 1 + .../openid4vci/DefaultOpenId4VciManager.kt | 100 ++++++++++++++---- .../wallet/issue/openid4vci/JWSProofSigner.kt | 2 +- .../issue/openid4vci/SupportedProofType.kt | 14 ++- .../openid4vci/SuspendedAuthorization.kt | 14 ++- .../ec/eudi/wallet/issue/openid4vci/Utils.kt | 26 ++++- .../ec/eudi/wallet/TestSign1ForAuthlete.kt | 49 --------- 10 files changed, 139 insertions(+), 125 deletions(-) delete mode 100644 wallet-core/src/test/java/eu/europa/ec/eudi/wallet/TestSign1ForAuthlete.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a1f1644d..1ec8ee91 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -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.3.0-SNAPSHOT" +eudi-lib-jvm-openid4vci-kt = "0.3.0" eudi-lib-jvm-siop-openid4vp-kt = "0.4.2" gradle-plugin = "7.4.0" identity-credential = "20231002" diff --git a/wallet-core/build.gradle b/wallet-core/build.gradle index 84871766..c4e3d429 100644 --- a/wallet-core/build.gradle +++ b/wallet-core/build.gradle @@ -83,6 +83,12 @@ android { } } + testOptions { + unitTests.all { + useJUnitPlatform() + } + } + // publishing { // singleVariant('release') { // withSourcesJar() diff --git a/wallet-core/src/androidTest/java/eu/europa/ec/eudi/wallet/document/issue/opeid4vci/CWTProofSignerTest.kt b/wallet-core/src/androidTest/java/eu/europa/ec/eudi/wallet/document/issue/opeid4vci/CWTProofSignerTest.kt index 30be2781..56cb29bf 100644 --- a/wallet-core/src/androidTest/java/eu/europa/ec/eudi/wallet/document/issue/opeid4vci/CWTProofSignerTest.kt +++ b/wallet-core/src/androidTest/java/eu/europa/ec/eudi/wallet/document/issue/opeid4vci/CWTProofSignerTest.kt @@ -16,15 +16,11 @@ package eu.europa.ec.eudi.wallet.document.issue.opeid4vci -import COSE.AlgorithmID -import COSE.Message -import COSE.MessageTag -import COSE.OneKey import android.app.KeyguardManager import android.content.Context import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry -import com.upokecenter.cbor.CBORObject +import com.nimbusds.jose.crypto.impl.ECDSA import eu.europa.ec.eudi.openid4vci.* import eu.europa.ec.eudi.wallet.document.CreateIssuanceRequestResult import eu.europa.ec.eudi.wallet.document.DocumentManager @@ -37,7 +33,6 @@ import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Assume.assumeTrue import org.junit.BeforeClass -import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import java.io.IOException @@ -117,6 +112,7 @@ class CWTProofSignerTest { val payload = "some random bytes".toByteArray() val proofSignature = proofSigner.sign(payload) + .let { ECDSA.transcodeSignatureToDER(it) } // convert it back to DER val publicKey = (proofSigner.popSigner.bindingKey as CwtBindingKey.CoseKey).jwk.toECKey().toPublicKey() val result = Signature.getInstance("SHA256withECDSA", BC).apply { @@ -126,46 +122,4 @@ class CWTProofSignerTest { assertTrue(result) documentManager.deleteDocumentById(issuanceRequest.documentId) } - - @Ignore("This is not for CI/CD use. This is just to test the sign1 message") - @Test - fun test_doSign_when_used_in_sign1_message_is_verified() { - val documentManager = DocumentManager.Builder(context) - .enableUserAuth(false) - .build() - - val issuanceRequestResult = documentManager.createIssuanceRequest("eu.europa.ec.eudiw.pid.1", false) - assertTrue(issuanceRequestResult is CreateIssuanceRequestResult.Success) - - val issuanceRequest = - (issuanceRequestResult as CreateIssuanceRequestResult.Success).issuanceRequest - - val cwtSigner = CWTProofSigner(issuanceRequest, SupportedProofAlgorithm.Cose.ES256_P_256) - val oneKey = OneKey(issuanceRequest.publicKey, null).AsCBOR() - val protectedHeaders = CBORObject.NewMap() - .Add(CBORObject.FromObject(1), AlgorithmID.ECDSA_256.AsCBOR()) - .Add(CBORObject.FromObject(3), "openid4vci-proof+cwt") - .Add("COSE_Key", oneKey) - .EncodeToBytes() - val unProtectedHeaders = CBORObject.NewMap() - val payload = byteArrayOf(1, 2, 3) - val structureToSign = CBORObject.NewArray() - .Add(protectedHeaders) - .Add(payload) - .EncodeToBytes() - val signature = cwtSigner.sign(structureToSign) - - val sign1Bytes = CBORObject.FromObjectAndTag( - CBORObject.NewArray().apply { - Add(protectedHeaders) - Add(unProtectedHeaders) - Add(payload) - Add(signature) - }, MessageTag.Sign1.value - ).EncodeToBytes() - - val sign1 = Message.DecodeFromBytes(sign1Bytes, MessageTag.Sign1) as COSE.Sign1Message - - sign1.validate(OneKey(sign1.protectedAttributes.get("COSE_Key"))) - } } \ No newline at end of file diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/CWTProofSigner.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/CWTProofSigner.kt index 0fe11aa6..1fd4828c 100644 --- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/CWTProofSigner.kt +++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/CWTProofSigner.kt @@ -52,5 +52,6 @@ internal class CWTProofSigner( */ fun sign(signingInput: ByteArray): ByteArray { return doSign(issuanceRequest, signingInput, supportedProofAlgorithm.signAlgorithmName) + .derToConcat(supportedProofAlgorithm) } } \ No newline at end of file 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 f592edff..9ba7f696 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 @@ -20,6 +20,7 @@ import android.content.Context import android.content.Intent import android.content.Intent.ACTION_VIEW import android.net.Uri +import android.util.Log import com.nimbusds.jose.jwk.Curve import eu.europa.ec.eudi.openid4vci.* import eu.europa.ec.eudi.wallet.document.AddDocumentResult @@ -34,6 +35,7 @@ import eu.europa.ec.eudi.wallet.issue.openid4vci.CredentialConfigurationFilter.C import eu.europa.ec.eudi.wallet.issue.openid4vci.IssueEvent.Companion.failure import eu.europa.ec.eudi.wallet.issue.openid4vci.ProofSigner.UserAuthStatus import kotlinx.coroutines.* +import org.bouncycastle.util.encoders.Hex import java.net.URI import java.util.* import java.util.concurrent.Executor @@ -92,6 +94,7 @@ internal class DefaultOpenId4VciManager( doIssueDocumentByOffer(offer, config, listener) } catch (e: Throwable) { + Log.e(TAG, "issueDocumentByDocType failed", e) listener(failure(e)) coroutineScope.cancel("issueDocumentByDocType failed", e) } @@ -109,6 +112,7 @@ internal class DefaultOpenId4VciManager( try { doIssueDocumentByOffer(offer, config, listener) } catch (e: Throwable) { + Log.e(TAG, "issueDocumentByOffer failed", e) listener(failure(e)) coroutineScope.cancel("issueDocumentByOffer failed", e) } @@ -125,18 +129,20 @@ internal class DefaultOpenId4VciManager( clearStateThen { launch(onIssueEvent.wrap(executor)) { coroutineScope, listener -> try { - val offer = offerUriCache[offerUri] - ?: CredentialOfferRequestResolver().resolve(offerUri).getOrThrow() - .let { - DefaultOffer( - it, Compose( - MsoMdocFormatFilter, - ProofTypeFilter(config.proofTypes) - ) + val offer = offerUriCache[offerUri].also { + Log.d(TAG, "OfferUri $offerUri cache hit") + } ?: CredentialOfferRequestResolver().resolve(offerUri).getOrThrow() + .let { + DefaultOffer( + it, Compose( + MsoMdocFormatFilter, + ProofTypeFilter(config.proofTypes) ) - } + ) + }.also { offerUriCache[offerUri] = it } doIssueDocumentByOffer(offer, config, listener) } catch (e: Throwable) { + Log.e(TAG, "issueDocumentByOfferUri failed", e) listener(failure(e)) coroutineScope.cancel("issueDocumentByOffer failed", e) } @@ -155,10 +161,12 @@ internal class DefaultOpenId4VciManager( val offer = DefaultOffer(credentialOffer, Compose(MsoMdocFormatFilter, ProofTypeFilter(config.proofTypes))) offerUriCache[offerUri] = offer + Log.d(TAG, "OfferUri $offerUri resolved") callback(OfferResult.Success(offer)) coroutineScope.cancel("resolveDocumentOffer succeeded") } catch (e: Throwable) { offerUriCache.remove(offerUri) + Log.e(TAG, "OfferUri $offerUri resolution failed", e) callback(OfferResult.Failure(e)) coroutineScope.cancel("resolveDocumentOffer failed", e) } @@ -209,6 +217,9 @@ internal class DefaultOpenId4VciManager( val issuanceRequest = documentManager .createIssuanceRequest(item, config.useStrongBoxIfSupported) .getOrThrow() + + Log.d(TAG, "Issuing document: ${issuanceRequest.documentId} for ${issuanceRequest.docType}") + doIssueCredential( authorizedRequest, item.configurationIdentifier, @@ -302,15 +313,19 @@ internal class DefaultOpenId4VciManager( addedDocuments: MutableSet, onEvent: OpenId4VciManager.OnResult ) { + Log.d(TAG, "doRequestSingleNoProof for ${issuanceRequest.documentId}") when (val outcome = authRequest.requestSingle(payload).getOrThrow()) { - is SubmittedRequest.InvalidProof -> doRequestSingleWithProof( - authRequest.handleInvalidProof(outcome.cNonce), - payload, - credentialConfiguration, - issuanceRequest, - addedDocuments, - onEvent - ) + is SubmittedRequest.InvalidProof -> { + Log.d(TAG, "doRequestSingleNoProof invalid proof") + doRequestSingleWithProof( + authRequest.handleInvalidProof(outcome.cNonce), + payload, + credentialConfiguration, + issuanceRequest, + addedDocuments, + onEvent + ) + } is SubmittedRequest.Failed -> onEvent(IssueEvent.DocumentFailed(issuanceRequest, outcome.error)) is SubmittedRequest.Success -> storeIssuedCredential( @@ -341,7 +356,9 @@ internal class DefaultOpenId4VciManager( addedDocuments: MutableSet, onEvent: OpenId4VciManager.OnResult ) { + Log.d(TAG, "doRequestSingleWithProof for ${issuanceRequest.documentId}") val proofSigner = ProofSigner(issuanceRequest, credentialConfiguration, config.proofTypes).getOrThrow() + Log.d(TAG, "doRequestSingleWithProof proofSigner: ${proofSigner::class.java.name}") try { when (val outcome = authRequest.requestSingle(payload, proofSigner.popSigner).getOrThrow()) { is SubmittedRequest.Failed -> onEvent(IssueEvent.DocumentFailed(issuanceRequest, outcome.error)) @@ -363,8 +380,10 @@ internal class DefaultOpenId4VciManager( } catch (e: Throwable) { when (val status = proofSigner.userAuthStatus) { is UserAuthStatus.Required -> { + Log.d(TAG, "doRequestSingleWithProof userAuthStatus: $status") val event = object : IssueEvent.DocumentRequiresUserAuth(issuanceRequest, status.cryptoObject) { override fun resume() { + Log.d(TAG, "doRequestSingleWithProof resume from user auth") runBlocking { doRequestSingleWithProof( authRequest, @@ -378,6 +397,7 @@ internal class DefaultOpenId4VciManager( } override fun cancel() { + Log.e(TAG, "doRequestSingleWithProof cancel from user auth") onEvent(IssueEvent.DocumentFailed(issuanceRequest, e.cause ?: e)) } } @@ -412,6 +432,10 @@ internal class DefaultOpenId4VciManager( is IssuedCredential.Issued -> { val cbor = Base64.getUrlDecoder().decode(issuedCredential.credential) + + Log.d(TAG, "storeIssuedCredential for ${issuanceRequest.documentId}") + Log.d(TAG, "storeIssuedCredential cbor: ${Hex.toHexString(cbor)}") + when (val addResult = documentManager.addDocument(issuanceRequest, cbor)) { is AddDocumentResult.Failure -> { documentManager.deleteDocumentById(issuanceRequest.documentId) @@ -433,11 +457,49 @@ internal class DefaultOpenId4VciManager( * @receiver The [OpenId4VciManager.OnResult]. * @return The wrapped [OpenId4VciManager.OnResult]. */ - private fun , V> R.wrap(executor: Executor?): OpenId4VciManager.OnResult { + private inline fun , reified V> R.wrap(executor: Executor?): OpenId4VciManager.OnResult { return OpenId4VciManager.OnResult { result: V -> (executor ?: context.mainExecutor()).execute { this@wrap.onResult(result) } + }.logResult() + } + + private inline fun , reified V> R.logResult(): OpenId4VciManager.OnResult { + return OpenId4VciManager.OnResult { result: V -> + when (result) { + is IssueEvent.DocumentIssued -> Log.d( + TAG, + "${IssueEvent.DocumentIssued::class.java.name} for ${result.documentId}" + ) + + is IssueEvent.DocumentFailed -> Log.e( + TAG, + IssueEvent.DocumentFailed::class.java.simpleName, + result.cause + ) + + is IssueEvent.DocumentRequiresUserAuth -> Log.d( + TAG, + IssueEvent.DocumentRequiresUserAuth::class.java.simpleName + ) + + is IssueEvent.Started -> Log.d( + TAG, + "${IssueEvent.Started::class.java.name} for ${result.total} documents" + ) + + is IssueEvent.Finished -> Log.d( + TAG, + "${IssueEvent.Finished::class.java.name} for ${result.issuedDocuments}" + ) + + is IssueEvent.Failure -> Log.e(TAG, IssueEvent.Failure::class.java.simpleName, result.cause) + is OfferResult.Failure -> Log.e(TAG, OfferResult.Failure::class.java.simpleName, result.error) + is OfferResult.Success -> Log.d(TAG, "${OfferResult.Success::class.java.name} for ${result.offer}") + else -> Log.d(TAG, V::class.java.simpleName) + } + this.onResult(result) } } @@ -461,7 +523,7 @@ internal class DefaultOpenId4VciManager( } companion object { - private const val TAG = "DefaultOpenId4VciManage" + internal const val TAG = "DefaultOpenId4VciManage" /** * Converts the [OpenId4VciManager.Config] to [OpenId4VCIConfig]. diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/JWSProofSigner.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/JWSProofSigner.kt index 3a1100ae..c8afb541 100644 --- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/JWSProofSigner.kt +++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/JWSProofSigner.kt @@ -70,7 +70,7 @@ internal class JWSProofSigner( ) } return doSign(issuanceRequest, signingInput, supportedProofAlgorithm.signAlgorithmName).let { signature -> - Base64URL.encode(signature.derToJose(header.algorithm)) + Base64URL.encode(signature.derToConcat(supportedProofAlgorithm)) } } } \ No newline at end of file diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/SupportedProofType.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/SupportedProofType.kt index fd351e5e..391a9b1a 100644 --- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/SupportedProofType.kt +++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/SupportedProofType.kt @@ -18,6 +18,7 @@ package eu.europa.ec.eudi.wallet.issue.openid4vci import com.nimbusds.jose.JWSAlgorithm +import com.nimbusds.jose.crypto.impl.ECDSA import eu.europa.ec.eudi.openid4vci.* import eu.europa.ec.eudi.wallet.document.Algorithm import eu.europa.ec.eudi.wallet.issue.openid4vci.SupportedProofType.ProofAlgorithm.Cose @@ -153,6 +154,7 @@ internal sealed interface SupportedProofType { * Proof algorithm for the supported proof type. * @property name the name of the proof algorithm * @property signAlgorithmName the name of the sign algorithm that it is used in the [eu.europa.ec.eudi.wallet.document.IssuanceRequest.signWithAuthKey] + * @property signatureByteArrayLength the length of the signature byte array to be use when converting the signature from DER to Concat format * method */ sealed interface ProofAlgorithm { @@ -161,6 +163,8 @@ internal sealed interface SupportedProofType { @get:Algorithm val signAlgorithmName: String + val signatureByteArrayLength: Int + /** * Proof algorithm for signing JWT with JWS. * @property algorithm the JWS algorithm @@ -170,9 +174,11 @@ internal sealed interface SupportedProofType { data class Jws( val algorithm: JWSAlgorithm, @Algorithm override val signAlgorithmName: String, - override val name: String = algorithm.name + override val name: String = algorithm.name, + override val signatureByteArrayLength: Int = ECDSA.getSignatureByteArrayLength(algorithm) ) : ProofAlgorithm { + /** * Companion object for [Jws] instances. * @property ES256 the ES256 proof algorithm @@ -194,7 +200,8 @@ internal sealed interface SupportedProofType { val coseAlgorithm: CoseAlgorithm, val coseCurve: CoseCurve, @Algorithm override val signAlgorithmName: String, - override val name: String = "${coseAlgorithm.name()}_${coseCurve.name()}" + override val name: String = "${coseAlgorithm.name()}_${coseCurve.name()}", + override val signatureByteArrayLength: Int ) : ProofAlgorithm { /** @@ -202,7 +209,8 @@ internal sealed interface SupportedProofType { * @property ES256_P_256 the ES256_P_256 proof algorithm for COSE ES256 with P-256 curve */ companion object { - val ES256_P_256 = Cose(CoseAlgorithm.ES256, CoseCurve.P_256, Algorithm.SHA256withECDSA) + val ES256_P_256 = + Cose(CoseAlgorithm.ES256, CoseCurve.P_256, Algorithm.SHA256withECDSA, signatureByteArrayLength = 64) } } } diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/SuspendedAuthorization.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/SuspendedAuthorization.kt index 780fe132..b37b083a 100644 --- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/SuspendedAuthorization.kt +++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/SuspendedAuthorization.kt @@ -18,6 +18,8 @@ package eu.europa.ec.eudi.wallet.issue.openid4vci import android.content.Intent import android.net.Uri +import android.util.Log +import eu.europa.ec.eudi.wallet.issue.openid4vci.DefaultOpenId4VciManager.Companion.TAG import kotlinx.coroutines.CancellableContinuation import kotlinx.coroutines.CancellationException import java.io.Closeable @@ -50,13 +52,21 @@ internal class SuspendedAuthorization( * @throws Throwable if the uri is invalid */ fun resumeFromUri(uri: Uri) { + Log.d(TAG, "resumeFromUri: $uri") try { uri.getQueryParameter("code")?.let { authorizationCode -> uri.getQueryParameter("state")?.let { serverState -> continuation.resume(Result.success(Response(authorizationCode, serverState))) - } ?: continuation.resumeWith(Result.failure(IllegalStateException("No server state found"))) - } ?: continuation.resumeWith(Result.failure(IllegalStateException("No authorization code found"))) + } ?: "No server state found".let { msg -> + Log.e(TAG, "resumeFromUri: msg") + continuation.resumeWith(Result.failure(IllegalStateException(msg))) + } + } ?: "No authorization code found".let { msg -> + Log.e(TAG, "resumeFromUri: msg") + continuation.resumeWith(Result.failure(IllegalStateException(msg))) + } } catch (e: Throwable) { + Log.e(TAG, "resumeFromUri exception", e) continuation.resumeWith(Result.failure(e)) } } diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Utils.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Utils.kt index e687f69f..135f3d05 100644 --- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Utils.kt +++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Utils.kt @@ -67,6 +67,26 @@ internal val PublicKey.pem: String wr.toString() } +/** + * Converts a signature in DER format to a concatenated format. + * @receiver the [ByteArray] + * @param signatureLength the length of the signature + * @return the concatenated signature + */ +@JvmSynthetic +internal fun ByteArray.derToConcat(signatureLength: Int) = + ECDSA.transcodeSignatureToConcat(this, signatureLength) + +/** + * Converts a signature in DER format to a concatenated format. + * @receiver the [ByteArray] + * @param algorithm the supported proof algorithm + * @return the concatenated signature + */ +@JvmSynthetic +internal fun ByteArray.derToConcat(algorithm: SupportedProofType.ProofAlgorithm) = + derToConcat(algorithm.signatureByteArrayLength) + /** * Converts the [ByteArray] to a JOSE signature. * @receiver the [ByteArray] @@ -76,5 +96,7 @@ internal val PublicKey.pem: String @JvmSynthetic internal fun ByteArray.derToJose(algorithm: JWSAlgorithm = JWSAlgorithm.ES256): ByteArray { val len = ECDSA.getSignatureByteArrayLength(algorithm) - return ECDSA.transcodeSignatureToConcat(this, len) -} \ No newline at end of file + return derToConcat(len) +} + + diff --git a/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/TestSign1ForAuthlete.kt b/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/TestSign1ForAuthlete.kt deleted file mode 100644 index 1d3f3a91..00000000 --- a/wallet-core/src/test/java/eu/europa/ec/eudi/wallet/TestSign1ForAuthlete.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 - -import COSE.Message -import COSE.MessageTag -import COSE.OneKey -import COSE.Sign1Message -import com.upokecenter.cbor.CBORObject -import org.bouncycastle.util.encoders.Hex -import org.junit.Assert -import org.junit.Ignore -import org.junit.Test - -class TestSign1ForAuthlete { - - @Ignore("This test is ignored because it is meant to be run only by hand. It is not a unit test.") - @Test - fun `test sign1 cwt that we send to authlete is verified`() { - - val sign1Hex = - // from example -// "d83dd284589da3012603746f70656e6964347663692d70726f6f662b63777468434f53455f4b6579a6010202582b3165354159394579423031586e557a61364c704a7a6b30326e36595f416d6d6e5362304642654e56567255032620012158203d2c50ac3db3974fe65dc02acf59a0a92781a018679b1db2c41129ac163c176d225820c55f1f6e2d454a8b14ba72deb8b36e2e4262aa663a4ca88c9eeafe1a7db0475da05860a4016c747261636b315f6c6967687403781a68747470733a2f2f747269616c2e617574686c6574652e6e6574061a665fdcab0a582b762d31622d6e38326b454a476248524f53656b47736d522d784575616d4378595f5430745874514e2d64595840461c38c8127b70ca2e491478da59c8764255513e9b15968d17367276ba2cecdaf4da83a343bef866d86f6fa516264859805d4d6cf7d836b6152eda61a42bf759" - - // from test - "d83dd284586da3012603746f70656e6964347663692d70726f6f662b63777468434f53455f4b6579a401022001215820c584947cb27885c927ee1d3062edbbb71b25f19b92d968f5767cb91cd7ff4abc225820cd2a0a3c52a3e94650a161272042d348f174e6b770a0f596ba8f1410f3629d68a05860a4016c747261636b315f6c6967687403781a68747470733a2f2f747269616c2e617574686c6574652e6e6574061a6661a0910a582b373432523836737067344e576c754c52483043716a6d303877477772747a3653325359553253587733636f584830460221009c14113a04660a35829efe0efd3c2278c95ef9983fab46f9c35eae54c26ae152022100aa789b9051d50757a4438574ac2a23ed9255f631f0efcc3447b5ba1e9e4237a6" - val sign1Bytes = Hex.decode(sign1Hex) - val cwtUntagged = CBORObject.DecodeFromBytes(sign1Bytes).let { - if (it.isTagged) it.Untag() else it - }.EncodeToBytes() - val sign1Message = Message.DecodeFromBytes(cwtUntagged, MessageTag.Sign1) as Sign1Message - val oneKey = OneKey(sign1Message.protectedAttributes.get("COSE_Key")) - Assert.assertTrue(sign1Message.validate(oneKey)) - } -} \ No newline at end of file