From e264c0f08de30fa5f3064f9a8d67c121419d75ad Mon Sep 17 00:00:00 2001 From: Nitin Vavdiya Date: Tue, 28 May 2024 21:00:50 +0530 Subject: [PATCH] fix: direct access to WalletKeyService while signing VC removed --- .../constant/MIWVerifiableCredentialType.java | 3 + .../dao/repository/WalletKeyRepository.java | 8 -- .../domain/CredentialCreationConfig.java | 7 ++ .../service/HoldersCredentialService.java | 28 +++++-- .../service/IssuersCredentialService.java | 57 ++++++++++---- .../service/JwtPresentationES256KService.java | 73 +---------------- .../service/LocalSecureTokenService.java | 1 - .../service/PresentationService.java | 78 +------------------ .../service/WalletKeyService.java | 16 ++-- .../signing/KeyProvider.java | 5 +- .../signing/LocalKeyProvider.java | 8 +- .../signing/LocalSigningServiceImpl.java | 39 +++++++++- .../utils/CommonUtils.java | 30 ------- .../service/IssuersCredentialServiceTest.java | 16 ++-- 14 files changed, 137 insertions(+), 232 deletions(-) diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/MIWVerifiableCredentialType.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/MIWVerifiableCredentialType.java index 62597d2b8..e7f166b44 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/MIWVerifiableCredentialType.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/MIWVerifiableCredentialType.java @@ -21,9 +21,12 @@ package org.eclipse.tractusx.managedidentitywallets.constant; +import lombok.experimental.UtilityClass; + /** * The type Miw verifiable credential type. */ +@UtilityClass public class MIWVerifiableCredentialType { public static final String VERIFIABLE_CREDENTIAL = "VerifiableCredential"; diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/dao/repository/WalletKeyRepository.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dao/repository/WalletKeyRepository.java index 483dbdfce..fcd0bc11b 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/dao/repository/WalletKeyRepository.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dao/repository/WalletKeyRepository.java @@ -39,14 +39,6 @@ public interface WalletKeyRepository extends BaseRepository { */ WalletKey getByWalletIdAndAlgorithm(Long id, String algorithm); - /** - * Gets by wallet id. - * - * @param id the id - * @return WalletKey by wallet id - */ - WalletKey getByWalletId(Long id); - /** * Find first by wallet bpn wallet key. * diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/CredentialCreationConfig.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/CredentialCreationConfig.java index 07f632672..f75ae464b 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/CredentialCreationConfig.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/CredentialCreationConfig.java @@ -24,8 +24,10 @@ import lombok.Builder; import lombok.Getter; import lombok.NonNull; +import lombok.Setter; import org.eclipse.tractusx.managedidentitywallets.constant.SupportedAlgorithms; 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.VerifiableCredentialStatus; import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredentialSubject; @@ -68,8 +70,13 @@ public class CredentialCreationConfig { private String keyName; @NonNull + @Setter private VerifiableEncoding encoding; + @Setter + //This is used when we issue VC as JWT + private VerifiableCredential verifiableCredential; + public static class CredentialCreationConfigBuilder { public CredentialCreationConfigBuilder vcId(Object object) { if (!(object instanceof URI) && !(object instanceof String)) { 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 fa2465378..a69ad4659 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/HoldersCredentialService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/HoldersCredentialService.java @@ -44,7 +44,6 @@ import org.eclipse.tractusx.managedidentitywallets.dto.CredentialsResponse; import org.eclipse.tractusx.managedidentitywallets.exception.CredentialNotFoundProblem; import org.eclipse.tractusx.managedidentitywallets.exception.ForbiddenException; -import org.eclipse.tractusx.managedidentitywallets.signing.KeyProvider; import org.eclipse.tractusx.managedidentitywallets.signing.SignerResult; import org.eclipse.tractusx.managedidentitywallets.signing.SigningService; import org.eclipse.tractusx.managedidentitywallets.utils.CommonUtils; @@ -82,9 +81,6 @@ public class HoldersCredentialService extends BaseService availableSigningServices; - private final KeyProvider keyProvider; - - private final WalletKeyService walletKeyService; @Override protected BaseRepository getRepository() { @@ -138,10 +134,27 @@ public PageImpl getCredentials(GetCredentialsCommand comman List list = new ArrayList<>(filter.getContent().size()); + Wallet issuerWallet = command.getIdentifier() != null ? commonService.getWalletByIdentifier(command.getIdentifier()) : holderWallet; + for (HoldersCredential credential : filter.getContent()) { CredentialsResponse cr = new CredentialsResponse(); if (command.isAsJwt()) { - cr.setJwt(CommonUtils.vcAsJwt(command.getIdentifier() != null ? commonService.getWalletByIdentifier(command.getIdentifier()) : holderWallet, holderWallet, credential.getData(), walletKeyService)); + + CredentialCreationConfig config = CredentialCreationConfig.builder() + .algorithm(SupportedAlgorithms.ED25519) + .issuerDoc(issuerWallet.getDidDocument()) + .holderDid(holderWallet.getDid()) + .keyName(issuerWallet.getBpn()) + .verifiableCredential(credential.getData()) + .subject(credential.getData().getCredentialSubject().get(0)) + .contexts(credential.getData().getContext()) + .vcId(credential.getData().getId()) + .types(credential.getData().getTypes()) + .encoding(VerifiableEncoding.JWT) + .build(); + + SignerResult signerResult = availableSigningServices.get(issuerWallet.getSigningServiceType()).createCredential(config); + cr.setJwt(signerResult.getJwt()); } else { cr.setVc(credential.getData()); } @@ -199,7 +212,10 @@ public CredentialsResponse issueCredential(Map data, String call // Return VC if (asJwt) { - cr.setJwt(CommonUtils.vcAsJwt(issuerWallet, commonService.getWalletByIdentifier(callerBpn), credential.getData(), walletKeyService)); + holdersCredentialCreationConfig.setVerifiableCredential(credential.getData()); + holdersCredentialCreationConfig.setEncoding(VerifiableEncoding.JWT); + SignerResult signerJwtResult = availableSigningServices.get(issuerWallet.getSigningServiceType()).createCredential(holdersCredentialCreationConfig); + cr.setJwt(signerJwtResult.getJwt()); } else { cr.setVc(credential.getData()); } 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 ee0cc0581..5cb44c63f 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialService.java @@ -117,7 +117,6 @@ public class IssuersCredentialService extends BaseService availableSigningServices; @@ -172,10 +171,27 @@ public PageImpl getCredentials(GetCredentialsCommand comman Page filter = filter(filterRequest, request, CriteriaOperator.AND); List list = new ArrayList<>(filter.getContent().size()); + + Wallet holderWallet = command.getIdentifier() != null ? commonService.getWalletByIdentifier(command.getIdentifier()) : issuerWallet; + for (IssuersCredential credential : filter.getContent()) { CredentialsResponse cr = new CredentialsResponse(); if (command.isAsJwt()) { - cr.setJwt(CommonUtils.vcAsJwt(issuerWallet, command.getIdentifier() != null ? commonService.getWalletByIdentifier(command.getIdentifier()) : issuerWallet, credential.getData(), walletKeyService)); + CredentialCreationConfig config = CredentialCreationConfig.builder() + .algorithm(SupportedAlgorithms.ED25519) + .issuerDoc(issuerWallet.getDidDocument()) + .holderDid(holderWallet.getDid()) + .keyName(issuerWallet.getBpn()) + .verifiableCredential(credential.getData()) + .subject(credential.getData().getCredentialSubject().get(0)) + .contexts(credential.getData().getContext()) + .vcId(credential.getData().getId()) + .types(credential.getData().getTypes()) + .encoding(VerifiableEncoding.JWT) + .build(); + + SignerResult signerResult = availableSigningServices.get(issuerWallet.getSigningServiceType()).createCredential(config); + cr.setJwt(signerResult.getJwt()); } else { cr.setVc(credential.getData()); } @@ -298,7 +314,10 @@ public CredentialsResponse issueFrameworkCredential(IssueFrameworkCredentialRequ // Return VC if (asJwt) { - cr.setJwt(CommonUtils.vcAsJwt(baseWallet, holderWallet, issuersCredential.getData(), walletKeyService)); + holdersCredentialCreationConfig.setVerifiableCredential(issuersCredential.getData()); + holdersCredentialCreationConfig.setEncoding(VerifiableEncoding.JWT); + SignerResult credential = availableSigningServices.get(baseWallet.getSigningServiceType()).createCredential(holdersCredentialCreationConfig); + cr.setJwt(credential.getJwt()); } else { cr.setVc(issuersCredential.getData()); } @@ -373,7 +392,10 @@ public CredentialsResponse issueDismantlerCredential(IssueDismantlerCredentialRe // Return VC if (asJwt) { - cr.setJwt(CommonUtils.vcAsJwt(issuerWallet, holderWallet, issuersCredential.getData(), walletKeyService)); + holdersCredentialCreationConfig.setVerifiableCredential(issuersCredential.getData()); + holdersCredentialCreationConfig.setEncoding(VerifiableEncoding.JWT); + SignerResult credential = availableSigningServices.get(issuerWallet.getSigningServiceType()).createCredential(holdersCredentialCreationConfig); + cr.setJwt(credential.getJwt()); } else { cr.setVc(issuersCredential.getData()); } @@ -452,7 +474,10 @@ public CredentialsResponse issueMembershipCredential(IssueMembershipCredentialRe // Return VC if (asJwt) { - cr.setJwt(CommonUtils.vcAsJwt(issuerWallet, holderWallet, issuersCredential.getData(), walletKeyService)); + holdersCredentialCreationConfig.setVerifiableCredential(issuersCredential.getData()); + holdersCredentialCreationConfig.setEncoding(VerifiableEncoding.JWT); + SignerResult credential = availableSigningServices.get(issuerWallet.getSigningServiceType()).createCredential(holdersCredentialCreationConfig); + cr.setJwt(credential.getJwt()); } else { cr.setVc(issuersCredential.getData()); } @@ -519,7 +544,10 @@ public CredentialsResponse issueCredentialUsingBaseWallet(String holderDid, Map< // Return VC if (asJwt) { - cr.setJwt(CommonUtils.vcAsJwt(issuerWallet, holderWallet, issuersCredential.getData(), walletKeyService)); + holdersCredentialCreationConfig.setVerifiableCredential(issuersCredential.getData()); + holdersCredentialCreationConfig.setEncoding(VerifiableEncoding.JWT); + SignerResult credential = availableSigningServices.get(issuerWallet.getSigningServiceType()).createCredential(holdersCredentialCreationConfig); + cr.setJwt(credential.getJwt()); } else { cr.setVc(issuersCredential.getData()); } @@ -580,6 +608,7 @@ private boolean validateJWTExpiryDate(boolean withExpiryDate, SignedJWT signedJW /** * Credentials validation map. * + * @param verificationRequest the verification request * @param withCredentialExpiryDate the with credential expiry date * @return the map */ @@ -610,7 +639,6 @@ public Map credentialsValidation(CredentialVerificationRequest v 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 { @@ -653,15 +681,7 @@ private boolean isSelfIssued(String holderBpn) { } - /** - * Update summery credentials. - * - * @param issuerDidDocument the issuer did document - * @param baseWalletId the issuer base wallet id - * @param holderBpn the holder bpn - * @param holderDid the holder did - * @param type the type - */ + private void updateSummeryCredentials(DidDocument issuerDidDocument, String issuerDid, String holderBpn, String holderDid, String type, SigningServiceType signingServiceType, SupportedAlgorithms algorithm) { //get last issued summary vc to holder to update items @@ -756,6 +776,11 @@ private Page getLastIssuedSummaryCredential(String issuerDid, return filter(filterRequest); } + /** + * Sets key service. + * + * @param availableKeyStorage the available key storage + */ @Autowired public void setKeyService(Map availableKeyStorage) { this.availableSigningServices = availableKeyStorage; diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/JwtPresentationES256KService.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/JwtPresentationES256KService.java index 8c7fdaa42..1d057d74b 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/JwtPresentationES256KService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/JwtPresentationES256KService.java @@ -30,30 +30,18 @@ import com.nimbusds.jose.JWSSigner; import com.nimbusds.jose.crypto.ECDSASigner; import com.nimbusds.jose.crypto.bc.BouncyCastleProviderSingleton; -import com.nimbusds.jose.jwk.Curve; import com.nimbusds.jose.jwk.ECKey; -import com.nimbusds.jose.jwk.KeyUse; -import com.nimbusds.jose.jwk.gen.ECKeyGenerator; import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.text.StringEscapeUtils; import org.eclipse.tractusx.managedidentitywallets.config.MIWSettings; -import org.eclipse.tractusx.managedidentitywallets.constant.SupportedAlgorithms; -import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; -import org.eclipse.tractusx.managedidentitywallets.dao.entity.WalletKey; -import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletRepository; import org.eclipse.tractusx.managedidentitywallets.exception.BadDataException; import org.eclipse.tractusx.managedidentitywallets.exception.SignatureFailureException; import org.eclipse.tractusx.managedidentitywallets.exception.UnsupportedAlgorithmException; -import org.eclipse.tractusx.managedidentitywallets.utils.CommonUtils; -import org.eclipse.tractusx.managedidentitywallets.utils.EncryptionUtils; 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.DidDocumentBuilder; -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.JWKVerificationMethod; import org.eclipse.tractusx.ssi.lib.model.did.VerificationMethod; import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; @@ -63,9 +51,6 @@ import org.eclipse.tractusx.ssi.lib.serialization.jwt.SerializedVerifiablePresentation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Isolation; -import org.springframework.transaction.annotation.Propagation; -import org.springframework.transaction.annotation.Transactional; import java.io.IOException; import java.net.URI; @@ -78,12 +63,6 @@ import java.util.UUID; import java.util.stream.Collectors; -import static org.eclipse.tractusx.managedidentitywallets.constant.StringPool.COLON_SEPARATOR; -import static org.eclipse.tractusx.managedidentitywallets.constant.StringPool.PRIVATE_KEY; -import static org.eclipse.tractusx.managedidentitywallets.constant.StringPool.PUBLIC_KEY; -import static org.eclipse.tractusx.managedidentitywallets.constant.StringPool.REFERENCE_KEY; -import static org.eclipse.tractusx.managedidentitywallets.constant.StringPool.VAULT_ACCESS_TOKEN; -import static org.eclipse.tractusx.managedidentitywallets.utils.CommonUtils.getKeyString; import static org.eclipse.tractusx.ssi.lib.model.did.JWKVerificationMethod.JWK_CURVE; import static org.eclipse.tractusx.ssi.lib.model.did.JWKVerificationMethod.JWK_KEK_TYPE; import static org.eclipse.tractusx.ssi.lib.model.did.JWKVerificationMethod.JWK_X; @@ -101,16 +80,10 @@ public class JwtPresentationES256KService { private JsonLdSerializer jsonLdSerializer; private Did agentDid; - private WalletRepository walletRepository; - private EncryptionUtils encryptionUtils; - private WalletKeyService walletKeyService; private MIWSettings miwSettings; @Autowired - public JwtPresentationES256KService(WalletRepository walletRepository, EncryptionUtils encryptionUtils, WalletKeyService walletKeyService, MIWSettings miwSettings) { - this.walletRepository = walletRepository; - this.encryptionUtils = encryptionUtils; - this.walletKeyService = walletKeyService; + public JwtPresentationES256KService(MIWSettings miwSettings) { this.miwSettings = miwSettings; } @@ -132,50 +105,6 @@ public SignedJWT createPresentation(Did issuer, List crede return createSignedJwt(verifiablePresentation.getId(), issuer, audience, serializedVerifiablePresentation, ecPrivateKey); } - @Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation = Propagation.REQUIRES_NEW) - public Wallet storeWalletKeyES256K(Wallet wallet, String keyId) { - try { - ECKey ecKey = new ECKeyGenerator(Curve.SECP256K1) - .keyUse(KeyUse.SIGNATURE) - .keyID(keyId) - .provider(BouncyCastleProviderSingleton.getInstance()) - .generate(); - - Did did = getDidFromDidString(wallet.getDid()); - - JWKVerificationMethod jwkVerificationMethod = getJwkVerificationMethod(ecKey, did); - DidDocument didDocument = wallet.getDidDocument(); - List verificationMethods = didDocument.getVerificationMethods(); - verificationMethods.add(jwkVerificationMethod); - DidDocument updatedDidDocument = buildDidDocument(wallet.getBpn(), did, verificationMethods); - - wallet = walletRepository.getByDid(wallet.getDid()); - wallet.setDidDocument(updatedDidDocument); - walletRepository.save(wallet); - - WalletKey walletKeyES256K = WalletKey.builder() - .keyId(keyId) - .referenceKey(REFERENCE_KEY) - .vaultAccessToken(VAULT_ACCESS_TOKEN) - .privateKey(encryptionUtils.encrypt(CommonUtils.getKeyString(ecKey.toECPrivateKey().getEncoded(), PRIVATE_KEY))) - .publicKey(encryptionUtils.encrypt(getKeyString(ecKey.toECPublicKey().getEncoded(), PUBLIC_KEY))) - .algorithm(SupportedAlgorithms.ES256K.toString()) - .build(); - //Save key ES256K - walletKeyService.getRepository().save(walletKeyES256K); - } catch (JOSEException e) { - throw new BadDataException("Could not generate EC Jwk", e); - } - return wallet; - } - - private Did getDidFromDidString(String didString) { - int index = StringUtils.ordinalIndexOf(didString, COLON_SEPARATOR, 2); - String identifier = didString.substring(index + 1); - DidMethod didMethod = new DidMethod("web"); - DidMethodIdentifier methodIdentifier = new DidMethodIdentifier(identifier); - return new Did(didMethod, methodIdentifier, null); - } public JWKVerificationMethod getJwkVerificationMethod(ECKey ecKey, Did did) { Map verificationMethodJson = new HashMap<>(); diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/LocalSecureTokenService.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/LocalSecureTokenService.java index 5ffae8bd6..d6fccfb60 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/LocalSecureTokenService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/LocalSecureTokenService.java @@ -27,7 +27,6 @@ import org.eclipse.tractusx.managedidentitywallets.dao.entity.JtiRecord; import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; import org.eclipse.tractusx.managedidentitywallets.dao.repository.JtiRepository; -import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletKeyRepository; import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletRepository; import org.eclipse.tractusx.managedidentitywallets.domain.BusinessPartnerNumber; import org.eclipse.tractusx.managedidentitywallets.domain.DID; diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/PresentationService.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/PresentationService.java index 75f6f370b..a121b84a3 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/PresentationService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/PresentationService.java @@ -30,7 +30,6 @@ import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.tuple.Pair; import org.eclipse.tractusx.managedidentitywallets.config.MIWSettings; import org.eclipse.tractusx.managedidentitywallets.constant.StringPool; import org.eclipse.tractusx.managedidentitywallets.constant.SupportedAlgorithms; @@ -48,32 +47,22 @@ import org.eclipse.tractusx.managedidentitywallets.signing.SignerResult; import org.eclipse.tractusx.managedidentitywallets.signing.SigningService; import org.eclipse.tractusx.managedidentitywallets.utils.Validate; -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.json.InvalidJsonLdException; -import org.eclipse.tractusx.ssi.lib.exception.key.InvalidPrivateKeyFormatException; import org.eclipse.tractusx.ssi.lib.exception.proof.JwtExpiredException; -import org.eclipse.tractusx.ssi.lib.jwt.SignedJwtFactory; import org.eclipse.tractusx.ssi.lib.jwt.SignedJwtValidator; 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.DidParser; import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; 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.proof.LinkedDataProofValidation; 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; import org.eclipse.tractusx.ssi.lib.serialization.jwt.SerializedVerifiablePresentation; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.net.URI; -import java.security.interfaces.ECPrivateKey; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -114,7 +103,6 @@ public class PresentationService extends BaseService { private final JtiRepository jtiRepository; - private final WalletKeyService walletKeyService; @Override protected BaseRepository getRepository() { @@ -169,7 +157,7 @@ public Map createPresentation(Map data, boolean } else { log.debug("Creating VP as JSON-LD for bpn ->{}", callerBpn); builder.encoding(VerifiableEncoding.JSON_LD) - .verificationMethod(URI.create(miwSettings.authorityWalletDid() + "#" + UUID.randomUUID().toString())); + .verificationMethod(URI.create(miwSettings.authorityWalletDid() + "#" + UUID.randomUUID())); } PresentationCreationConfig presentationConfig = builder.build(); @@ -180,68 +168,6 @@ public Map createPresentation(Map data, boolean return response; } - private Map buildVP(boolean asJwt, String audience, String callerBpn, Wallet callerWallet, List verifiableCredentials, SupportedAlgorithms algorithm) { - Map response = new HashMap<>(); - if (asJwt && algorithm.equals(SupportedAlgorithms.ES256K)) { - buildVPJwtES256K(audience, callerBpn, callerWallet, verifiableCredentials, algorithm, response); - } else if (asJwt && algorithm.equals(SupportedAlgorithms.ED25519)) { - buildVPJwtEdDSA(audience, callerBpn, callerWallet, verifiableCredentials, algorithm, response); - } else { - buildVPJsonLd(callerBpn, verifiableCredentials, response); - } - return response; - } - - private void buildVPJsonLd(String callerBpn, List verifiableCredentials, Map response) { - log.debug("Creating VP as JSON-LD for bpn ->{}", callerBpn); - VerifiablePresentationBuilder verifiablePresentationBuilder = - new VerifiablePresentationBuilder(); - - VerifiablePresentation verifiablePresentation = - verifiablePresentationBuilder - .id(URI.create(miwSettings.authorityWalletDid() + "#" + UUID.randomUUID())) - .type(List.of(VerifiablePresentationType.VERIFIABLE_PRESENTATION)) - .verifiableCredentials(verifiableCredentials) - .build(); - response.put(StringPool.VP, verifiablePresentation); - } - - @SneakyThrows({ InvalidPrivateKeyFormatException.class }) - private void buildVPJwtEdDSA(String audience, String callerBpn, Wallet callerWallet, List verifiableCredentials, SupportedAlgorithms algorithm, Map response) { - Pair result = getPrivateKey(callerWallet, algorithm, audience, callerBpn); - String keyId = walletKeyService.getWalletKeyIdByWalletId(callerWallet.getId(), algorithm); - - SerializedJwtPresentationFactory presentationFactory = new SerializedJwtPresentationFactoryImpl( - new SignedJwtFactory(new OctetKeyPairFactory()), new JsonLdSerializerImpl(), result.getKey()); - - X25519PrivateKey ed25519Key = (X25519PrivateKey) result.getRight(); - X25519PrivateKey privateKey = new X25519PrivateKey(ed25519Key.asByte()); - SignedJWT presentation = presentationFactory.createPresentation(result.getLeft(), verifiableCredentials, audience, privateKey, keyId); - response.put(StringPool.VP, presentation.serialize()); - } - - private void buildVPJwtES256K(String audience, String callerBpn, Wallet callerWallet, List verifiableCredentials, SupportedAlgorithms algorithm, Map response) { - Pair result = getPrivateKey(callerWallet, algorithm, audience, callerBpn); - ECPrivateKey ecPrivateKey = (ECPrivateKey) result.getRight(); - - JwtPresentationES256KService presentationFactory = new JwtPresentationES256KService(result.getLeft(), new JsonLdSerializerImpl()); - SignedJWT presentation = presentationFactory.createPresentation(result.getLeft(), verifiableCredentials, audience, ecPrivateKey); - - response.put(StringPool.VP, presentation.serialize()); - } - - @SneakyThrows({ DidParseException.class }) - private Pair getPrivateKey(Wallet callerWallet, SupportedAlgorithms algorithm, String audience, String callerBpn) { - log.debug("Creating VP as JWT for bpn ->{}", callerBpn); - 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(callerWallet.getDid()); - - //Build JWT - return Pair.of(vpIssuerDid, walletKeyService.getPrivateKeyByWalletIdAndAlgorithm(callerWallet.getId(), algorithm)); - } - /** * Validate presentation map. * @@ -409,7 +335,7 @@ public Map createVpWithRequiredScopes(SignedJWT innerJWT, boolea .algorithm(SupportedAlgorithms.ES256K); } else { builder.encoding(VerifiableEncoding.JSON_LD) - .verificationMethod(URI.create(miwSettings.authorityWalletDid() + "#" + UUID.randomUUID().toString())) + .verificationMethod(URI.create(miwSettings.authorityWalletDid() + "#" + UUID.randomUUID())) .algorithm(SupportedAlgorithms.valueOf(callerWallet.getAlgorithm())); } 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 51357e2ba..ab7a636a6 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/WalletKeyService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/WalletKeyService.java @@ -79,8 +79,8 @@ protected SpecificationUtil getSpecificationUtil() { @SneakyThrows public byte[] getPrivateKeyByWalletIdAsBytes(long walletId, String algorithm) { Object privateKey = getPrivateKeyByWalletIdAndAlgorithm(walletId, SupportedAlgorithms.valueOf(algorithm)); - if (privateKey instanceof X25519PrivateKey X25519PrivateKey) { - return X25519PrivateKey.asByte(); + if (privateKey instanceof X25519PrivateKey x25519PrivateKey) { + return x25519PrivateKey.asByte(); } else { return ((ECPrivateKey) privateKey).getEncoded(); } @@ -88,13 +88,13 @@ public byte[] getPrivateKeyByWalletIdAsBytes(long walletId, String algorithm) { @SneakyThrows - public byte[] getPrivateKeyByKeyId(String keyId, SupportedAlgorithms supportedAlgorithms) { - WalletKey wallet = walletKeyRepository.getByKeyIdAndAlgorithm(keyId, supportedAlgorithms.name()); - Object privateKey = getKeyObject(SupportedAlgorithms.valueOf(wallet.getAlgorithm()), encryptionUtils.decrypt(wallet.getPrivateKey())); - if (privateKey instanceof X25519PrivateKey X25519PrivateKey) { - return X25519PrivateKey.asByte(); + public Object getPrivateKeyByKeyId(String keyId, SupportedAlgorithms supportedAlgorithms) { + WalletKey walletKey = walletKeyRepository.getByKeyIdAndAlgorithm(keyId, supportedAlgorithms.name()); + Object privateKey = getKeyObject(SupportedAlgorithms.valueOf(walletKey.getAlgorithm()), encryptionUtils.decrypt(walletKey.getPrivateKey())); + if (privateKey instanceof X25519PrivateKey x25519PrivateKey) { + return x25519PrivateKey; } else { - return ((ECPrivateKey) privateKey).getEncoded(); + return privateKey; } } /** diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/KeyProvider.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/KeyProvider.java index 5efd1afcc..e8b925dad 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/KeyProvider.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/KeyProvider.java @@ -41,7 +41,7 @@ public interface KeyProvider { * @return the key as a byte-array * */ - byte[] getPrivateKey(String keyName, SupportedAlgorithms algorithm); + Object getPrivateKey(String keyName, SupportedAlgorithms algorithm); /** * @param walletKey the key to save @@ -49,6 +49,9 @@ public interface KeyProvider { void saveKeys(List walletKey); + String getKeyId(String keyName, SupportedAlgorithms algorithm); + + /** * @return the type of KeyProvider * diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/LocalKeyProvider.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/LocalKeyProvider.java index df590a20e..93353361d 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/LocalKeyProvider.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/LocalKeyProvider.java @@ -45,7 +45,7 @@ public class LocalKeyProvider implements KeyProvider { private final EncryptionUtils encryptionUtils; @Override - public byte[] getPrivateKey(String keyName, SupportedAlgorithms algorithm) { + public Object getPrivateKey(String keyName, SupportedAlgorithms algorithm) { WalletKey walletKey = walletKeyRepository.getByAlgorithmAndWallet_Bpn(algorithm.name(), keyName); return walletKeyService.getPrivateKeyByKeyId(walletKey.getKeyId(), algorithm); } @@ -55,6 +55,12 @@ public void saveKeys(List walletKeys) { walletKeyRepository.saveAllAndFlush(walletKeys); } + @Override + public String getKeyId(String keyName, SupportedAlgorithms algorithm) { + WalletKey walletKey = walletKeyRepository.getByAlgorithmAndWallet_Bpn(algorithm.name(), keyName); + return walletKey.getKeyId(); + } + @Override public KeyStorageType getKeyStorageType() { return KeyStorageType.DB; diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/LocalSigningServiceImpl.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/LocalSigningServiceImpl.java index 1cef961c9..1b1198ff3 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/LocalSigningServiceImpl.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/LocalSigningServiceImpl.java @@ -60,6 +60,7 @@ import org.eclipse.tractusx.ssi.lib.jwt.SignedJwtFactory; import org.eclipse.tractusx.ssi.lib.model.JsonLdObject; import org.eclipse.tractusx.ssi.lib.model.base.EncodeType; +import org.eclipse.tractusx.ssi.lib.model.did.DidParser; import org.eclipse.tractusx.ssi.lib.model.proof.Proof; import org.eclipse.tractusx.ssi.lib.model.verifiable.Verifiable; import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; @@ -72,6 +73,7 @@ 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; +import org.eclipse.tractusx.ssi.lib.serialization.jwt.SerializedJwtVCFactoryImpl; import org.springframework.stereotype.Component; import java.net.URI; @@ -102,20 +104,51 @@ public class LocalSigningServiceImpl implements LocalSigningService { @Override public SignerResult createCredential(CredentialCreationConfig config) { - byte[] privateKeyBytes = keyProvider.getPrivateKey(config.getKeyName(), config.getAlgorithm()); + byte[] privateKeyBytes = getPrivateKeyBytes(config.getKeyName(), config.getAlgorithm()); VerifiableEncoding encoding = Objects.requireNonNull(config.getEncoding()); SignerResult.SignerResultBuilder resultBuilder = SignerResult.builder().encoding(encoding); switch (encoding) { case JSON_LD -> { return resultBuilder.jsonLd(createVerifiableCredential(config, privateKeyBytes)).build(); } - case JWT -> throw new NotImplementedException("not implemented yet"); + case JWT -> { + SignedJWT verifiableCredentialAsJwt = createVerifiableCredentialAsJwt(config); + return resultBuilder.jwt(verifiableCredentialAsJwt.serialize()).build(); + } default -> throw new IllegalArgumentException("encoding %s is not supported".formatted(config.getEncoding())); } } + private byte[] getPrivateKeyBytes(String keyName, SupportedAlgorithms supportedAlgorithms) { + byte[] privateKeyBytes; + if (supportedAlgorithms.equals(SupportedAlgorithms.ED25519)) { + privateKeyBytes = ((IPrivateKey) keyProvider.getPrivateKey(keyName, supportedAlgorithms)).asByte(); + } else if (supportedAlgorithms.equals(SupportedAlgorithms.ES256K)) { + ECPrivateKey ecKey = (ECPrivateKey) keyProvider.getPrivateKey(keyName, supportedAlgorithms); + privateKeyBytes = ecKey.getEncoded(); + } else { + throw new IllegalArgumentException("Unknown algorithm " + supportedAlgorithms); + } + return privateKeyBytes; + } + + @SneakyThrows + private SignedJWT createVerifiableCredentialAsJwt(CredentialCreationConfig config) { + if (!config.getAlgorithm().equals(SupportedAlgorithms.ED25519)) { + throw new IllegalArgumentException("VC as JWT is not supported for provided algorithm -> " + config.getAlgorithm()); + } + // JWT Factory + SerializedJwtVCFactoryImpl vcFactory = new SerializedJwtVCFactoryImpl( + new SignedJwtFactory(new OctetKeyPairFactory())); + IPrivateKey iPrivateKey = ((IPrivateKey) keyProvider.getPrivateKey(config.getKeyName(), config.getAlgorithm())); + + return vcFactory.createVCJwt(DidParser.parse(config.getIssuerDoc().getId()), DidParser.parse(config.getHolderDid()), config.getVerifiableCredential(), + iPrivateKey, + keyProvider.getKeyId(config.getKeyName(), config.getAlgorithm())); + } + @Override public Map getKeys(KeyCreationConfig config) throws KeyGenerationException { @@ -195,7 +228,7 @@ public SigningServiceType getSupportedServiceType() { @Override public SignerResult createPresentation(PresentationCreationConfig config) { - byte[] privateKeyBytes = keyProvider.getPrivateKey(config.getKeyName(), config.getAlgorithm()); + byte[] privateKeyBytes = getPrivateKeyBytes(config.getKeyName(), config.getAlgorithm()); VerifiableEncoding encoding = Objects.requireNonNull(config.getEncoding()); SignerResult.SignerResultBuilder resultBuilder = SignerResult.builder().encoding(encoding); switch (config.getEncoding()) { 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 83626da0c..c38a50d64 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/CommonUtils.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/CommonUtils.java @@ -22,28 +22,17 @@ package org.eclipse.tractusx.managedidentitywallets.utils; import com.fasterxml.jackson.databind.ObjectMapper; -import com.nimbusds.jwt.SignedJWT; import lombok.SneakyThrows; import lombok.experimental.UtilityClass; import org.bouncycastle.util.io.pem.PemObject; import org.bouncycastle.util.io.pem.PemWriter; import org.eclipse.tractusx.managedidentitywallets.constant.StringPool; -import org.eclipse.tractusx.managedidentitywallets.constant.SupportedAlgorithms; import org.eclipse.tractusx.managedidentitywallets.dao.entity.HoldersCredential; -import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; import org.eclipse.tractusx.managedidentitywallets.domain.CredentialCreationConfig; import org.eclipse.tractusx.managedidentitywallets.dto.SecureTokenRequest; import org.eclipse.tractusx.managedidentitywallets.exception.BadDataException; -import org.eclipse.tractusx.managedidentitywallets.service.WalletKeyService; -import org.eclipse.tractusx.ssi.lib.crypt.octet.OctetKeyPairFactory; -import org.eclipse.tractusx.ssi.lib.crypt.x25519.X25519PrivateKey; -import org.eclipse.tractusx.ssi.lib.exception.did.DidParseException; -import org.eclipse.tractusx.ssi.lib.jwt.SignedJwtFactory; -import org.eclipse.tractusx.ssi.lib.model.did.Did; -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.model.verifiable.credential.VerifiableCredentialType; -import org.eclipse.tractusx.ssi.lib.serialization.jwt.SerializedJwtVCFactoryImpl; import org.springframework.util.MultiValueMap; import java.io.StringWriter; @@ -114,25 +103,6 @@ public static SecureTokenRequest getSecureTokenRequest(MultiValueMap(), - holdersCredentialRepository, commonService, objectMapper, - walletKeyService); + holdersCredentialRepository, commonService, objectMapper); } @BeforeEach @@ -199,8 +198,7 @@ void shouldIssueCredentialAsJwt() .asByte()); - when(walletKeyService.getPrivateKeyByKeyId(anyString(), any())).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); @@ -264,8 +262,7 @@ void shouldIssueCredentialAsJwt() when(baseWallet.getSigningServiceType()).thenReturn(SigningServiceType.LOCAL); - when(walletKeyService.getPrivateKeyByKeyId(anyString(), any())).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); @@ -318,8 +315,7 @@ void shouldIssueCredentialAsJwt() throws IOException, InvalidPrivateKeyFormatExc when(baseWallet.getSigningServiceType()).thenReturn(SigningServiceType.LOCAL); - when(walletKeyService.getPrivateKeyByKeyId(anyString(), any())).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); @@ -382,9 +378,9 @@ public HoldersCredential answer(InvocationOnMock invocation) throws Throwable { .thenReturn(new X25519PrivateKey(keyPair.getPrivateKey().asStringForStoring(), true)); when(walletKeyService.getWalletKeyIdByWalletId(baseWallet.getId(), SupportedAlgorithms.ED25519)).thenReturn(walletKeyId); + when(walletKeyRepository.getByKeyIdAndAlgorithm(anyString(), anyString())).thenReturn(walletKey); when(baseWallet.getSigningServiceType()).thenReturn(SigningServiceType.LOCAL); - when(walletKeyService.getPrivateKeyByKeyId(anyString(), any())).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);