diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/StringPool.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/StringPool.java index 0c11b49eb..47de3c147 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/StringPool.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/StringPool.java @@ -33,6 +33,7 @@ public class StringPool { public static final String ALLOWED_VEHICLE_BRANDS = "allowedVehicleBrands"; public static final String VERIFIABLE_CREDENTIALS = "verifiableCredentials"; public static final String VP = "vp"; + public static final String VC = "vc"; public static final String VALID = "valid"; public static final String VALIDATE_AUDIENCE = "validateAudience"; public static final String VALIDATE_EXPIRY_DATE = "validateExpiryDate"; diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/HoldersCredentialService.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/HoldersCredentialService.java index 869e7d0a6..8f3fa1a33 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/HoldersCredentialService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/HoldersCredentialService.java @@ -152,7 +152,7 @@ public CredentialsResponse issueCredential(Map data, boolean asJ Validate.isFalse(callerBpn.equals(issuerWallet.getBpn())).launch(new ForbiddenException(BASE_WALLET_BPN_IS_NOT_MATCHING_WITH_REQUEST_BPN_FROM_TOKEN)); // get Key - byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdentifierAsBytes(issuerWallet.getId()); + byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdAsBytes(issuerWallet.getId()); // check if the expiryDate is set Date expiryDate = null; diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialService.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialService.java index 9c243c30f..59e773f4f 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialService.java @@ -21,6 +21,8 @@ package org.eclipse.tractusx.managedidentitywallets.service; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.nimbusds.jwt.SignedJWT; import com.smartsensesolutions.java.commons.FilterRequest; import com.smartsensesolutions.java.commons.base.repository.BaseRepository; import com.smartsensesolutions.java.commons.base.service.BaseService; @@ -29,6 +31,8 @@ import com.smartsensesolutions.java.commons.sort.Sort; import com.smartsensesolutions.java.commons.sort.SortType; import com.smartsensesolutions.java.commons.specification.SpecificationUtil; + +import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.text.StringEscapeUtils; @@ -40,6 +44,7 @@ import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; import org.eclipse.tractusx.managedidentitywallets.dao.repository.HoldersCredentialRepository; import org.eclipse.tractusx.managedidentitywallets.dao.repository.IssuersCredentialRepository; +import org.eclipse.tractusx.managedidentitywallets.dto.CredentialVerificationRequest; import org.eclipse.tractusx.managedidentitywallets.dto.CredentialsResponse; import org.eclipse.tractusx.managedidentitywallets.dto.IssueDismantlerCredentialRequest; import org.eclipse.tractusx.managedidentitywallets.dto.IssueFrameworkCredentialRequest; @@ -52,11 +57,15 @@ import org.eclipse.tractusx.ssi.lib.did.resolver.DidResolver; import org.eclipse.tractusx.ssi.lib.did.web.DidWebResolver; import org.eclipse.tractusx.ssi.lib.did.web.util.DidWebParser; +import org.eclipse.tractusx.ssi.lib.exception.proof.JwtExpiredException; +import org.eclipse.tractusx.ssi.lib.jwt.SignedJwtValidator; +import org.eclipse.tractusx.ssi.lib.jwt.SignedJwtVerifier; import org.eclipse.tractusx.ssi.lib.model.did.DidDocument; import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredentialSubject; import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredentialType; import org.eclipse.tractusx.ssi.lib.proof.LinkedDataProofValidation; +import org.eclipse.tractusx.ssi.lib.serialization.SerializeUtil; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.stereotype.Service; @@ -66,7 +75,9 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; +import java.io.IOException; import java.net.http.HttpClient; +import java.text.ParseException; import java.time.Instant; import java.util.*; @@ -75,6 +86,7 @@ */ @Service @Slf4j +@RequiredArgsConstructor public class IssuersCredentialService extends BaseService { /** @@ -93,26 +105,7 @@ public class IssuersCredentialService extends BaseService credentialSpecificationUtil, - WalletKeyService walletKeyService, HoldersCredentialRepository holdersCredentialRepository, CommonService commonService) { - this.issuersCredentialRepository = issuersCredentialRepository; - this.miwSettings = miwSettings; - this.credentialSpecificationUtil = credentialSpecificationUtil; - this.walletKeyService = walletKeyService; - this.holdersCredentialRepository = holdersCredentialRepository; - this.commonService = commonService; - } + private final ObjectMapper objectMapper; @Override @@ -190,7 +183,7 @@ public PageImpl getCredentials(String credentialId, String */ @Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation = Propagation.REQUIRED) public VerifiableCredential issueBpnCredential(Wallet baseWallet, Wallet holderWallet, boolean authority) { - byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdentifierAsBytes(baseWallet.getId()); + byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdAsBytes(baseWallet.getId()); List types = List.of(VerifiableCredentialType.VERIFIABLE_CREDENTIAL, MIWVerifiableCredentialType.BPN_CREDENTIAL); VerifiableCredentialSubject verifiableCredentialSubject = new VerifiableCredentialSubject(Map.of(StringPool.TYPE, MIWVerifiableCredentialType.BPN_CREDENTIAL, StringPool.ID, holderWallet.getDid(), @@ -233,7 +226,7 @@ public CredentialsResponse issueFrameworkCredential(IssueFrameworkCredentialRequ validateAccess(callerBPN, baseWallet); // get Key - byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdentifierAsBytes(baseWallet.getId()); + byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdAsBytes(baseWallet.getId()); //if base wallet issue credentials to itself boolean isSelfIssued = isSelfIssued(holderWallet.getBpn()); @@ -293,7 +286,7 @@ public CredentialsResponse issueDismantlerCredential(IssueDismantlerCredentialRe //check duplicate isCredentialExit(holderWallet.getDid(), MIWVerifiableCredentialType.DISMANTLER_CREDENTIAL); - byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdentifierAsBytes(issuerWallet.getId()); + byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdAsBytes(issuerWallet.getId()); //if base wallet issue credentials to itself boolean isSelfIssued = isSelfIssued(request.getBpn()); @@ -352,7 +345,7 @@ public CredentialsResponse issueMembershipCredential(IssueMembershipCredentialRe validateAccess(callerBPN, issuerWallet); - byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdentifierAsBytes(issuerWallet.getId()); + byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdAsBytes(issuerWallet.getId()); List types = List.of(VerifiableCredentialType.VERIFIABLE_CREDENTIAL, VerifiableCredentialType.MEMBERSHIP_CREDENTIAL); //if base wallet issue credentials to itself @@ -417,7 +410,7 @@ public CredentialsResponse issueCredentialUsingBaseWallet(String holderDid, Map< validateAccess(callerBpn, issuerWallet); // get issuer Key - byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdentifierAsBytes(issuerWallet.getId()); + byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdAsBytes(issuerWallet.getId()); boolean isSelfIssued = isSelfIssued(holderWallet.getBpn()); @@ -449,31 +442,105 @@ public CredentialsResponse issueCredentialUsingBaseWallet(String holderDid, Map< return cr; } + + + private JWTVerificationResult verifyVCAsJWT(String jwt, DidResolver didResolver, boolean withCredentialsValidation, boolean withCredentialExpiryDate) throws IOException, ParseException { + SignedJWT signedJWT = SignedJWT.parse(jwt); + Map claims = objectMapper.readValue(signedJWT.getPayload().toBytes(), Map.class); + String vcClaim = objectMapper.writeValueAsString(claims.get("vc")); + Map map = SerializeUtil.fromJson(vcClaim); + VerifiableCredential verifiableCredential = new VerifiableCredential(map); + + //took this approach to avoid issues in sonarQube + return new JWTVerificationResult(validateSignature(withCredentialsValidation , signedJWT, didResolver) && validateJWTExpiryDate(withCredentialExpiryDate, signedJWT), verifiableCredential); + + } + + private record JWTVerificationResult(boolean valid, VerifiableCredential verifiableCredential) { + + } + + private boolean validateSignature(boolean withValidateSignature, SignedJWT signedJWT, DidResolver didResolver) { + if(!withValidateSignature) { + return true; + } + //validate jwt signature + try { + SignedJwtVerifier jwtVerifier = new SignedJwtVerifier(didResolver); + return jwtVerifier.verify(signedJWT); + } catch (Exception e) { + log.error("Can not verify signature of jwt", e); + return false; + } + } + private boolean validateJWTExpiryDate(boolean withExpiryDate , SignedJWT signedJWT) { + if(!withExpiryDate) { + return true; + } + try { + SignedJwtValidator jwtValidator = new SignedJwtValidator(); + jwtValidator.validateDate(signedJWT); + return true; + } catch (Exception e) { + if (!(e instanceof JwtExpiredException)) { + log.error("Can not validate jwt expiry date ", e); + } + return false; + } + } /** * Credentials validation map. + * + * @param verificationRequest the verifiable credential + * @param withCredentialExpiryDate the with credential expiry date + * @return the map + */ + public Map credentialsValidation(CredentialVerificationRequest verificationRequest, boolean withCredentialExpiryDate) { + return credentialsValidation(verificationRequest, true, withCredentialExpiryDate); + } + + /** + * Credentials validation map. * * @param data the data * @param withCredentialExpiryDate the with credential expiry date * @return the map */ @SneakyThrows - public Map credentialsValidation(Map data, boolean withCredentialExpiryDate) { - VerifiableCredential verifiableCredential = new VerifiableCredential(data); + public Map credentialsValidation(CredentialVerificationRequest verificationRequest, boolean withCredentialsValidation , boolean withCredentialExpiryDate) { + HttpClient httpClient = HttpClient.newBuilder() + .followRedirects(HttpClient.Redirect.ALWAYS) + .build(); - DidResolver didResolver = new DidWebResolver(HttpClient.newHttpClient(), new DidWebParser(), miwSettings.enforceHttps()); + DidResolver didResolver = new DidWebResolver(httpClient, new DidWebParser(), miwSettings.enforceHttps()); + Map response = new TreeMap<>(); + boolean valid; + VerifiableCredential verifiableCredential; + boolean dateValidation = true; + + if (verificationRequest.containsKey(StringPool.VC_JWT_KEY)) { + JWTVerificationResult result = verifyVCAsJWT((String) verificationRequest.get(StringPool.VC_JWT_KEY), didResolver, withCredentialsValidation, withCredentialExpiryDate); + verifiableCredential = result.verifiableCredential; + valid = result.valid; + } else { - LinkedDataProofValidation proofValidation = LinkedDataProofValidation.newInstance(didResolver); + verifiableCredential = new VerifiableCredential(verificationRequest); + LinkedDataProofValidation proofValidation = LinkedDataProofValidation.newInstance(didResolver); - boolean valid = proofValidation.verify(verifiableCredential); - Map response = new TreeMap<>(); + if (withCredentialsValidation) { + valid = proofValidation.verify(verifiableCredential); + } else { + valid = true; + } - //check expiry - boolean dateValidation = CommonService.validateExpiry(withCredentialExpiryDate, verifiableCredential, response); + dateValidation = CommonService.validateExpiry(withCredentialExpiryDate, verifiableCredential, + response); + } response.put(StringPool.VALID, valid && dateValidation); - response.put("vc", verifiableCredential); + response.put(StringPool.VC, verificationRequest); return response; } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/WalletKeyService.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/WalletKeyService.java index 4584fea5c..5ba6673ba 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/WalletKeyService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/WalletKeyService.java @@ -65,7 +65,7 @@ protected SpecificationUtil getSpecificationUtil() { * @return the byte [ ] */ @SneakyThrows - public byte[] getPrivateKeyByWalletIdentifierAsBytes(long walletId) { + public byte[] getPrivateKeyByWalletIdAsBytes(long walletId) { return getPrivateKeyByWalletId(walletId).asByte(); } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/CommonUtils.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/CommonUtils.java index fd2060ce5..7bfa2f1e9 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/CommonUtils.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/CommonUtils.java @@ -55,6 +55,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Optional; import java.util.UUID; import java.util.regex.Pattern; @@ -171,7 +172,7 @@ public static String vcAsJwt(Wallet issuerWallet, Wallet holderWallet, Verifiabl x25519PrivateKey privateKey = walletKeyService.getPrivateKeyByWalletId(issuerWallet.getId()); // JWT Factory - SignedJWT vcJWT = vcFactory.createVCJwt(issuerDid, holderDid, Date.from(vc.getExpirationDate()), vc, + SignedJWT vcJWT = vcFactory.createVCJwt(issuerDid, holderDid, vc, privateKey, walletKeyService.getWalletKeyIdByWalletId(issuerWallet.getId())); diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialServiceTest.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialServiceTest.java new file mode 100644 index 000000000..5863616e7 --- /dev/null +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialServiceTest.java @@ -0,0 +1,474 @@ +/* + * ******************************************************************************* + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + * ****************************************************************************** + */ + +package org.eclipse.tractusx.managedidentitywallets.service; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.tomakehurst.wiremock.junit5.WireMockExtension; +import com.nimbusds.jose.JWSObject; +import com.nimbusds.jwt.SignedJWT; +import com.smartsensesolutions.java.commons.specification.SpecificationUtil; + +import lombok.SneakyThrows; + +import org.eclipse.tractusx.managedidentitywallets.config.MIWSettings; +import org.eclipse.tractusx.managedidentitywallets.constant.MIWVerifiableCredentialType; +import org.eclipse.tractusx.managedidentitywallets.constant.StringPool; +import org.eclipse.tractusx.managedidentitywallets.dao.entity.HoldersCredential; +import org.eclipse.tractusx.managedidentitywallets.dao.entity.IssuersCredential; +import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; +import org.eclipse.tractusx.managedidentitywallets.dao.entity.WalletKey; +import org.eclipse.tractusx.managedidentitywallets.dao.repository.HoldersCredentialRepository; +import org.eclipse.tractusx.managedidentitywallets.dao.repository.IssuersCredentialRepository; +import org.eclipse.tractusx.managedidentitywallets.dto.CredentialVerificationRequest; +import org.eclipse.tractusx.managedidentitywallets.dto.CredentialsResponse; +import org.eclipse.tractusx.managedidentitywallets.dto.IssueDismantlerCredentialRequest; +import org.eclipse.tractusx.managedidentitywallets.dto.IssueFrameworkCredentialRequest; +import org.eclipse.tractusx.managedidentitywallets.dto.IssueMembershipCredentialRequest; +import org.eclipse.tractusx.managedidentitywallets.utils.MockUtil; +import org.eclipse.tractusx.managedidentitywallets.utils.TestUtils; +import org.eclipse.tractusx.ssi.lib.crypt.KeyPair; +import org.eclipse.tractusx.ssi.lib.crypt.octet.OctetKeyPairFactory; +import org.eclipse.tractusx.ssi.lib.crypt.x25519.x25519PrivateKey; +import org.eclipse.tractusx.ssi.lib.did.resolver.DidResolver; +import org.eclipse.tractusx.ssi.lib.exception.did.DidParseException; +import org.eclipse.tractusx.ssi.lib.exception.did.DidResolverException; +import org.eclipse.tractusx.ssi.lib.exception.key.InvalidPrivateKeyFormatException; +import org.eclipse.tractusx.ssi.lib.exception.key.KeyTransformationException; +import org.eclipse.tractusx.ssi.lib.jwt.SignedJwtFactory; +import org.eclipse.tractusx.ssi.lib.jwt.SignedJwtVerifier; +import org.eclipse.tractusx.ssi.lib.model.did.Did; +import org.eclipse.tractusx.ssi.lib.model.did.DidDocument; +import org.eclipse.tractusx.ssi.lib.model.did.DidMethod; +import org.eclipse.tractusx.ssi.lib.model.did.DidMethodIdentifier; +import org.eclipse.tractusx.ssi.lib.model.did.DidParser; +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; +import org.eclipse.tractusx.ssi.lib.serialization.jwt.SerializedJwtVCFactoryImpl; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.springframework.security.oauth2.jwt.JwtException; + +import java.io.IOException; +import java.sql.Connection; +import java.sql.SQLException; +import java.text.ParseException; +import java.time.Duration; +import java.time.Instant; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.sql.DataSource; + +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.ok; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class IssuersCredentialServiceTest { + public static final String DID_WEB_LOCALHOST = "did:web:localhost"; + + public static final Did ISSUER = MockUtil.generateDid("caller"); + public static final String KEY_ID = "key-1"; + + private static MIWSettings miwSettings; + + private static WalletKeyService walletKeyService; + + private static HoldersCredentialRepository holdersCredentialRepository; + + private static CommonService commonService; + + private static IssuersCredentialRepository issuersCredentialRepository; + + private static IssuersCredentialService issuersCredentialService; + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @BeforeAll + public static void beforeAll() throws SQLException { + + miwSettings = Mockito.mock(MIWSettings.class); + walletKeyService = Mockito.mock(WalletKeyService.class); + holdersCredentialRepository = Mockito.mock(HoldersCredentialRepository.class); + commonService = Mockito.mock(CommonService.class); + issuersCredentialRepository = mock(IssuersCredentialRepository.class); + + Connection connection = mock(Connection.class); + + DataSource dataSource = mock(DataSource.class); + when(dataSource.getConnection()).thenReturn(connection); + + issuersCredentialService = new IssuersCredentialService( + issuersCredentialRepository, + miwSettings, + new SpecificationUtil(), + walletKeyService, + holdersCredentialRepository, + commonService, + objectMapper + ); + } + + @BeforeEach + public void beforeEach() { + Mockito.reset( + miwSettings, + walletKeyService, + holdersCredentialRepository, + commonService, + issuersCredentialRepository); + } + + @Nested + class issueMembershipCredentialTest { + + @Test + void shouldIssueCredentialAsJwt() + throws IOException, 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); + + IssueMembershipCredentialRequest issueMembershipCredentialRequest = new IssueMembershipCredentialRequest(); + issueMembershipCredentialRequest.setBpn(holderWalletBpn); + + WalletKey walletKey = mock(WalletKey.class); + when(walletKey.getKeyId()).thenReturn(KEY_ID); + when(walletKey.getId()).thenReturn(42L); + + when(walletKeyService.getPrivateKeyByWalletId(baseWallet.getId())) + .thenReturn(new x25519PrivateKey(keyPair.getPrivateKey().asStringForStoring(), true)); + when(walletKeyService.getWalletKeyIdByWalletId(baseWallet.getId())).thenReturn(walletKeyId); + + 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 IOException, InvalidPrivateKeyFormatException, ParseException, 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); + + + when(holdersCredentialRepository.getByHolderDidAndIssuerDidAndTypeAndStored( + any(String.class), + any(String.class), + eq(MIWVerifiableCredentialType.SUMMARY_CREDENTIAL), + eq(false) + )).thenReturn(Collections.emptyList()); + + IssueFrameworkCredentialRequest request = TestUtils.getIssueFrameworkCredentialRequest( + holderWalletBpn, + "SustainabilityCredential"); + WalletKey walletKey = mock(WalletKey.class); + when(walletKey.getKeyId()).thenReturn(KEY_ID); + when(walletKey.getId()).thenReturn(42L); + + when(walletKeyService.getPrivateKeyByWalletId(baseWallet.getId())) + .thenReturn(new x25519PrivateKey(keyPair.getPrivateKey().asStringForStoring(), true)); + when(walletKeyService.getWalletKeyIdByWalletId(baseWallet.getId())).thenReturn(walletKeyId); + + 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 IOException, InvalidPrivateKeyFormatException, ParseException, + 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); + + IssueDismantlerCredentialRequest request = new IssueDismantlerCredentialRequest(); + request.setActivityType("dunno"); + request.setBpn(holderWalletBpn); + request.setAllowedVehicleBrands(Collections.emptySet()); + + WalletKey walletKey = mock(WalletKey.class); + when(walletKey.getKeyId()).thenReturn(KEY_ID); + when(walletKey.getId()).thenReturn(42L); + + when(walletKeyService.getPrivateKeyByWalletId(baseWallet.getId())) + .thenReturn(new x25519PrivateKey(keyPair.getPrivateKey().asStringForStoring(), true)); + when(walletKeyService.getWalletKeyIdByWalletId(baseWallet.getId())).thenReturn(walletKeyId); + + 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 { + + @Test + void shouldIssueCredentialAsJwt() throws IOException, ParseException, InvalidPrivateKeyFormatException, + KeyTransformationException, JwtException { + Map wallets = mockBaseAndHolderWallet(); + Wallet baseWallet = (Wallet) wallets.get("base"); + String baseWalletBpn = baseWallet.getBpn(); + String baseWalletDid = baseWallet.getDid(); + Wallet holderWallet = (Wallet) wallets.get("holder"); + String holderWalletBpn = holderWallet.getBpn(); + String walletKeyId = "key-1"; + + KeyPair keyPair = MockUtil.generateEDKeys(); + VerifiableCredential verifiableCredential = MockUtil.getCredentialBuilder( + List.of("TypeA,TypeB"), + List.of(MockUtil.mockCredentialSubject(), MockUtil.mockCredentialSubject2()), + Instant.now().plus(Duration.ofDays(5)), + MockUtil.generateDid("basewallet")).build(); + + MockUtil.makeCreateWorkForIssuer(issuersCredentialRepository); + when(walletKeyService.getPrivateKeyByWalletIdAsBytes(any(Long.class))).thenReturn(keyPair.getPrivateKey() + .asByte()); + when(commonService.getWalletByIdentifier(holderWalletBpn)).thenReturn(holderWallet); + when(commonService.getWalletByIdentifier(verifiableCredential.getIssuer() + .toString())).thenReturn(baseWallet); + when(miwSettings.authorityWalletBpn()).thenReturn(baseWalletBpn); + when(holdersCredentialRepository.save(any(HoldersCredential.class))) + .thenAnswer(new Answer() { + @Override + public HoldersCredential answer(InvocationOnMock invocation) throws Throwable { + HoldersCredential argument = invocation.getArgument(0, HoldersCredential.class); + argument.setId(42L); + return argument; + } + }); + + WalletKey walletKey = mock(WalletKey.class); + when(walletKey.getKeyId()).thenReturn(KEY_ID); + when(walletKey.getId()).thenReturn(42L); + when(walletKeyService.getPrivateKeyByWalletId(baseWallet.getId())) + .thenReturn(new x25519PrivateKey(keyPair.getPrivateKey().asStringForStoring(), true)); + when(walletKeyService.getWalletKeyIdByWalletId(baseWallet.getId())).thenReturn(walletKeyId); + + CredentialsResponse credentialsResponse = assertDoesNotThrow( + () -> issuersCredentialService.issueCredentialUsingBaseWallet( + holderWalletBpn, + verifiableCredential, + true, + baseWalletBpn)); + + validateCredentialResponse(credentialsResponse, MockUtil.buildDidDocument(new Did(new DidMethod("web"), + new DidMethodIdentifier("basewallet"), + null), keyPair)); + } + } + + @Nested + class jwtValidationTest { + + @RegisterExtension + static WireMockExtension issuer = WireMockExtension.newInstance() + .options(wireMockConfig() + .dynamicPort() + // .notifier(new ConsoleNotifier(true)) + ) + .build(); + + @Test + void shouldValidateAsJWT() throws DidParseException { + Map wallets = mockBaseAndHolderWallet("localhost%3A" + issuer.getPort()); + Wallet baseWallet = (Wallet) wallets.get("base"); + String baseWalletDid = baseWallet.getDid(); + + DidDocument issuerDidDocument = MockUtil.buildDidDocument( + DidParser.parse(baseWalletDid), + (KeyPair) wallets.get("baseKeys")); + issuer.stubFor( + get("/.well-known/did.json").willReturn(ok(issuerDidDocument.toPrettyJson()))); + + Wallet holderWallet = (Wallet) wallets.get("holder"); + String holderWalletDid = holderWallet.getDid(); + + VerifiableCredential verifiableCredential = MockUtil.getCredentialBuilder( + List.of("TypeA,TypeB"), + List.of(MockUtil.mockCredentialSubject(), MockUtil.mockCredentialSubject2()), + Instant.now().plus(Duration.ofDays(5)), + MockUtil.generateDid("basewallet")).build(); + + SerializedJwtVCFactoryImpl vcFactory = new SerializedJwtVCFactoryImpl( + new SignedJwtFactory(new OctetKeyPairFactory())); + + SignedJWT vcJWT = vcFactory.createVCJwt(DidParser.parse(baseWalletDid), DidParser.parse(holderWalletDid), + verifiableCredential, + ((KeyPair) wallets.get("baseKeys")).getPrivateKey(), + "key-1"); + + String serialized = vcJWT.serialize(); + + CredentialVerificationRequest credentialVerificationRequest = new CredentialVerificationRequest(); + credentialVerificationRequest.setJwt(serialized); + + Map stringObjectMap = assertDoesNotThrow( + () -> issuersCredentialService.credentialsValidation(credentialVerificationRequest, true)); + assertTrue((Boolean) stringObjectMap.get(StringPool.VALID)); + } + } + + private Map mockBaseAndHolderWallet() { + KeyPair baseKeys = MockUtil.generateEDKeys(); + KeyPair holderKeys = MockUtil.generateEDKeys(); + String baseWalletBpn = TestUtils.getRandomBpmNumber(); + + Wallet baseWallet = MockUtil.mockWallet( + baseWalletBpn, + MockUtil.generateDid("basewallet"), + baseKeys); + String holderWalletBpn = TestUtils.getRandomBpmNumber(); + Wallet holderWallet = MockUtil.mockWallet( + holderWalletBpn, + MockUtil.generateDid("holderwallet"), + holderKeys); + + return Map.of("base", baseWallet, "holder", holderWallet, "baseKeys", baseKeys, "holderKeys", holderKeys); + } + + private Map mockBaseAndHolderWallet(String baseHost) { + KeyPair baseKeys = MockUtil.generateEDKeys(); + KeyPair holderKeys = MockUtil.generateEDKeys(); + String baseWalletBpn = TestUtils.getRandomBpmNumber(); + + Wallet baseWallet = MockUtil.mockWallet( + baseWalletBpn, + MockUtil.generateDid(baseHost), + baseKeys); + String holderWalletBpn = TestUtils.getRandomBpmNumber(); + Wallet holderWallet = MockUtil.mockWallet( + holderWalletBpn, + MockUtil.generateDid("holderwallet"), + holderKeys); + + return Map.of("base", baseWallet, "holder", holderWallet, "baseKeys", baseKeys, "holderKeys", holderKeys); + } + + private void mockCommon( + String baseWalletBpn, + String holderWalletBpn, + KeyPair keyPair, + Wallet baseWallet, + Wallet holderWallet) { + when(miwSettings.contractTemplatesUrl()).thenReturn("https://templates.com"); + when(miwSettings.authorityWalletBpn()).thenReturn(baseWalletBpn); + when(commonService.getWalletByIdentifier(baseWalletBpn)).thenReturn(baseWallet); + when(commonService.getWalletByIdentifier(holderWalletBpn)).thenReturn(holderWallet); + when(walletKeyService.getPrivateKeyByWalletIdAsBytes(baseWallet.getId())) + .thenReturn(keyPair.getPrivateKey().asByte()); + when(miwSettings.supportedFrameworkVCTypes()).thenReturn(Set.of("SustainabilityCredential")); + when(holdersCredentialRepository.save(any(HoldersCredential.class))) + .thenAnswer(new Answer() { + @Override + public HoldersCredential answer(InvocationOnMock invocation) throws Throwable { + HoldersCredential argument = invocation.getArgument(0, HoldersCredential.class); + argument.setId(42L); + return argument; + } + }); + } + + @SneakyThrows + private void validateCredentialResponse(CredentialsResponse credentialsResponse, DidDocument didDocument) { + assertTrue(credentialsResponse.containsKey("jwt")); + JWSObject parsed = JWSObject.parse((String) credentialsResponse.get("jwt")); + assertEquals("did:web:basewallet#" + KEY_ID, parsed.getHeader().getKeyID()); + assertEquals("JWT", parsed.getHeader().getType().getType()); + assertEquals("EdDSA", parsed.getHeader().getAlgorithm().getName()); + + Map payload = parsed.getPayload().toJSONObject(); + assertTrue(payload.containsKey("vc")); + + SignedJwtVerifier jwtVerifier = new SignedJwtVerifier(new DidResolver() { + @Override + public DidDocument resolve(Did did) throws DidResolverException { + return didDocument; + } + + @Override + public boolean isResolvable(Did did) { + return false; + } + }); + + SignedJWT signedJwt = SignedJWT.parse((String) credentialsResponse.get("jwt")); + assertTrue(jwtVerifier.verify(signedJwt)); + } +} diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/MockUtil.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/MockUtil.java new file mode 100644 index 000000000..e60072e81 --- /dev/null +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/MockUtil.java @@ -0,0 +1,305 @@ +/* + * ******************************************************************************* + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + * ****************************************************************************** + */ + package org.eclipse.tractusx.managedidentitywallets.utils; + +import com.nimbusds.jose.util.JSONObjectUtils; + +import lombok.SneakyThrows; + +import org.eclipse.tractusx.managedidentitywallets.dao.entity.HoldersCredential; +import org.eclipse.tractusx.managedidentitywallets.dao.entity.IssuersCredential; +import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; +import org.eclipse.tractusx.managedidentitywallets.dao.repository.HoldersCredentialRepository; +import org.eclipse.tractusx.managedidentitywallets.dao.repository.IssuersCredentialRepository; +import org.eclipse.tractusx.ssi.lib.crypt.IPublicKey; +import org.eclipse.tractusx.ssi.lib.crypt.KeyPair; +import org.eclipse.tractusx.ssi.lib.crypt.x25519.x25519Generator; +import org.eclipse.tractusx.ssi.lib.exception.key.InvalidPrivateKeyFormatException; +import org.eclipse.tractusx.ssi.lib.exception.key.KeyGenerationException; +import org.eclipse.tractusx.ssi.lib.exception.proof.UnsupportedSignatureTypeException; +import org.eclipse.tractusx.ssi.lib.model.MultibaseString; +import org.eclipse.tractusx.ssi.lib.model.base.MultibaseFactory; +import org.eclipse.tractusx.ssi.lib.model.did.*; +import org.eclipse.tractusx.ssi.lib.model.proof.Proof; +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredentialBuilder; +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredentialSubject; +import org.eclipse.tractusx.ssi.lib.proof.LinkedDataProofGenerator; +import org.eclipse.tractusx.ssi.lib.proof.SignatureType; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.jpa.domain.Specification; +import org.testcontainers.shaded.com.fasterxml.jackson.core.JsonProcessingException; +import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.text.ParseException; +import java.time.Duration; +import java.time.Instant; +import java.util.*; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class MockUtil { + + public static VerifiableCredential mockCredential( + List types, + List credentialSubjects, + KeyPair keyPair, + String host, + Instant expirationDate + ) { + return mockCredential(types, credentialSubjects, keyPair, host, expirationDate, false); + } + + @SneakyThrows + public static VerifiableCredential mockCredential( + List types, + List credentialSubjects, + KeyPair keyPair, + String host, + Instant expirationDate, + boolean jws + ) { + Did issuer = new Did(new DidMethod("web"), new DidMethodIdentifier(host), null); + VerifiableCredentialBuilder builder = MockUtil.getCredentialBuilder( + types, + credentialSubjects, + expirationDate, + issuer + ); + + // Ed25519 Proof Builder + LinkedDataProofGenerator generator; + try { + generator = LinkedDataProofGenerator.newInstance(jws ? SignatureType.JWS : SignatureType.ED25519); + } catch (UnsupportedSignatureTypeException e) { + throw new AssertionError(e); + } + + Proof proof; + try { + proof = + generator.createProof(builder.build(), URI.create(issuer + "#key-1"), keyPair.getPrivateKey()); + } catch (InvalidPrivateKeyFormatException e) { + throw new AssertionError(e); + } + + // Adding Proof to VC + builder.proof(proof); + + return builder.build(); + } + + public static VerifiableCredentialBuilder getCredentialBuilder( + List types, + List credentialSubjects, + Instant expirationDate, + Did issuer + ) { + + VerifiableCredentialBuilder builder = + new VerifiableCredentialBuilder() + .context(List.of( + URI.create("https://www.w3.org/2018/credentials/v1"), + URI.create("https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json"), + URI.create("https://w3id.org/security/suites/jws-2020/v1"), + URI.create("https://catenax-ng.github.io/product-core-schemas/SummaryVC.json"), + URI.create("https://w3id.org/security/suites/ed25519-2020/v1"), + URI.create("https://w3id.org/vc/status-list/2021/v1") + ) + ) + .id(URI.create(issuer + "#key-1")) + .issuer(issuer.toUri()) + .issuanceDate(Instant.now().minus(Duration.ofDays(5))) + .credentialSubject(credentialSubjects) + .expirationDate(expirationDate) + .type(types); + + try { + System.out.println(new ObjectMapper().writeValueAsString(builder.build())); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + + return builder; + } + + public static Did generateDid(String host) { + return new Did( + new DidMethod("web"), + new DidMethodIdentifier(host), + null + ); + } + + @SneakyThrows + public static DidDocument buildDidDocument(Did did, KeyPair keyPair) { + IPublicKey publicKey = keyPair.getPublicKey(); + MultibaseString publicKeyBase = MultibaseFactory.create(publicKey.asByte()); + + // Building Verification Methods: + List verificationMethods = new ArrayList<>(); + Ed25519VerificationMethodBuilder builder = new Ed25519VerificationMethodBuilder(); + Ed25519VerificationMethod key = + builder + .id(URI.create(did.toUri() + "#key-" + 1)) + .controller(did.toUri()) + .publicKeyMultiBase(publicKeyBase) + .build(); + verificationMethods.add(key); + DidDocumentBuilder didDocumentBuilder = new DidDocumentBuilder(); + didDocumentBuilder.id(did.toUri()); + didDocumentBuilder.verificationMethods(verificationMethods); + + return didDocumentBuilder.build(); + } + + public static Wallet mockWallet(String bpn, Did did, KeyPair keyPair) { + Wallet wallet = mock(Wallet.class); + when(wallet.getId()).thenReturn(new Random().nextLong()); + when(wallet.getName()).thenReturn("WalletName"); + when(wallet.getBpn()).thenReturn(bpn); + when(wallet.getDid()).thenReturn(did.toUri().toString()); + when(wallet.getDidDocument()).thenReturn(buildDidDocument(did, keyPair)); + when(wallet.getAlgorithm()).thenReturn("Ed25519"); + when(wallet.getCreatedAt()).thenReturn(new Date()); + when(wallet.getModifiedAt()).thenReturn(new Date()); + when(wallet.getModifiedFrom()).thenReturn(null); + return wallet; + } + + public static void makeFilterWorkForHolder(HoldersCredentialRepository holdersCredentialRepository) { + KeyPair keyPair = generateEDKeys(); + VerifiableCredential verifiableCredential = mockCredential( + List.of("VerifiableCredential", "SummaryCredential"), + List.of(mockCredentialSubject()), + keyPair, + "localhost", + Instant.now().plus(Duration.ofDays(5)) + ); + HoldersCredential holdersCredential = mockHolderCredential(verifiableCredential); + //getRepository().findAll(specification, pageRequest); + when(holdersCredentialRepository.findAll(any(Specification.class), any(PageRequest.class))).thenReturn( + new PageImpl<>(List.of(holdersCredential)) + ); + } + + public static void makeFilterWorkForIssuer(IssuersCredentialRepository holdersCredentialRepository) { + KeyPair keyPair = generateEDKeys(); + VerifiableCredential verifiableCredential = mockCredential( + List.of("VerifiableCredential", "SummaryCredential"), + List.of(mockCredentialSubject()), + keyPair, + "localhost", + Instant.now().plus(Duration.ofDays(5)) + ); + IssuersCredential holdersCredential = mockIssuerCredential(verifiableCredential); + //getRepository().findAll(specification, pageRequest); + when(holdersCredentialRepository.findAll(any(Specification.class), any(PageRequest.class))).thenReturn( + new PageImpl<>(List.of(holdersCredential)) + ); + } + + public static void makeCreateWorkForHolder(HoldersCredentialRepository holdersCredentialRepository) { + when(holdersCredentialRepository.save(any(HoldersCredential.class))) + .thenAnswer(new Answer() { + @Override + public HoldersCredential answer(InvocationOnMock invocation) throws Throwable { + HoldersCredential argument = invocation.getArgument(0, HoldersCredential.class); + argument.setId(42L); + return argument; + } + } + ); + } + + public static void makeCreateWorkForIssuer(IssuersCredentialRepository issuersCredentialRepository) { + when(issuersCredentialRepository.save(any(IssuersCredential.class))) + .thenAnswer(new Answer() { + @Override + public IssuersCredential answer(InvocationOnMock invocation) throws Throwable { + IssuersCredential argument = invocation.getArgument(0, IssuersCredential.class); + argument.setId(42L); + return argument; + } + } + ); + } + + public static KeyPair generateEDKeys() { + x25519Generator gen = new x25519Generator(); + KeyPair baseWalletKeys; + try { + baseWalletKeys = gen.generateKey(); + } catch (KeyGenerationException e) { + throw new AssertionError(e); + } + return baseWalletKeys; + } + + public static HoldersCredential mockHolderCredential(VerifiableCredential verifiableCredential) { + + + HoldersCredential cred = mock(HoldersCredential.class); + when(cred.getCredentialId()).thenReturn("credentialId"); + when(cred.getData()).thenReturn(verifiableCredential); + return cred; + } + + public static IssuersCredential mockIssuerCredential(VerifiableCredential verifiableCredential) { + IssuersCredential cred = mock(IssuersCredential.class); + when(cred.getCredentialId()).thenReturn("credentialId"); + when(cred.getData()).thenReturn(verifiableCredential); + return cred; + } + + public static VerifiableCredentialSubject mockCredentialSubject() { + Map subj; + try (InputStream in = MockUtil.class.getResourceAsStream("/credential-subject.json")) { + subj = JSONObjectUtils.parse(new String(in.readAllBytes(), StandardCharsets.UTF_8)); + } catch (IOException | ParseException e) { + throw new RuntimeException(e); + } + + + return new VerifiableCredentialSubject(subj); + } + + public static VerifiableCredentialSubject mockCredentialSubject2() { + Map subj; + try (InputStream in = MockUtil.class.getResourceAsStream("/credential-subject-2.json")) { + subj = JSONObjectUtils.parse(new String(in.readAllBytes(), StandardCharsets.UTF_8)); + } catch (IOException | ParseException e) { + throw new RuntimeException(e); + } + + + return new VerifiableCredentialSubject(subj); + } +} diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/VerifiableCredentialIssuerEqualProofSignerTest.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/VerifiableCredentialIssuerEqualProofSignerTest.java index 55fba9d3f..eb6e3912e 100644 --- a/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/VerifiableCredentialIssuerEqualProofSignerTest.java +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/VerifiableCredentialIssuerEqualProofSignerTest.java @@ -107,7 +107,7 @@ private VerifiableCredential issueVC(String issuerDid, Wallet signerWallet) thro LinkedDataProofGenerator generator = LinkedDataProofGenerator.newInstance(SignatureType.JWS); URI verificationMethod = signerWallet.getDidDocument().getVerificationMethods().get(0).getId(); - byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdentifierAsBytes(signerWallet.getId()); + byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdAsBytes(signerWallet.getId()); JWSSignature2020 proof = (JWSSignature2020) generator.createProof(builder.build(), verificationMethod, new x25519PrivateKey(privateKeyBytes)); diff --git a/src/test/resources/credential-subject-2.json b/src/test/resources/credential-subject-2.json new file mode 100644 index 000000000..6b191fdaa --- /dev/null +++ b/src/test/resources/credential-subject-2.json @@ -0,0 +1,18 @@ +{ + "id": "https://localhost/.well-known/participant.json", + "type": "gx:DummyParticipant", + "gx:legalName": "Sample Company", + "gx:legalRegistrationNumber": + { + "gx:taxID": "113123123" + }, + "gx:headquarterAddress": + { + "gx:countrySubdivisionCode": "BE-BRU" + }, + "gx:legalAddress": + { + "gx:countrySubdivisionCode": "BE-BRU" + }, + "gx-terms-and-conditions:gaiaxTermsAndConditions": "70c1d713215f95191a11d38fe2341faed27d19e083917bc8732ca4fea4976700" +} \ No newline at end of file diff --git a/src/test/resources/credential-subject.json b/src/test/resources/credential-subject.json new file mode 100644 index 000000000..d0327d670 --- /dev/null +++ b/src/test/resources/credential-subject.json @@ -0,0 +1,18 @@ +{ + "id": "https://localhost/.well-known/participant.json", + "type": "gx:LegalParticipant", + "gx:legalName": "Sample Company", + "gx:legalRegistrationNumber": + { + "gx:taxID": "113123123" + }, + "gx:headquarterAddress": + { + "gx:countrySubdivisionCode": "BE-BRU" + }, + "gx:legalAddress": + { + "gx:countrySubdivisionCode": "BE-BRU" + }, + "gx-terms-and-conditions:gaiaxTermsAndConditions": "70c1d713215f95191a11d38fe2341faed27d19e083917bc8732ca4fea4976700" +}