From 09d337f85f70e1c6514dc111757264330dc2a3ac Mon Sep 17 00:00:00 2001 From: Nitin Vavdiya Date: Tue, 11 Jun 2024 16:22:17 +0530 Subject: [PATCH] fix: VP validation tests --- .../service/IssuersCredentialServiceTest.java | 171 +----------------- .../utils/TestUtils.java | 23 ++- .../vc/PresentationValidationTest.java | 37 ++-- 3 files changed, 37 insertions(+), 194 deletions(-) diff --git a/miw/src/test/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialServiceTest.java b/miw/src/test/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialServiceTest.java index 6ed32280..6be2a0c3 100644 --- a/miw/src/test/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialServiceTest.java +++ b/miw/src/test/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialServiceTest.java @@ -27,6 +27,7 @@ import com.nimbusds.jwt.SignedJWT; import com.smartsensesolutions.java.commons.specification.SpecificationUtil; import lombok.SneakyThrows; +import org.apache.commons.lang3.time.DateUtils; import org.eclipse.tractusx.managedidentitywallets.config.MIWSettings; import org.eclipse.tractusx.managedidentitywallets.constant.StringPool; import org.eclipse.tractusx.managedidentitywallets.constant.SupportedAlgorithms; @@ -77,6 +78,7 @@ import java.sql.SQLException; import java.time.Duration; import java.time.Instant; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -136,6 +138,7 @@ public static void beforeAll() throws SQLException { when(dataSource.getConnection()).thenReturn(connection); when(miwSettings.encryptionKey()).thenReturn("26FlcjRKOEML8YW699CXlg=="); + when(miwSettings.vcExpiryDate()).thenReturn(DateUtils.addMonths(new Date(), 10)); encryptionUtils = new EncryptionUtils(miwSettings); issuersCredentialService = new IssuersCredentialService( @@ -155,174 +158,6 @@ public void beforeEach() { issuersCredentialRepository); } - @Nested - class issueMembershipCredentialTest { - - @Test - void shouldIssueCredentialAsJwt() - throws InvalidPrivateKeyFormatException, KeyTransformationException { - Map wallets = mockBaseAndHolderWallet(); - Wallet baseWallet = (Wallet) wallets.get("base"); - String baseWalletBpn = baseWallet.getBpn(); - Wallet holderWallet = (Wallet) wallets.get("holder"); - String holderWalletBpn = holderWallet.getBpn(); - String walletKeyId = "key-1"; - KeyPair keyPair = MockUtil.generateEDKeys(); - - mockCommon(baseWalletBpn, holderWalletBpn, keyPair, baseWallet, holderWallet); - MockUtil.makeFilterWorkForIssuer(issuersCredentialRepository); - MockUtil.makeCreateWorkForIssuer(issuersCredentialRepository); - - - - WalletKey walletKey = mock(WalletKey.class); - when(walletKey.getKeyId()).thenReturn(KEY_ID); - when(walletKey.getId()).thenReturn(42L); - when(baseWallet.getAlgorithm()).thenReturn("ED25519"); - when(baseWallet.getSigningServiceType()).thenReturn(SigningServiceType.LOCAL); - when(walletKeyService.getPrivateKeyByWalletIdAndAlgorithm(baseWallet.getId(), SupportedAlgorithms.valueOf(baseWallet.getAlgorithm()))) - .thenReturn(new X25519PrivateKey(keyPair.getPrivateKey().asStringForStoring(), true)); - when(walletKeyService.getWalletKeyIdByWalletId(baseWallet.getId(), SupportedAlgorithms.ED25519)).thenReturn(walletKeyId); - when(walletKeyService.getPrivateKeyByWalletIdAsBytes(baseWallet.getId(), "ED25519")).thenReturn(keyPair.getPrivateKey() - .asByte()); - - - when(walletKeyService.getPrivateKeyByKeyId(anyString(), any())).thenReturn(keyPair.getPrivateKey()); - when(walletKeyRepository.getByAlgorithmAndWallet_Bpn(anyString(), anyString())).thenReturn(walletKey); - - LocalSigningServiceImpl localSigningService = new LocalSigningServiceImpl(secureTokenService); - localSigningService.setKeyProvider(new LocalKeyProvider(walletKeyService, walletKeyRepository, encryptionUtils)); - - Map map = new HashMap<>(); - map.put(SigningServiceType.LOCAL, localSigningService); - - issuersCredentialService.setKeyService(map); - - //TODO need to check what could be done - /*CredentialsResponse credentialsResponse = assertDoesNotThrow( - () -> issuersCredentialService.issueMembershipCredential( - issueMembershipCredentialRequest, - true, - baseWalletBpn)); - - validateCredentialResponse(credentialsResponse, MockUtil.buildDidDocument(new Did(new DidMethod("web"), - new DidMethodIdentifier("basewallet"), - null), keyPair));*/ - } - } - - @Nested - class issueFrameWorkCredentialTest { - - @Test - void shouldIssueCredentialAsJwt() - throws InvalidPrivateKeyFormatException, JwtException, KeyTransformationException { - Map wallets = mockBaseAndHolderWallet(); - Wallet baseWallet = (Wallet) wallets.get("base"); - String baseWalletBpn = baseWallet.getBpn(); - Wallet holderWallet = (Wallet) wallets.get("holder"); - String holderWalletBpn = holderWallet.getBpn(); - String walletKeyId = "key-1"; - - KeyPair keyPair = MockUtil.generateEDKeys(); - - mockCommon(baseWalletBpn, holderWalletBpn, keyPair, baseWallet, holderWallet); - MockUtil.makeFilterWorkForIssuer(issuersCredentialRepository); - MockUtil.makeCreateWorkForIssuer(issuersCredentialRepository); - - - //TODO need to check - /*when(holdersCredentialRepository.getByHolderDidAndIssuerDidAndTypeAndStored( - any(String.class), - any(String.class), - eq(MIWVerifiableCredentialType.SUMMARY_CREDENTIAL), - eq(false) - )).thenReturn(Collections.emptyList());*/ - - WalletKey walletKey = mock(WalletKey.class); - when(walletKey.getKeyId()).thenReturn(KEY_ID); - when(walletKey.getId()).thenReturn(42L); - when(baseWallet.getAlgorithm()).thenReturn("ED25519"); - when(walletKeyService.getPrivateKeyByWalletIdAsBytes(baseWallet.getId(), "ED25519")).thenReturn(keyPair.getPrivateKey() - .asByte()); - when(walletKeyService.getPrivateKeyByWalletIdAndAlgorithm(baseWallet.getId(), SupportedAlgorithms.valueOf(baseWallet.getAlgorithm()))) - .thenReturn(new X25519PrivateKey(keyPair.getPrivateKey().asStringForStoring(), true)); - when(walletKeyService.getWalletKeyIdByWalletId(baseWallet.getId(), SupportedAlgorithms.ED25519)).thenReturn(walletKeyId); - - - when(baseWallet.getSigningServiceType()).thenReturn(SigningServiceType.LOCAL); - when(walletKeyService.getPrivateKeyByKeyId(anyString(), any())).thenReturn(keyPair.getPrivateKey()); - when(walletKeyRepository.getByAlgorithmAndWallet_Bpn(anyString(), anyString())).thenReturn(walletKey); - - LocalSigningServiceImpl localSigningService = new LocalSigningServiceImpl(secureTokenService); - localSigningService.setKeyProvider(new LocalKeyProvider(walletKeyService, walletKeyRepository, encryptionUtils)); - - Map map = new HashMap<>(); - map.put(SigningServiceType.LOCAL, localSigningService); - - issuersCredentialService.setKeyService(map); - - - //TODO need to check what could be done - /* CredentialsResponse credentialsResponse = assertDoesNotThrow( - () -> issuersCredentialService.issueFrameworkCredential(request, true, baseWalletBpn)); - validateCredentialResponse(credentialsResponse, MockUtil.buildDidDocument(new Did(new DidMethod("web"), - new DidMethodIdentifier("basewallet"), - null), keyPair));*/ - } - } - - @Nested - class issueDismantlerCredentialTest { - - @Test - void shouldIssueCredentialAsJwt() throws InvalidPrivateKeyFormatException, - JwtException, KeyTransformationException { - Map wallets = mockBaseAndHolderWallet(); - Wallet baseWallet = (Wallet) wallets.get("base"); - String baseWalletBpn = baseWallet.getBpn(); - Wallet holderWallet = (Wallet) wallets.get("holder"); - String holderWalletBpn = holderWallet.getBpn(); - String walletKeyId = "key-1"; - KeyPair keyPair = MockUtil.generateEDKeys(); - - mockCommon(baseWalletBpn, holderWalletBpn, keyPair, baseWallet, holderWallet); - MockUtil.makeFilterWorkForIssuer(issuersCredentialRepository); - MockUtil.makeCreateWorkForIssuer(issuersCredentialRepository); - - - - WalletKey walletKey = mock(WalletKey.class); - when(walletKey.getKeyId()).thenReturn(KEY_ID); - when(walletKey.getId()).thenReturn(42L); - when(baseWallet.getAlgorithm()).thenReturn("ED25519"); - when(walletKeyService.getPrivateKeyByWalletIdAndAlgorithm(baseWallet.getId(), SupportedAlgorithms.valueOf(baseWallet.getAlgorithm()))) - .thenReturn(new X25519PrivateKey(keyPair.getPrivateKey().asStringForStoring(), true)); - when(walletKeyService.getPrivateKeyByWalletIdAsBytes(baseWallet.getId(), "ED25519")).thenReturn(keyPair.getPrivateKey().asByte()); - when(walletKeyService.getWalletKeyIdByWalletId(baseWallet.getId(), SupportedAlgorithms.ED25519)).thenReturn(walletKeyId); - - - when(baseWallet.getSigningServiceType()).thenReturn(SigningServiceType.LOCAL); - when(walletKeyService.getPrivateKeyByKeyId(anyString(), any())).thenReturn(keyPair.getPrivateKey()); - when(walletKeyRepository.getByAlgorithmAndWallet_Bpn(anyString(), anyString())).thenReturn(walletKey); - - LocalSigningServiceImpl localSigningService = new LocalSigningServiceImpl(secureTokenService); - localSigningService.setKeyProvider(new LocalKeyProvider(walletKeyService, walletKeyRepository, encryptionUtils)); - - Map map = new HashMap<>(); - map.put(SigningServiceType.LOCAL, localSigningService); - - issuersCredentialService.setKeyService(map); - - //TODO need to check - /* CredentialsResponse credentialsResponse = assertDoesNotThrow( - () -> issuersCredentialService.issueDismantlerCredential(request, true, baseWalletBpn)); - validateCredentialResponse(credentialsResponse, MockUtil.buildDidDocument(new Did(new DidMethod("web"), - new DidMethodIdentifier("basewallet"), - null), keyPair));*/ - } - } - @Nested class issueCredentialUsingBaseWallet { diff --git a/miw/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/TestUtils.java b/miw/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/TestUtils.java index f616c8cf..71a0d980 100644 --- a/miw/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/TestUtils.java +++ b/miw/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/TestUtils.java @@ -64,7 +64,6 @@ import java.util.Date; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.UUID; import static org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames.ACCESS_TOKEN; @@ -227,6 +226,17 @@ public static Wallet buildWallet(String bpn, String did, String didJson) { public static VerifiableCredential issueCustomVCUsingBaseWallet(String holderDid, String issuerDid, String type, HttpHeaders headers, MIWSettings miwSettings, ObjectMapper objectMapper, TestRestTemplate restTemplate) { + Map map = getCredentialAsMap(issuerDid, type, miwSettings, objectMapper); + HttpEntity entity = new HttpEntity<>(map, headers); + ResponseEntity response = restTemplate.exchange(RestURI.ISSUERS_CREDENTIALS + "?holderDid={did}", HttpMethod.POST, entity, String.class, holderDid); + if (response.getStatusCode().value() == HttpStatus.FORBIDDEN.value()) { + throw new ForbiddenException(); + } + Assertions.assertEquals(HttpStatus.CREATED.value(), response.getStatusCode().value()); + return new VerifiableCredential(new ObjectMapper().readValue(response.getBody(), Map.class)); + } + + public static Map getCredentialAsMap(String issuerDid, String type, MIWSettings miwSettings, ObjectMapper objectMapper) throws JsonProcessingException { // Create VC without proof //VC Builder VerifiableCredentialBuilder verifiableCredentialBuilder = @@ -234,7 +244,7 @@ public static VerifiableCredential issueCustomVCUsingBaseWallet(String holderDid //VC Subject VerifiableCredentialSubject verifiableCredentialSubject = - new VerifiableCredentialSubject(Map.of("test", "test")); + new VerifiableCredentialSubject(Map.of("id", "test")); //Using Builder VerifiableCredential credentialWithoutProof = @@ -248,13 +258,6 @@ public static VerifiableCredential issueCustomVCUsingBaseWallet(String holderDid .credentialSubject(verifiableCredentialSubject) .build(); - Map map = objectMapper.readValue(credentialWithoutProof.toJson(), Map.class); - HttpEntity entity = new HttpEntity<>(map, headers); - ResponseEntity response = restTemplate.exchange(RestURI.ISSUERS_CREDENTIALS + "?holderDid={did}", HttpMethod.POST, entity, String.class, holderDid); - if (response.getStatusCode().value() == HttpStatus.FORBIDDEN.value()) { - throw new ForbiddenException(); - } - Assertions.assertEquals(HttpStatus.CREATED.value(), response.getStatusCode().value()); - return new VerifiableCredential(new ObjectMapper().readValue(response.getBody(), Map.class)); + return objectMapper.readValue(credentialWithoutProof.toJson(), Map.class); } } diff --git a/miw/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/PresentationValidationTest.java b/miw/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/PresentationValidationTest.java index b7764045..f652f636 100644 --- a/miw/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/PresentationValidationTest.java +++ b/miw/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/PresentationValidationTest.java @@ -34,6 +34,7 @@ import org.eclipse.tractusx.managedidentitywallets.constant.StringPool; import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; import org.eclipse.tractusx.managedidentitywallets.dto.CreateWalletRequest; +import org.eclipse.tractusx.managedidentitywallets.dto.CredentialsResponse; import org.eclipse.tractusx.managedidentitywallets.service.IssuersCredentialService; import org.eclipse.tractusx.managedidentitywallets.service.PresentationService; import org.eclipse.tractusx.managedidentitywallets.service.WalletService; @@ -92,9 +93,10 @@ class PresentationValidationTest { private String bpnOperator; private Did tenant_1; private Did tenant_2; - private VerifiableCredential membershipCredential_1; - private VerifiableCredential membershipCredential_2; + private VerifiableCredential vc_1; + private VerifiableCredential vc_2; + @SneakyThrows @BeforeEach public void setup() throws DidParseException { bpnOperator = miwSettings.authorityWalletBpn(); @@ -116,18 +118,21 @@ public void setup() throws DidParseException { tenant_2 = DidParser.parse(tenantWallet2.getDid()); - //TODO need to fix test cases - /*CredentialsResponse rs1 = issuersCredentialService.issueMembershipCredential(issueMembershipCredentialRequest, false, bpnOperator); - membershipCredential_1 = new ObjectMapper().convertValue(rs1, VerifiableCredential.class); - IssueMembershipCredentialRequest issueMembershipCredentialRequest2 = new IssueMembershipCredentialRequest(); - issueMembershipCredentialRequest2.setBpn(bpnTenant_2); - CredentialsResponse rs2 = issuersCredentialService.issueMembershipCredential(issueMembershipCredentialRequest2, false, bpnOperator); - membershipCredential_2 = new ObjectMapper().convertValue(rs2, VerifiableCredential.class);*/ + Map type1 = TestUtils.getCredentialAsMap(miwSettings.authorityWalletDid(), "Type1", miwSettings, new com.fasterxml.jackson.databind.ObjectMapper()); + + CredentialsResponse rs1 = issuersCredentialService.issueCredentialUsingBaseWallet(tenantWallet.getDid(), type1, false, bpnOperator); + vc_1 = new ObjectMapper().convertValue(rs1, VerifiableCredential.class); + + + Map type2 = TestUtils.getCredentialAsMap(miwSettings.authorityWalletDid(), "Type2", miwSettings, new com.fasterxml.jackson.databind.ObjectMapper()); + + CredentialsResponse rs2 = issuersCredentialService.issueCredentialUsingBaseWallet(tenantWallet.getDid(), type2, false, bpnOperator); + vc_2 = new ObjectMapper().convertValue(rs2, VerifiableCredential.class); } @Test void testSuccessfulValidation() { - Map presentation = createPresentationJwt(membershipCredential_1, tenant_1); + Map presentation = createPresentationJwt(vc_1, tenant_1); VerifiablePresentationValidationResponse response = validateJwtOfCredential(presentation); Assertions.assertTrue(response.valid); } @@ -135,7 +140,7 @@ void testSuccessfulValidation() { @Test @SneakyThrows public void testSuccessfulValidationForMultipleVC() { - Map creationResponse = createPresentationJwt(List.of(membershipCredential_1, membershipCredential_2), tenant_1); + Map creationResponse = createPresentationJwt(List.of(vc_1, vc_2), tenant_1); // get the payload of the json web token String encodedJwtPayload = ((String) creationResponse.get("vp")).split("\\.")[1]; Map decodedJwtPayload = OBJECT_MAPPER.readValue(Base64.getUrlDecoder().decode(encodedJwtPayload), Map.class); @@ -151,7 +156,7 @@ public void testSuccessfulValidationForMultipleVC() { public void testValidationFailureOfCredentialWitInvalidExpirationDate() { // test is related to this old issue where the signature check still succeeded // https://github.com/eclipse-tractusx/SSI-agent-lib/issues/4 - VerifiableCredential copyCredential = new VerifiableCredential(membershipCredential_1); + VerifiableCredential copyCredential = new VerifiableCredential(vc_1); // e.g. an attacker tries to extend the validity of a verifiable credential copyCredential.put(VerifiableCredential.EXPIRATION_DATE, "2500-09-30T22:00:00Z"); Map presentation = createPresentationJwt(copyCredential, tenant_1); @@ -164,10 +169,10 @@ public void testValidationFailureOfCredentialWitInvalidExpirationDate() { public void testValidationFailureOfCredentialWitInvalidExpirationDateInSecondCredential() { // test is related to this old issue where the signature check still succeeded // https://github.com/eclipse-tractusx/SSI-agent-lib/issues/4 - VerifiableCredential copyCredential = new VerifiableCredential(membershipCredential_1); + VerifiableCredential copyCredential = new VerifiableCredential(vc_1); // e.g. an attacker tries to extend the validity of a verifiable credential copyCredential.put(VerifiableCredential.EXPIRATION_DATE, "2500-09-30T22:00:00Z"); - Map presentation = createPresentationJwt(List.of(membershipCredential_1, copyCredential), tenant_1); + Map presentation = createPresentationJwt(List.of(vc_1, copyCredential), tenant_1); VerifiablePresentationValidationResponse response = validateJwtOfCredential(presentation); Assertions.assertFalse(response.valid); } @@ -175,7 +180,7 @@ public void testValidationFailureOfCredentialWitInvalidExpirationDateInSecondCre @Test @SneakyThrows void testValidationFailureOfPresentationPayloadManipulation() { - Map presentation = createPresentationJwt(membershipCredential_1, tenant_1); + Map presentation = createPresentationJwt(vc_1, tenant_1); String jwt = (String) presentation.get(StringPool.VP); String payload = jwt.split("\\.")[1]; @@ -190,7 +195,7 @@ void testValidationFailureOfPresentationPayloadManipulation() { .context(List.of(VerifiablePresentation.DEFAULT_CONTEXT)) .id(URI.create("did:test:" + UUID.randomUUID())) .type(List.of(VerifiablePresentationType.VERIFIABLE_PRESENTATION)) - .verifiableCredentials(List.of(membershipCredential_2)) + .verifiableCredentials(List.of(vc_2)) .build(); payloadMap.put("vp", newPresentation); String newPayloadJson = OBJECT_MAPPER.writeValueAsString(payloadMap);