Skip to content

Commit

Permalink
fix: VP validation tests
Browse files Browse the repository at this point in the history
  • Loading branch information
nitin-vavdiya committed Jun 12, 2024
1 parent 1430881 commit 09d337f
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 194 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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(
Expand All @@ -155,174 +158,6 @@ public void beforeEach() {
issuersCredentialRepository);
}

@Nested
class issueMembershipCredentialTest {

@Test
void shouldIssueCredentialAsJwt()
throws InvalidPrivateKeyFormatException, KeyTransformationException {
Map<String, Object> 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<SigningServiceType, SigningService> 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<String, Object> 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<SigningServiceType, SigningService> 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<String, Object> 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<SigningServiceType, SigningService> 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 {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -227,14 +226,25 @@ 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<String, Object> map = getCredentialAsMap(issuerDid, type, miwSettings, objectMapper);
HttpEntity<Map> entity = new HttpEntity<>(map, headers);
ResponseEntity<String> 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<String, Object> getCredentialAsMap(String issuerDid, String type, MIWSettings miwSettings, ObjectMapper objectMapper) throws JsonProcessingException {
// Create VC without proof
//VC Builder
VerifiableCredentialBuilder verifiableCredentialBuilder =
new VerifiableCredentialBuilder();

//VC Subject
VerifiableCredentialSubject verifiableCredentialSubject =
new VerifiableCredentialSubject(Map.of("test", "test"));
new VerifiableCredentialSubject(Map.of("id", "test"));

//Using Builder
VerifiableCredential credentialWithoutProof =
Expand All @@ -248,13 +258,6 @@ public static VerifiableCredential issueCustomVCUsingBaseWallet(String holderDid
.credentialSubject(verifiableCredentialSubject)
.build();

Map<String, Objects> map = objectMapper.readValue(credentialWithoutProof.toJson(), Map.class);
HttpEntity<Map> entity = new HttpEntity<>(map, headers);
ResponseEntity<String> 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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -116,26 +118,29 @@ 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<String, Object> 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<String, Object> 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<String, Object> presentation = createPresentationJwt(membershipCredential_1, tenant_1);
Map<String, Object> presentation = createPresentationJwt(vc_1, tenant_1);
VerifiablePresentationValidationResponse response = validateJwtOfCredential(presentation);
Assertions.assertTrue(response.valid);
}

@Test
@SneakyThrows
public void testSuccessfulValidationForMultipleVC() {
Map<String, Object> creationResponse = createPresentationJwt(List.of(membershipCredential_1, membershipCredential_2), tenant_1);
Map<String, Object> 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<String, Object> decodedJwtPayload = OBJECT_MAPPER.readValue(Base64.getUrlDecoder().decode(encodedJwtPayload), Map.class);
Expand All @@ -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<String, Object> presentation = createPresentationJwt(copyCredential, tenant_1);
Expand All @@ -164,18 +169,18 @@ 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<String, Object> presentation = createPresentationJwt(List.of(membershipCredential_1, copyCredential), tenant_1);
Map<String, Object> presentation = createPresentationJwt(List.of(vc_1, copyCredential), tenant_1);
VerifiablePresentationValidationResponse response = validateJwtOfCredential(presentation);
Assertions.assertFalse(response.valid);
}

@Test
@SneakyThrows
void testValidationFailureOfPresentationPayloadManipulation() {
Map<String, Object> presentation = createPresentationJwt(membershipCredential_1, tenant_1);
Map<String, Object> presentation = createPresentationJwt(vc_1, tenant_1);

String jwt = (String) presentation.get(StringPool.VP);
String payload = jwt.split("\\.")[1];
Expand All @@ -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);
Expand Down

0 comments on commit 09d337f

Please sign in to comment.