Skip to content

Commit

Permalink
Merge pull request eclipse-tractusx#31 from catenax-ng/features/java-…
Browse files Browse the repository at this point in the history
…did-web-update-jwt-vp-signer-identity

update vp-jwt subject
  • Loading branch information
mknoopvw authored Jun 22, 2023
2 parents 36e90df + 5ec7a82 commit 6463c3e
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 104 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ dependencies {
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:${openApiVersion}"
implementation group: 'com.smartsensesolutions', name: 'commons-dao', version: '0.0.5'
implementation 'org.liquibase:liquibase-core'
implementation 'org.eclipse.tractusx.ssi:cx-ssi-lib:0.0.6'
implementation 'org.eclipse.tractusx.ssi:cx-ssi-lib:0.0.7'
runtimeOnly 'org.postgresql:postgresql'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@
import org.eclipse.tractusx.ssi.lib.model.did.DidDocument;
import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential;

import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.List;

/**
Expand Down Expand Up @@ -66,16 +64,6 @@ public class Wallet extends MIWBaseEntity {
@Convert(converter = StringToDidDocumentConverter.class)
private DidDocument didDocument;


@Transient
private List<VerifiableCredential> verifiableCredentials;

/**
* Sets did.
*
* @param did the did
*/
public void setDid(String did) {
this.did = URLDecoder.decode(did, Charset.defaultCharset());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.eclipse.tractusx.managedidentitywallets.exception.WalletNotFoundProblem;
import org.eclipse.tractusx.managedidentitywallets.utils.CommonUtils;
import org.eclipse.tractusx.managedidentitywallets.utils.Validate;
import org.eclipse.tractusx.ssi.lib.exception.DidParseException;
import org.springframework.stereotype.Service;

@Service
Expand All @@ -49,7 +50,12 @@ public Wallet getWalletByIdentifier(String identifier) {
if (CommonUtils.getIdentifierType(identifier).equals(StringPool.BPN)) {
wallet = walletRepository.getByBpn(identifier);
} else {
wallet = walletRepository.getByDid(identifier);
try {
wallet = walletRepository.getByDid(identifier);
} catch (DidParseException e) {
log.error("Error while parsing did {}", identifier, e);
throw new WalletNotFoundProblem("Error while parsing did " + identifier);
}
}
Validate.isNull(wallet).launch(new WalletNotFoundProblem("Wallet not found for identifier " + identifier));
return wallet;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ public PageImpl<VerifiableCredential> getCredentials(String credentialId, String

//Holder must be caller of API
Wallet holderWallet = commonService.getWalletByIdentifier(callerBPN);
filterRequest.appendCriteria(StringPool.HOLDER_DID, Operator.EQUALS, holderWallet.getDid());
filterRequest.appendCriteria(StringPool.HOLDER_DID, Operator.EQUALS, holderWallet.getDid().toString());

if (StringUtils.hasText(issuerIdentifier)) {
Wallet issuerWallet = commonService.getWalletByIdentifier(issuerIdentifier);
filterRequest.appendCriteria(StringPool.ISSUER_DID, Operator.EQUALS, issuerWallet.getDid());
filterRequest.appendCriteria(StringPool.ISSUER_DID, Operator.EQUALS, issuerWallet.getDid().toString());
}

if (StringUtils.hasText(credentialId)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,16 @@
import org.eclipse.tractusx.managedidentitywallets.exception.ForbiddenException;
import org.eclipse.tractusx.managedidentitywallets.utils.CommonUtils;
import org.eclipse.tractusx.managedidentitywallets.utils.Validate;
import org.eclipse.tractusx.ssi.lib.did.resolver.DidDocumentResolverRegistry;
import org.eclipse.tractusx.ssi.lib.did.resolver.DidDocumentResolverRegistryImpl;
import org.eclipse.tractusx.ssi.lib.did.web.DidWebDocumentResolver;
import org.eclipse.tractusx.ssi.lib.did.web.util.DidWebParser;
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.resolver.DidDocumentResolverRegistry;
import org.eclipse.tractusx.ssi.lib.resolver.DidDocumentResolverRegistryImpl;
import org.eclipse.tractusx.ssi.lib.proof.SignatureType;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -187,9 +188,11 @@ public PageImpl<VerifiableCredential> getCredentials(String credentialId, String
public VerifiableCredential issueBpnCredential(Wallet baseWallet, Wallet holderWallet, boolean authority) {
byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdentifierAsBytes(baseWallet.getId());
List<String> types = List.of(VerifiableCredentialType.VERIFIABLE_CREDENTIAL, MIWVerifiableCredentialType.BPN_CREDENTIAL);
HoldersCredential holdersCredential = CommonUtils.getHoldersCredential(Map.of(StringPool.TYPE, MIWVerifiableCredentialType.BPN_CREDENTIAL,
VerifiableCredentialSubject verifiableCredentialSubject = new VerifiableCredentialSubject(Map.of(StringPool.TYPE, MIWVerifiableCredentialType.BPN_CREDENTIAL,
StringPool.ID, holderWallet.getDid(),
StringPool.BPN, holderWallet.getBpn()), types, baseWallet.getDidDocument(), privateKeyBytes, holderWallet.getDid(), miwSettings.vcContexts(), miwSettings.vcExpiryDate(), authority);
StringPool.BPN, holderWallet.getBpn()));
HoldersCredential holdersCredential = CommonUtils.getHoldersCredential(verifiableCredentialSubject,
types, baseWallet.getDidDocument(), privateKeyBytes, holderWallet.getDid(), miwSettings.vcContexts(), miwSettings.vcExpiryDate(), authority);

//Store Credential in holder wallet
holdersCredential = holdersCredentialRepository.save(holdersCredential);
Expand Down Expand Up @@ -231,12 +234,12 @@ public VerifiableCredential issueFrameworkCredential(IssueFrameworkCredentialReq
//if base wallet issue credentials to itself
boolean isSelfIssued = isSelfIssued(holderWallet.getBpn());

Map<String, Object> subject = Map.of(
VerifiableCredentialSubject subject = new VerifiableCredentialSubject(Map.of(
StringPool.TYPE, request.getType(),
StringPool.ID, holderWallet.getDid(),
StringPool.HOLDER_IDENTIFIER, holderWallet.getBpn(),
StringPool.CONTRACT_TEMPLATE, request.getContractTemplate(),
StringPool.CONTRACT_VERSION, request.getContractVersion());
StringPool.CONTRACT_VERSION, request.getContractVersion()));
List<String> types = List.of(VerifiableCredentialType.VERIFIABLE_CREDENTIAL, MIWVerifiableCredentialType.USE_CASE_FRAMEWORK_CONDITION);
HoldersCredential holdersCredential = CommonUtils.getHoldersCredential(subject, types, baseWallet.getDidDocument(), privateKeyBytes, holderWallet.getDid(), miwSettings.vcContexts(), miwSettings.vcExpiryDate(), isSelfIssued);

Expand Down Expand Up @@ -282,11 +285,11 @@ public VerifiableCredential issueDismantlerCredential(IssueDismantlerCredentialR
//if base wallet issue credentials to itself
boolean isSelfIssued = isSelfIssued(request.getBpn());

Map<String, Object> subject = Map.of(StringPool.TYPE, MIWVerifiableCredentialType.DISMANTLER_CREDENTIAL,
VerifiableCredentialSubject subject = new VerifiableCredentialSubject(Map.of(StringPool.TYPE, MIWVerifiableCredentialType.DISMANTLER_CREDENTIAL,
StringPool.ID, holderWallet.getDid(),
StringPool.HOLDER_IDENTIFIER, holderWallet.getBpn(),
StringPool.ACTIVITY_TYPE, request.getActivityType(),
StringPool.ALLOWED_VEHICLE_BRANDS, request.getAllowedVehicleBrands());
StringPool.ALLOWED_VEHICLE_BRANDS, request.getAllowedVehicleBrands()));
List<String> types = List.of(VerifiableCredentialType.VERIFIABLE_CREDENTIAL, MIWVerifiableCredentialType.DISMANTLER_CREDENTIAL);
HoldersCredential holdersCredential = CommonUtils.getHoldersCredential(subject, types, issuerWallet.getDidDocument(), privateKeyBytes, holderWallet.getDid(), miwSettings.vcContexts(), miwSettings.vcExpiryDate(), isSelfIssued);

Expand Down Expand Up @@ -335,12 +338,13 @@ public VerifiableCredential issueMembershipCredential(IssueMembershipCredentialR
boolean isSelfIssued = isSelfIssued(issueMembershipCredentialRequest.getBpn());

//VC Subject
HoldersCredential holdersCredential = CommonUtils.getHoldersCredential(Map.of(StringPool.TYPE, VerifiableCredentialType.MEMBERSHIP_CREDENTIAL,
VerifiableCredentialSubject verifiableCredentialSubject = new VerifiableCredentialSubject(Map.of(StringPool.TYPE, VerifiableCredentialType.MEMBERSHIP_CREDENTIAL,
StringPool.ID, holderWallet.getDid(),
StringPool.HOLDER_IDENTIFIER, holderWallet.getBpn(),
StringPool.MEMBER_OF, issuerWallet.getName(),
StringPool.STATUS, "Active",
StringPool.START_TIME, Instant.now().toString()), types, issuerWallet.getDidDocument(), privateKeyBytes, holderWallet.getDid(), miwSettings.vcContexts(), miwSettings.vcExpiryDate(), isSelfIssued);
StringPool.START_TIME, Instant.now().toString()));
HoldersCredential holdersCredential = CommonUtils.getHoldersCredential(verifiableCredentialSubject, types, issuerWallet.getDidDocument(), privateKeyBytes, holderWallet.getDid(), miwSettings.vcContexts(), miwSettings.vcExpiryDate(), isSelfIssued);


//save in holder wallet
Expand Down Expand Up @@ -423,8 +427,21 @@ public Map<String, Object> credentialsValidation(Map<String, Object> data) {
didDocumentResolverRegistry.register(
new DidWebDocumentResolver(HttpClient.newHttpClient(), new DidWebParser(), miwSettings.enforceHttps()));

LinkedDataProofValidation proofValidation = LinkedDataProofValidation.newInstance(didDocumentResolverRegistry);
Boolean valid = proofValidation.checkProof(verifiableCredential);
String proofTye = verifiableCredential.getProof().get(StringPool.TYPE).toString();
LinkedDataProofValidation proofValidation;
if (SignatureType.ED21559.toString().equals(proofTye)) {
proofValidation = LinkedDataProofValidation.newInstance(
SignatureType.ED21559,
didDocumentResolverRegistry);
} else if (SignatureType.JWS.toString().equals(proofTye)) {
proofValidation = LinkedDataProofValidation.newInstance(
SignatureType.JWS,
didDocumentResolverRegistry);
} else {
throw new BadDataException(String.format("Invalid proof type: %s", proofTye));
}

Boolean valid = proofValidation.verifiyProof(verifiableCredential);
Map<String, Object> response = new HashMap<>();
response.put(StringPool.VALID, valid);
response.put("vc", verifiableCredential);
Expand Down Expand Up @@ -482,6 +499,7 @@ private void updateSummeryCredentials(DidDocument issuerDidDocument, byte[] issu
}
} else {
items = List.of(type);

}
} else {
items = List.of(type);
Expand All @@ -500,11 +518,11 @@ private void updateSummeryCredentials(DidDocument issuerDidDocument, byte[] issu
//issue new summery VC
boolean isSelfIssued = isSelfIssued(holderBpn);

Map<String, Object> subject = Map.of(StringPool.ID, holderDid,
VerifiableCredentialSubject subject = new VerifiableCredentialSubject(Map.of(StringPool.ID, holderDid,
StringPool.HOLDER_IDENTIFIER, holderBpn,
StringPool.ITEMS, items,
StringPool.TYPE, MIWVerifiableCredentialType.SUMMARY_CREDENTIAL,
StringPool.CONTRACT_TEMPLATES, miwSettings.contractTemplatesUrl());
StringPool.CONTRACT_TEMPLATES, miwSettings.contractTemplatesUrl()));

List<String> types = List.of(VerifiableCredentialType.VERIFIABLE_CREDENTIAL, MIWVerifiableCredentialType.SUMMARY_CREDENTIAL);
HoldersCredential holdersCredential = CommonUtils.getHoldersCredential(subject, types,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,14 @@
import org.eclipse.tractusx.managedidentitywallets.exception.BadDataException;
import org.eclipse.tractusx.managedidentitywallets.exception.ForbiddenException;
import org.eclipse.tractusx.managedidentitywallets.utils.Validate;
import org.eclipse.tractusx.ssi.lib.crypt.ed25519.Ed25519Key;
import org.eclipse.tractusx.ssi.lib.crypt.octet.OctetKeyPairFactory;
import org.eclipse.tractusx.ssi.lib.crypt.x21559.x21559PrivateKey;
import org.eclipse.tractusx.ssi.lib.did.resolver.DidDocumentResolverRegistry;
import org.eclipse.tractusx.ssi.lib.did.resolver.DidDocumentResolverRegistryImpl;
import org.eclipse.tractusx.ssi.lib.did.web.DidWebDocumentResolver;
import org.eclipse.tractusx.ssi.lib.did.web.util.DidWebParser;
import org.eclipse.tractusx.ssi.lib.exception.InvalidePrivateKeyFormat;
import org.eclipse.tractusx.ssi.lib.jwt.SignedJwtFactory;
import org.eclipse.tractusx.ssi.lib.jwt.SignedJwtValidator;
import org.eclipse.tractusx.ssi.lib.jwt.SignedJwtVerifier;
Expand All @@ -47,9 +53,6 @@
import org.eclipse.tractusx.ssi.lib.model.verifiable.presentation.VerifiablePresentation;
import org.eclipse.tractusx.ssi.lib.model.verifiable.presentation.VerifiablePresentationBuilder;
import org.eclipse.tractusx.ssi.lib.model.verifiable.presentation.VerifiablePresentationType;
import org.eclipse.tractusx.ssi.lib.resolver.DidDocumentResolverRegistry;
import org.eclipse.tractusx.ssi.lib.resolver.DidDocumentResolverRegistryImpl;
import org.eclipse.tractusx.ssi.lib.resolver.OctetKeyPairFactory;
import org.eclipse.tractusx.ssi.lib.serialization.jsonLd.JsonLdSerializerImpl;
import org.eclipse.tractusx.ssi.lib.serialization.jwt.SerializedJwtPresentationFactory;
import org.eclipse.tractusx.ssi.lib.serialization.jwt.SerializedJwtPresentationFactoryImpl;
Expand Down Expand Up @@ -98,19 +101,18 @@ protected SpecificationUtil<HoldersCredential> getSpecificationUtil() {
* @param callerBpn the caller bpn
* @return the map
*/
@SneakyThrows({InvalidePrivateKeyFormat.class})
public Map<String, Object> createPresentation(Map<String, Object> data, boolean asJwt, String audience, String callerBpn) {
List<Map<String, Object>> verifiableCredentialList = (List<Map<String, Object>>) data.get(StringPool.VERIFIABLE_CREDENTIALS);

//only support one credential at a time to create VP
Validate.isTrue(verifiableCredentialList.size() > 1).launch(new BadDataException("Only one credentials is supported to create presentation"));

String holderIdentifier = data.get(StringPool.HOLDER_IDENTIFIER).toString();

//check if holder wallet is in the system
Wallet holderWallet = commonService.getWalletByIdentifier(holderIdentifier);
Wallet callerWallet = commonService.getWalletByIdentifier(callerBpn);

//validate BPN access - Issuer(Creator) of VP must be caller Issuer of VP must be holder of VC
Validate.isFalse(holderWallet.getBpn().equalsIgnoreCase(callerBpn)).launch(new ForbiddenException("Holder identifier is not matching with request BPN(from the token)"));
Validate.isFalse(callerWallet.getBpn().equalsIgnoreCase(callerBpn)).launch(new ForbiddenException("Holder identifier is not matching with request BPN(from the token)"));

List<VerifiableCredential> verifiableCredentials = new ArrayList<>(verifiableCredentialList.size());
verifiableCredentialList.forEach(map -> {
Expand All @@ -124,15 +126,17 @@ public Map<String, Object> createPresentation(Map<String, Object> data, boolean
Validate.isFalse(StringUtils.hasText(audience)).launch(new BadDataException("Audience needed to create VP as JWT"));

//Issuer of VP is holder of VC
Did vpIssuerDid = DidParser.parse(holderWallet.getDid());
Did vpIssuerDid = DidParser.parse(callerWallet.getDid());

//JWT Factory
SerializedJwtPresentationFactory presentationFactory = new SerializedJwtPresentationFactoryImpl(
new SignedJwtFactory(new OctetKeyPairFactory()), new JsonLdSerializerImpl(), vpIssuerDid);

//Build JWT
Ed25519Key ed25519Key = walletKeyService.getPrivateKeyByWalletIdentifier(callerWallet.getId());
x21559PrivateKey privateKey = new x21559PrivateKey(ed25519Key.getEncoded());
SignedJWT presentation = presentationFactory.createPresentation(vpIssuerDid
, verifiableCredentials, audience, walletKeyService.getPrivateKeyByWalletIdentifier(holderWallet.getId()));
, verifiableCredentials, audience, privateKey);

response.put(StringPool.VP, presentation.serialize());
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.util.io.pem.PemReader;
import org.bouncycastle.util.encoders.Base64;
import org.eclipse.tractusx.managedidentitywallets.dao.entity.WalletKey;
import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletKeyRepository;
import org.eclipse.tractusx.managedidentitywallets.utils.EncryptionUtils;
Expand Down Expand Up @@ -60,7 +60,6 @@ protected SpecificationUtil<WalletKey> getSpecificationUtil() {
return specificationUtil;
}


/**
* Get private key by wallet identifier as bytes byte [ ].
*
Expand All @@ -83,7 +82,7 @@ public byte[] getPrivateKeyByWalletIdentifierAsBytes(long walletId) {
public Ed25519Key getPrivateKeyByWalletIdentifier(long walletId) {
WalletKey wallet = walletKeyRepository.getByWalletId(walletId);
String privateKey = encryptionUtils.decrypt(wallet.getPrivateKey());
byte[] content = new PemReader(new StringReader(privateKey)).readPemObject().getContent();
byte[] content = Base64.decode(privateKey);
return Ed25519Key.asPrivateKey(content);
}

Expand Down
Loading

0 comments on commit 6463c3e

Please sign in to comment.