diff --git a/dev-assets/env-files/env.docker.dist b/dev-assets/env-files/env.docker.dist index d6c8204c8..aeedf42a1 100644 --- a/dev-assets/env-files/env.docker.dist +++ b/dev-assets/env-files/env.docker.dist @@ -26,6 +26,8 @@ ENCRYPTION_KEY= AUTHORITY_WALLET_BPN=BPNL000000000000 AUTHORITY_WALLET_DID=did:web:localhost:BPNL000000000000 AUTHORITY_WALLET_NAME=Catena-X +AUTHORITY_SIGNING_SERVICE_TYPE=LOCAL +LOCAL_SIGNING_KEY_STORAGE_TYPE=DB KEYCLOAK_REALM=miw_test VC_SCHEMA_LINK="https://www.w3.org/2018/credentials/v1, https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json" VC_EXPIRY_DATE=01-01-2025 diff --git a/dev-assets/env-files/env.local.dist b/dev-assets/env-files/env.local.dist index 68ffa0547..30c20135a 100644 --- a/dev-assets/env-files/env.local.dist +++ b/dev-assets/env-files/env.local.dist @@ -26,6 +26,8 @@ ENCRYPTION_KEY= AUTHORITY_WALLET_BPN=BPNL000000000000 AUTHORITY_WALLET_DID=did:web:localhost:BPNL000000000000 AUTHORITY_WALLET_NAME=Catena-X +AUTHORITY_SIGNING_SERVICE_TYPE=LOCAL +LOCAL_SIGNING_KEY_STORAGE_TYPE=DB KEYCLOAK_REALM=miw_test VC_SCHEMA_LINK="https://www.w3.org/2018/credentials/v1, https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json" VC_EXPIRY_DATE=01-01-2025 diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/ManagedIdentityWalletsApplication.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/ManagedIdentityWalletsApplication.java index f67053adc..3e50441c1 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/ManagedIdentityWalletsApplication.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/ManagedIdentityWalletsApplication.java @@ -1,6 +1,6 @@ /* * ******************************************************************************* - * Copyright (c) 2021,2023 Contributors to the Eclipse Foundation + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/ApplicationConfig.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/ApplicationConfig.java index a8cb28daf..7d7541e5f 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/ApplicationConfig.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/ApplicationConfig.java @@ -28,6 +28,10 @@ import com.smartsensesolutions.java.commons.specification.SpecificationUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.text.StringEscapeUtils; +import org.eclipse.tractusx.managedidentitywallets.domain.SigningServiceType; +import org.eclipse.tractusx.managedidentitywallets.signing.KeyProvider; +import org.eclipse.tractusx.managedidentitywallets.signing.LocalSigningService; +import org.eclipse.tractusx.managedidentitywallets.signing.SigningService; import org.springdoc.core.properties.SwaggerUiConfigProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -40,6 +44,10 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.nio.charset.StandardCharsets; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * The type Application config. @@ -50,11 +58,13 @@ public class ApplicationConfig implements WebMvcConfigurer { private final SwaggerUiConfigProperties properties; private final String resourceBundlePath; + private final MIWSettings miwSettings; @Autowired - public ApplicationConfig(@Value("${resource.bundle.path:classpath:i18n/language}") String resourceBundlePath, SwaggerUiConfigProperties properties) { + public ApplicationConfig(@Value("${resource.bundle.path:classpath:i18n/language}") String resourceBundlePath, SwaggerUiConfigProperties properties, MIWSettings miwSettings) { this.resourceBundlePath = resourceBundlePath; this.properties = properties; + this.miwSettings = miwSettings; } /** @@ -98,4 +108,23 @@ public LocalValidatorFactoryBean validator() { beanValidatorFactory.setValidationMessageSource(messageSource()); return beanValidatorFactory; } + + @Bean + public Map availableKeyStorages(List storages, List keyProviders) { + KeyProvider localSigningKeyProvider = keyProviders.stream().filter(s -> s.getKeyStorageType().equals(miwSettings.localSigningKeyStorageType())) + .findFirst() + .orElseThrow(() -> new IllegalStateException("no key provider with type %s found".formatted(miwSettings.localSigningKeyStorageType()))); + + Map available = new EnumMap<>(SigningServiceType.class); + storages.forEach( + s -> { + if(s instanceof LocalSigningService local){ + local.setKeyProvider(localSigningKeyProvider); + } + available.put(s.getSupportedServiceType(), s); + } + ); + + return available; + } } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/MIWSettings.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/MIWSettings.java index 95c3bb747..2880a6a45 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/MIWSettings.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/MIWSettings.java @@ -21,6 +21,8 @@ package org.eclipse.tractusx.managedidentitywallets.config; +import org.eclipse.tractusx.managedidentitywallets.domain.KeyStorageType; +import org.eclipse.tractusx.managedidentitywallets.domain.SigningServiceType; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.format.annotation.DateTimeFormat; @@ -39,5 +41,7 @@ public record MIWSettings(String host, String encryptionKey, String authorityWal @DateTimeFormat(pattern = "dd-MM-yyyy") Date vcExpiryDate, Set supportedFrameworkVCTypes, boolean enforceHttps, String contractTemplatesUrl, - List didDocumentContextUrls) { -} \ No newline at end of file + List didDocumentContextUrls, + KeyStorageType localSigningKeyStorageType, + SigningServiceType authoritySigningServiceType) { +} 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 1d05be7d2..669705031 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/StringPool.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/StringPool.java @@ -91,4 +91,6 @@ private StringPool() { public static final String BEARER_SPACE = "Bearer "; public static final String BPN_NUMBER_REGEX = "^(BPN)(L|S|A)[0-9A-Z]{12}"; + + public static final String W3_ID_JWS_2020_V1_CONTEXT_URL = "https://w3id.org/security/suites/jws-2020/v1"; } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/IssuersCredentialController.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/IssuersCredentialController.java index 90ff993e3..9a7f9c10c 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/IssuersCredentialController.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/IssuersCredentialController.java @@ -28,11 +28,10 @@ import jakarta.validation.constraints.Min; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; - import org.eclipse.tractusx.managedidentitywallets.apidocs.IssuersCredentialControllerApiDocs.GetCredentialsApiDocs; import org.eclipse.tractusx.managedidentitywallets.apidocs.IssuersCredentialControllerApiDocs.IssueDismantlerCredentialApiDoc; -import org.eclipse.tractusx.managedidentitywallets.apidocs.IssuersCredentialControllerApiDocs.IssueMembershipCredentialApiDoc; import org.eclipse.tractusx.managedidentitywallets.apidocs.IssuersCredentialControllerApiDocs.IssueFrameworkCredentialApiDocs; +import org.eclipse.tractusx.managedidentitywallets.apidocs.IssuersCredentialControllerApiDocs.IssueMembershipCredentialApiDoc; import org.eclipse.tractusx.managedidentitywallets.apidocs.IssuersCredentialControllerApiDocs.IssueVerifiableCredentialUsingBaseWalletApiDocs; import org.eclipse.tractusx.managedidentitywallets.apidocs.IssuersCredentialControllerApiDocs.ValidateVerifiableCredentialApiDocs; import org.eclipse.tractusx.managedidentitywallets.constant.RestURI; @@ -45,7 +44,11 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; import java.security.Principal; import java.util.List; diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/dao/entity/Wallet.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dao/entity/Wallet.java index 4cb65dba9..9e21a85ee 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/dao/entity/Wallet.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dao/entity/Wallet.java @@ -23,8 +23,21 @@ import com.fasterxml.jackson.annotation.JsonIgnore; -import jakarta.persistence.*; -import lombok.*; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Transient; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.eclipse.tractusx.managedidentitywallets.domain.SigningServiceType; import org.eclipse.tractusx.managedidentitywallets.utils.StringToDidDocumentConverter; import org.eclipse.tractusx.ssi.lib.model.did.DidDocument; import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; @@ -60,10 +73,16 @@ public class Wallet extends MIWBaseEntity { @Column(nullable = false) private String algorithm; + @Enumerated(EnumType.STRING) + @Column(name="signing_service_type", nullable = false) + private SigningServiceType signingServiceType; + @Column(nullable = false) @Convert(converter = StringToDidDocumentConverter.class) private DidDocument didDocument; + + @Transient private List verifiableCredentials; } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/CredentialCreationConfig.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/CredentialCreationConfig.java new file mode 100644 index 000000000..b0048b1cd --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/CredentialCreationConfig.java @@ -0,0 +1,85 @@ +/* + * ******************************************************************************* + * 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.domain; + +import lombok.Builder; +import lombok.Getter; +import lombok.NonNull; +import org.eclipse.tractusx.ssi.lib.model.did.DidDocument; +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredentialStatus; +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredentialSubject; + +import java.net.URI; +import java.util.Date; +import java.util.List; + +@Builder +@Getter +public class CredentialCreationConfig { + + @NonNull + private VerifiableCredentialSubject subject; + + private VerifiableCredentialStatus verifiableCredentialStatus; + + @NonNull + private DidDocument issuerDoc; + + @NonNull + private String holderDid; + + @NonNull + private List types; + + @NonNull + private List contexts; + + private URI vcId; + + private Date expiryDate; + + private boolean selfIssued; + + // this will be used by the DB-Impl of storage to retrieve privateKey + @NonNull + private String keyName; + + @NonNull + private VerifiableEncoding encoding; + + public static class CredentialCreationConfigBuilder { + public CredentialCreationConfigBuilder vcId(Object object) { + if (!(object instanceof URI) && !(object instanceof String)) { + throw new IllegalArgumentException("vcId must be of type String or URI, argument has type%s".formatted(object.getClass().getName())); + } + + if (object instanceof URI uri) { + this.vcId = uri; + } else { + this.vcId = URI.create((String) object); + } + + return this; + + } + } +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/KeyCreationConfig.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/KeyCreationConfig.java new file mode 100644 index 000000000..6f5ef2e5e --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/KeyCreationConfig.java @@ -0,0 +1,41 @@ +/* + * ******************************************************************************* + * 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.domain; + +import com.nimbusds.jose.jwk.Curve; +import com.nimbusds.jose.jwk.KeyType; +import lombok.Builder; +import lombok.Getter; +import lombok.NonNull; + +@Builder +@Getter +public class KeyCreationConfig { + + @NonNull + private String keyName; + + private Curve curve; + + @NonNull + private KeyType keyType; +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/KeyStorageType.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/KeyStorageType.java new file mode 100644 index 000000000..1fd489de4 --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/KeyStorageType.java @@ -0,0 +1,27 @@ +/* + * ******************************************************************************* + * 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.domain; + +public enum KeyStorageType { + DB, + REMOTE +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/PresentationCreationConfig.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/PresentationCreationConfig.java new file mode 100644 index 000000000..430b6c1a9 --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/PresentationCreationConfig.java @@ -0,0 +1,55 @@ +/* + * ******************************************************************************* + * 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.domain; + +import lombok.Builder; +import lombok.Getter; +import lombok.NonNull; +import org.eclipse.tractusx.ssi.lib.model.did.Did; +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; + +import java.net.URI; +import java.util.List; + +@Builder +@Getter +public class PresentationCreationConfig { + + @NonNull + private VerifiableEncoding encoding; + + @NonNull + private String keyName; + + @NonNull + private List verifiableCredentials; + + @NonNull + private Did vpIssuerDid; + + // all for JWT + private String audience; + + // all for JsonLD + URI verificationMethod; + +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/SigningServiceType.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/SigningServiceType.java new file mode 100644 index 000000000..1b31137a5 --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/SigningServiceType.java @@ -0,0 +1,28 @@ +/* + * ******************************************************************************* + * 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.domain; + +public enum SigningServiceType { + LOCAL, + AZURE, + REMOTE +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/VerifiableEncoding.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/VerifiableEncoding.java new file mode 100644 index 000000000..64a1e23cf --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/domain/VerifiableEncoding.java @@ -0,0 +1,27 @@ +/* + * ******************************************************************************* + * 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.domain; + +public enum VerifiableEncoding { + JWT, + JSON_LD +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/CreateWalletRequest.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/CreateWalletRequest.java index 6c6f4d62e..3c26af9c0 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/CreateWalletRequest.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/CreateWalletRequest.java @@ -26,6 +26,7 @@ import jakarta.validation.constraints.Size; import lombok.*; import org.eclipse.tractusx.managedidentitywallets.constant.StringPool; +import org.eclipse.tractusx.managedidentitywallets.domain.SigningServiceType; /** @@ -45,4 +46,6 @@ public class CreateWalletRequest { @NotBlank(message = "Please provide name") @Size(min = 1, max = 255, message = "Please provide valid name") private String name; + + private SigningServiceType signingServiceType = SigningServiceType.LOCAL; } 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 670055051..bdaa90888 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/HoldersCredentialService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/HoldersCredentialService.java @@ -36,8 +36,13 @@ import org.eclipse.tractusx.managedidentitywallets.dao.entity.HoldersCredential; import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; import org.eclipse.tractusx.managedidentitywallets.dao.repository.HoldersCredentialRepository; +import org.eclipse.tractusx.managedidentitywallets.domain.CredentialCreationConfig; +import org.eclipse.tractusx.managedidentitywallets.domain.SigningServiceType; +import org.eclipse.tractusx.managedidentitywallets.domain.VerifiableEncoding; import org.eclipse.tractusx.managedidentitywallets.exception.CredentialNotFoundProblem; import org.eclipse.tractusx.managedidentitywallets.exception.ForbiddenException; +import org.eclipse.tractusx.managedidentitywallets.signing.SignerResult; +import org.eclipse.tractusx.managedidentitywallets.signing.SigningService; import org.eclipse.tractusx.managedidentitywallets.utils.CommonUtils; import org.eclipse.tractusx.managedidentitywallets.utils.Validate; import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; @@ -71,7 +76,7 @@ public class HoldersCredentialService extends BaseService credentialSpecificationUtil; - private final WalletKeyService walletKeyService; + private final Map availableSigningServices; @Override protected BaseRepository getRepository() { @@ -150,19 +155,29 @@ public VerifiableCredential issueCredential(Map data, String cal //validate BPN access, Holder must be caller of API 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()); - // check if the expiryDate is set Date expiryDate = null; if (verifiableCredential.getExpirationDate() != null) { expiryDate = Date.from(verifiableCredential.getExpirationDate()); } + + CredentialCreationConfig holdersCredentialCreationConfig = CredentialCreationConfig.builder() + .encoding(VerifiableEncoding.JSON_LD) + .subject(verifiableCredential.getCredentialSubject().get(0)) + .types(verifiableCredential.getTypes()) + .issuerDoc(issuerWallet.getDidDocument()) + .holderDid(issuerWallet.getDid()) + .contexts(verifiableCredential.getContext()) + .expiryDate(expiryDate) + .selfIssued(true) + .keyName(issuerWallet.getBpn()) + .build(); + // Create Credential - HoldersCredential credential = CommonUtils.getHoldersCredential(verifiableCredential.getCredentialSubject().get(0), - verifiableCredential.getTypes(), issuerWallet.getDidDocument(), - privateKeyBytes, issuerWallet.getDid(), - verifiableCredential.getContext(), expiryDate, true); + SignerResult signerResult = availableSigningServices.get(issuerWallet.getSigningServiceType()).createCredential(holdersCredentialCreationConfig); + VerifiableCredential vc = (VerifiableCredential) signerResult.getJsonLd(); + HoldersCredential credential = CommonUtils.convertVerifiableCredential(vc,holdersCredentialCreationConfig); + //Store Credential in holder table credential = create(credential); 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 683605f99..e90773600 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialService.java @@ -40,12 +40,17 @@ 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.domain.CredentialCreationConfig; +import org.eclipse.tractusx.managedidentitywallets.domain.SigningServiceType; +import org.eclipse.tractusx.managedidentitywallets.domain.VerifiableEncoding; 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.exception.BadDataException; import org.eclipse.tractusx.managedidentitywallets.exception.DuplicateCredentialProblem; import org.eclipse.tractusx.managedidentitywallets.exception.ForbiddenException; +import org.eclipse.tractusx.managedidentitywallets.signing.SignerResult; +import org.eclipse.tractusx.managedidentitywallets.signing.SigningService; import org.eclipse.tractusx.managedidentitywallets.utils.CommonUtils; import org.eclipse.tractusx.managedidentitywallets.utils.Validate; import org.eclipse.tractusx.ssi.lib.did.resolver.DidResolver; @@ -56,7 +61,7 @@ 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.proof.SignatureType; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.stereotype.Service; @@ -68,7 +73,12 @@ import java.net.http.HttpClient; import java.time.Instant; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; /** * The type Issuers credential service. @@ -87,29 +97,29 @@ public class IssuersCredentialService extends BaseService credentialSpecificationUtil; - private final WalletKeyService walletKeyService; - private final HoldersCredentialRepository holdersCredentialRepository; private final CommonService commonService; + private Map availableSigningServices; + + /** * Instantiates a new Issuers credential service. * * @param issuersCredentialRepository the issuers credential repository * @param miwSettings the miw settings * @param credentialSpecificationUtil the credential specification util - * @param walletKeyService the wallet key service * @param holdersCredentialRepository the holders credential repository * @param commonService the common service */ public IssuersCredentialService(IssuersCredentialRepository issuersCredentialRepository, MIWSettings miwSettings, SpecificationUtil credentialSpecificationUtil, - WalletKeyService walletKeyService, HoldersCredentialRepository holdersCredentialRepository, CommonService commonService) { + HoldersCredentialRepository holdersCredentialRepository, + CommonService commonService) { this.issuersCredentialRepository = issuersCredentialRepository; this.miwSettings = miwSettings; this.credentialSpecificationUtil = credentialSpecificationUtil; - this.walletKeyService = walletKeyService; this.holdersCredentialRepository = holdersCredentialRepository; this.commonService = commonService; } @@ -190,13 +200,27 @@ 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()); + 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(), StringPool.BPN, holderWallet.getBpn())); - HoldersCredential holdersCredential = CommonUtils.getHoldersCredential(verifiableCredentialSubject, - types, baseWallet.getDidDocument(), privateKeyBytes, holderWallet.getDid(), miwSettings.vcContexts(), miwSettings.vcExpiryDate(), authority); + + CredentialCreationConfig holdersCredentialCreationConfig = CredentialCreationConfig.builder() + .encoding(VerifiableEncoding.JSON_LD) + .subject(verifiableCredentialSubject) + .types(types) + .issuerDoc(baseWallet.getDidDocument()) + .holderDid(holderWallet.getDid()) + .contexts(miwSettings.vcContexts()) + .expiryDate(miwSettings.vcExpiryDate()) + .selfIssued(authority) + .keyName(miwSettings.authorityWalletBpn()) + .build(); + + SignerResult result = availableSigningServices.get(baseWallet.getSigningServiceType()).createCredential(holdersCredentialCreationConfig); + VerifiableCredential vc = (VerifiableCredential) result.getJsonLd(); + HoldersCredential holdersCredential = CommonUtils.convertVerifiableCredential(vc, holdersCredentialCreationConfig); //Store Credential in holder wallet holdersCredential = holdersCredentialRepository.save(holdersCredential); @@ -206,7 +230,7 @@ public VerifiableCredential issueBpnCredential(Wallet baseWallet, Wallet holderW issuersCredentialRepository.save(issuersCredential); //update summery VC - updateSummeryCredentials(baseWallet.getDidDocument(), privateKeyBytes, baseWallet.getDid(), holderWallet.getBpn(), holderWallet.getDid(), MIWVerifiableCredentialType.BPN_CREDENTIAL); + updateSummeryCredentials(baseWallet.getDidDocument(), baseWallet.getDid(), holderWallet.getBpn(), holderWallet.getDid(), MIWVerifiableCredentialType.BPN_CREDENTIAL, baseWallet.getSigningServiceType()); log.debug("BPN credential issued for bpn -{}", StringEscapeUtils.escapeJava(holderWallet.getBpn())); @@ -232,8 +256,6 @@ public VerifiableCredential issueFrameworkCredential(IssueFrameworkCredentialReq Wallet baseWallet = commonService.getWalletByIdentifier(miwSettings.authorityWalletBpn()); validateAccess(callerBPN, baseWallet); - // get Key - byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdentifierAsBytes(baseWallet.getId()); //if base wallet issue credentials to itself boolean isSelfIssued = isSelfIssued(holderWallet.getBpn()); @@ -245,7 +267,22 @@ public VerifiableCredential issueFrameworkCredential(IssueFrameworkCredentialReq StringPool.CONTRACT_TEMPLATE, request.getContractTemplate(), StringPool.CONTRACT_VERSION, request.getContractVersion())); List 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); + + CredentialCreationConfig holdersCredentialCreationConfig = CredentialCreationConfig.builder() + .encoding(VerifiableEncoding.JSON_LD) + .subject(subject) + .types(types) + .issuerDoc(baseWallet.getDidDocument()) + .keyName(miwSettings.authorityWalletBpn()) + .holderDid(holderWallet.getDid()) + .contexts(miwSettings.vcContexts()) + .expiryDate(miwSettings.vcExpiryDate()) + .selfIssued(isSelfIssued) + .build(); + + SignerResult result = availableSigningServices.get(baseWallet.getSigningServiceType()).createCredential(holdersCredentialCreationConfig); + VerifiableCredential vc = (VerifiableCredential) result.getJsonLd(); + HoldersCredential holdersCredential = CommonUtils.convertVerifiableCredential(vc, holdersCredentialCreationConfig); //save in holder wallet holdersCredential = holdersCredentialRepository.save(holdersCredential); @@ -255,7 +292,7 @@ public VerifiableCredential issueFrameworkCredential(IssueFrameworkCredentialReq issuersCredential = create(issuersCredential); //update summery cred - updateSummeryCredentials(baseWallet.getDidDocument(), privateKeyBytes, baseWallet.getDid(), holderWallet.getBpn(), holderWallet.getDid(), request.getType()); + updateSummeryCredentials(baseWallet.getDidDocument(), baseWallet.getDid(), holderWallet.getBpn(), holderWallet.getDid(), request.getType(), baseWallet.getSigningServiceType()); log.debug("Framework VC of type ->{} issued to bpn ->{}", StringEscapeUtils.escapeJava(request.getType()), StringEscapeUtils.escapeJava(holderWallet.getBpn())); @@ -284,8 +321,6 @@ public VerifiableCredential issueDismantlerCredential(IssueDismantlerCredentialR //check duplicate isCredentialExit(holderWallet.getDid(), MIWVerifiableCredentialType.DISMANTLER_CREDENTIAL); - byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdentifierAsBytes(issuerWallet.getId()); - //if base wallet issue credentials to itself boolean isSelfIssued = isSelfIssued(request.getBpn()); @@ -295,7 +330,23 @@ public VerifiableCredential issueDismantlerCredential(IssueDismantlerCredentialR StringPool.ACTIVITY_TYPE, request.getActivityType(), StringPool.ALLOWED_VEHICLE_BRANDS, request.getAllowedVehicleBrands() == null ? Collections.emptySet() : request.getAllowedVehicleBrands())); List 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); + + + CredentialCreationConfig holdersCredentialCreationConfig = CredentialCreationConfig.builder() + .encoding(VerifiableEncoding.JSON_LD) + .subject(subject) + .types(types) + .issuerDoc(issuerWallet.getDidDocument()) + .keyName(miwSettings.authorityWalletBpn()) + .holderDid(holderWallet.getDid()) + .contexts(miwSettings.vcContexts()) + .expiryDate(miwSettings.vcExpiryDate()) + .selfIssued(isSelfIssued) + .build(); + + SignerResult result = availableSigningServices.get(issuerWallet.getSigningServiceType()).createCredential(holdersCredentialCreationConfig); + VerifiableCredential vc = (VerifiableCredential) result.getJsonLd(); + HoldersCredential holdersCredential = CommonUtils.convertVerifiableCredential(vc, holdersCredentialCreationConfig); //save in holder wallet @@ -306,7 +357,7 @@ public VerifiableCredential issueDismantlerCredential(IssueDismantlerCredentialR issuersCredential = create(issuersCredential); //update summery VC - updateSummeryCredentials(issuerWallet.getDidDocument(), privateKeyBytes, issuerWallet.getDid(), holderWallet.getBpn(), holderWallet.getDid(), MIWVerifiableCredentialType.DISMANTLER_CREDENTIAL); + updateSummeryCredentials(issuerWallet.getDidDocument(), issuerWallet.getDid(), holderWallet.getBpn(), holderWallet.getDid(), MIWVerifiableCredentialType.DISMANTLER_CREDENTIAL, issuerWallet.getSigningServiceType()); log.debug("Dismantler VC issued to bpn -> {}", StringEscapeUtils.escapeJava(request.getBpn())); @@ -335,7 +386,6 @@ public VerifiableCredential issueMembershipCredential(IssueMembershipCredentialR validateAccess(callerBPN, issuerWallet); - byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdentifierAsBytes(issuerWallet.getId()); List types = List.of(VerifiableCredentialType.VERIFIABLE_CREDENTIAL, VerifiableCredentialType.MEMBERSHIP_CREDENTIAL); //if base wallet issue credentials to itself @@ -348,7 +398,23 @@ public VerifiableCredential issueMembershipCredential(IssueMembershipCredentialR StringPool.MEMBER_OF, issuerWallet.getName(), StringPool.STATUS, "Active", StringPool.START_TIME, Instant.now().toString())); - HoldersCredential holdersCredential = CommonUtils.getHoldersCredential(verifiableCredentialSubject, types, issuerWallet.getDidDocument(), privateKeyBytes, holderWallet.getDid(), miwSettings.vcContexts(), miwSettings.vcExpiryDate(), isSelfIssued); + + + CredentialCreationConfig holdersCredentialCreationConfig = CredentialCreationConfig.builder() + .encoding(VerifiableEncoding.JSON_LD) + .subject(verifiableCredentialSubject) + .types(types) + .issuerDoc(issuerWallet.getDidDocument()) + .keyName(miwSettings.authorityWalletBpn()) + .holderDid(holderWallet.getDid()) + .contexts(miwSettings.vcContexts()) + .expiryDate(miwSettings.vcExpiryDate()) + .selfIssued(isSelfIssued) + .build(); + + SignerResult result = availableSigningServices.get(issuerWallet.getSigningServiceType()).createCredential(holdersCredentialCreationConfig); + VerifiableCredential vc = (VerifiableCredential) result.getJsonLd(); + HoldersCredential holdersCredential = CommonUtils.convertVerifiableCredential(vc, holdersCredentialCreationConfig); //save in holder wallet @@ -360,7 +426,7 @@ public VerifiableCredential issueMembershipCredential(IssueMembershipCredentialR issuersCredential = create(issuersCredential); //update summery VC - updateSummeryCredentials(issuerWallet.getDidDocument(), privateKeyBytes, issuerWallet.getDid(), holderWallet.getBpn(), holderWallet.getDid(), VerifiableCredentialType.MEMBERSHIP_CREDENTIAL); + updateSummeryCredentials(issuerWallet.getDidDocument(), issuerWallet.getDid(), holderWallet.getBpn(), holderWallet.getDid(), VerifiableCredentialType.MEMBERSHIP_CREDENTIAL, issuerWallet.getSigningServiceType()); log.debug("Membership VC issued to bpn ->{}", StringEscapeUtils.escapeJava(issueMembershipCredentialRequest.getBpn())); @@ -391,17 +457,25 @@ public VerifiableCredential issueCredentialUsingBaseWallet(String holderDid, Map validateAccess(callerBpn, issuerWallet); - // get issuer Key - byte[] privateKeyBytes = walletKeyService.getPrivateKeyByWalletIdentifierAsBytes(issuerWallet.getId()); - boolean isSelfIssued = isSelfIssued(holderWallet.getBpn()); + CredentialCreationConfig holdersCredentialCreationConfig = CredentialCreationConfig.builder() + .encoding(VerifiableEncoding.JSON_LD) + .subject(verifiableCredential.getCredentialSubject().get(0)) + .types(verifiableCredential.getTypes()) + .issuerDoc(issuerWallet.getDidDocument()) + .keyName(miwSettings.authorityWalletBpn()) + .holderDid(holderWallet.getDid()) + .contexts(verifiableCredential.getContext()) + .expiryDate(Date.from(verifiableCredential.getExpirationDate())) + .selfIssued(isSelfIssued) + .build(); + + // Create Credential - HoldersCredential holdersCredential = CommonUtils.getHoldersCredential(verifiableCredential.getCredentialSubject().get(0), - verifiableCredential.getTypes(), issuerWallet.getDidDocument(), - privateKeyBytes, - holderWallet.getDid(), - verifiableCredential.getContext(), Date.from(verifiableCredential.getExpirationDate()), isSelfIssued); + SignerResult result = availableSigningServices.get(issuerWallet.getSigningServiceType()).createCredential(holdersCredentialCreationConfig); + VerifiableCredential vc = (VerifiableCredential) result.getJsonLd(); + HoldersCredential holdersCredential = CommonUtils.convertVerifiableCredential(vc, holdersCredentialCreationConfig); //save in holder wallet @@ -468,12 +542,12 @@ private boolean isSelfIssued(String holderBpn) { * Update summery credentials. * * @param issuerDidDocument the issuer did document - * @param issuerPrivateKey the issuer private key + * @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, byte[] issuerPrivateKey, String issuerDid, String holderBpn, String holderDid, String type) { + private void updateSummeryCredentials(DidDocument issuerDidDocument, String issuerDid, String holderBpn, String holderDid, String type, SigningServiceType signingServiceType) { //get last issued summary vc to holder to update items Page filter = getLastIssuedSummaryCredential(issuerDid, holderDid); @@ -522,11 +596,22 @@ private void updateSummeryCredentials(DidDocument issuerDidDocument, byte[] issu StringPool.CONTRACT_TEMPLATE, miwSettings.contractTemplatesUrl())); List types = List.of(VerifiableCredentialType.VERIFIABLE_CREDENTIAL, MIWVerifiableCredentialType.SUMMARY_CREDENTIAL); - HoldersCredential holdersCredential = CommonUtils.getHoldersCredential(subject, types, - issuerDidDocument, - issuerPrivateKey, - holderDid, miwSettings.summaryVcContexts(), miwSettings.vcExpiryDate(), isSelfIssued); + CredentialCreationConfig holdersCredentialCreationConfig = CredentialCreationConfig.builder() + .encoding(VerifiableEncoding.JSON_LD) + .subject(subject) + .types(types) + .issuerDoc(issuerDidDocument) + .keyName(miwSettings.authorityWalletBpn()) + .holderDid(holderDid) + .contexts(miwSettings.summaryVcContexts()) + .expiryDate(miwSettings.vcExpiryDate()) + .selfIssued(isSelfIssued) + .build(); + + SignerResult result = availableSigningServices.get(signingServiceType).createCredential(holdersCredentialCreationConfig); + VerifiableCredential vc = (VerifiableCredential) result.getJsonLd(); + HoldersCredential holdersCredential = CommonUtils.convertVerifiableCredential(vc, holdersCredentialCreationConfig); //save in holder wallet holdersCredentialRepository.save(holdersCredential); @@ -554,4 +639,10 @@ private Page getLastIssuedSummaryCredential(String issuerDid, return filter(filterRequest); } + + @Autowired + public void setKeyService(Map availableKeyStorage) { + this.availableSigningServices = availableKeyStorage; + } + } 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 75739bdaf..b69d5e6cb 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/PresentationService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/PresentationService.java @@ -21,13 +21,11 @@ package org.eclipse.tractusx.managedidentitywallets.service; -import com.ctc.wstx.shaded.msv_core.util.Uri; import com.fasterxml.jackson.databind.ObjectMapper; import com.nimbusds.jwt.SignedJWT; import com.smartsensesolutions.java.commons.base.repository.BaseRepository; import com.smartsensesolutions.java.commons.base.service.BaseService; import com.smartsensesolutions.java.commons.specification.SpecificationUtil; -import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -36,37 +34,34 @@ import org.eclipse.tractusx.managedidentitywallets.dao.entity.HoldersCredential; import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; import org.eclipse.tractusx.managedidentitywallets.dao.repository.HoldersCredentialRepository; +import org.eclipse.tractusx.managedidentitywallets.domain.PresentationCreationConfig; +import org.eclipse.tractusx.managedidentitywallets.domain.SigningServiceType; +import org.eclipse.tractusx.managedidentitywallets.domain.VerifiableEncoding; import org.eclipse.tractusx.managedidentitywallets.exception.BadDataException; +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.x21559.x21559PrivateKey; -import org.eclipse.tractusx.ssi.lib.did.resolver.DidDocumentResolver; import org.eclipse.tractusx.ssi.lib.did.resolver.DidResolver; import org.eclipse.tractusx.ssi.lib.exception.InvalidJsonLdException; -import org.eclipse.tractusx.ssi.lib.exception.InvalidePrivateKeyFormat; import org.eclipse.tractusx.ssi.lib.exception.JwtExpiredException; -import org.eclipse.tractusx.ssi.lib.exception.UnsupportedSignatureTypeException; -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.DidDocument; 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.proof.SignatureType; 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.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; /** * The type Presentation service. @@ -83,12 +78,14 @@ public class PresentationService extends BaseService { private final CommonService commonService; - private final WalletKeyService walletKeyService; private final MIWSettings miwSettings; private final DidDocumentResolverService didDocumentResolverService; + private final Map availableSigningServices; + + @Override protected BaseRepository getRepository() { return holdersCredentialRepository; @@ -108,7 +105,6 @@ protected SpecificationUtil getSpecificationUtil() { * @param callerBpn the caller bpn * @return the map */ - @SneakyThrows({InvalidePrivateKeyFormat.class}) public Map createPresentation(Map data, boolean asJwt, String audience, String callerBpn) { List> verifiableCredentialList = (List>) data.get(StringPool.VERIFIABLE_CREDENTIALS); @@ -121,39 +117,34 @@ public Map createPresentation(Map data, boolean verifiableCredentials.add(verifiableCredential); }); + SigningService keyStorageService = availableSigningServices.get(callerWallet.getSigningServiceType()); + Map response = new HashMap<>(); + Did vpIssuerDid = DidParser.parse(callerWallet.getDid()); + + + PresentationCreationConfig.PresentationCreationConfigBuilder builder = PresentationCreationConfig.builder() + .verifiableCredentials(verifiableCredentials) + .keyName(callerWallet.getBpn()) + .vpIssuerDid(vpIssuerDid); + if (asJwt) { 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()); - - //JWT Factory - SerializedJwtPresentationFactory presentationFactory = new SerializedJwtPresentationFactoryImpl( - new SignedJwtFactory(new OctetKeyPairFactory()), new JsonLdSerializerImpl(), vpIssuerDid); - - //Build JWT - x21559PrivateKey ed25519Key = walletKeyService.getPrivateKeyByWalletIdentifier(callerWallet.getId()); - x21559PrivateKey privateKey = new x21559PrivateKey(ed25519Key.asByte()); - SignedJWT presentation = presentationFactory.createPresentation(vpIssuerDid - , verifiableCredentials, audience, privateKey); - - response.put(StringPool.VP, presentation.serialize()); + builder.encoding(VerifiableEncoding.JWT) + .audience(audience); } else { log.debug("Creating VP as JSON-LD for bpn ->{}", callerBpn); - VerifiablePresentationBuilder verifiablePresentationBuilder = - new VerifiablePresentationBuilder(); - - // Build VP - VerifiablePresentation verifiablePresentation = - verifiablePresentationBuilder - .id(URI.create(miwSettings.authorityWalletDid() + "#" + UUID.randomUUID().toString())) - .type(List.of(VerifiablePresentationType.VERIFIABLE_PRESENTATION)) - .verifiableCredentials(verifiableCredentials) - .build(); - response.put(StringPool.VP, verifiablePresentation); + builder.encoding(VerifiableEncoding.JSON_LD) + .verificationMethod(URI.create(miwSettings.authorityWalletDid() + "#" + UUID.randomUUID().toString())); } + + PresentationCreationConfig presentationConfig = builder.build(); + SignerResult signerResult = keyStorageService.createPresentation(presentationConfig); + + response.put(StringPool.VP, asJwt ? signerResult.getJwt() : signerResult.getJsonLd().toJson()); + return response; } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/WalletService.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/WalletService.java index 3dd1435e9..ae1d76084 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/WalletService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/WalletService.java @@ -21,6 +21,7 @@ package org.eclipse.tractusx.managedidentitywallets.service; +import com.nimbusds.jose.jwk.KeyType; import com.smartsensesolutions.java.commons.FilterRequest; import com.smartsensesolutions.java.commons.base.repository.BaseRepository; import com.smartsensesolutions.java.commons.base.service.BaseService; @@ -34,6 +35,9 @@ import org.apache.commons.text.StringEscapeUtils; import org.bouncycastle.util.io.pem.PemObject; import org.bouncycastle.util.io.pem.PemWriter; +import org.eclipse.tractusx.managedidentitywallets.domain.KeyCreationConfig; +import org.eclipse.tractusx.managedidentitywallets.domain.SigningServiceType; +import org.eclipse.tractusx.managedidentitywallets.signing.SigningService; import org.eclipse.tractusx.managedidentitywallets.config.MIWSettings; import org.eclipse.tractusx.managedidentitywallets.constant.StringPool; import org.eclipse.tractusx.managedidentitywallets.dao.entity.HoldersCredential; @@ -41,16 +45,15 @@ import org.eclipse.tractusx.managedidentitywallets.dao.entity.WalletKey; import org.eclipse.tractusx.managedidentitywallets.dao.repository.HoldersCredentialRepository; import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletRepository; +import org.eclipse.tractusx.managedidentitywallets.domain.KeyStorageType; import org.eclipse.tractusx.managedidentitywallets.dto.CreateWalletRequest; import org.eclipse.tractusx.managedidentitywallets.exception.BadDataException; import org.eclipse.tractusx.managedidentitywallets.exception.DuplicateWalletProblem; import org.eclipse.tractusx.managedidentitywallets.exception.ForbiddenException; import org.eclipse.tractusx.managedidentitywallets.utils.EncryptionUtils; import org.eclipse.tractusx.managedidentitywallets.utils.Validate; -import org.eclipse.tractusx.ssi.lib.crypt.IKeyGenerator; import org.eclipse.tractusx.ssi.lib.crypt.KeyPair; import org.eclipse.tractusx.ssi.lib.crypt.jwk.JsonWebKey; -import org.eclipse.tractusx.ssi.lib.crypt.x21559.x21559Generator; import org.eclipse.tractusx.ssi.lib.did.web.DidWebFactory; import org.eclipse.tractusx.ssi.lib.model.did.*; import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; @@ -92,8 +95,6 @@ public class WalletService extends BaseService { private final EncryptionUtils encryptionUtils; - private final WalletKeyService walletKeyService; - private final HoldersCredentialRepository holdersCredentialRepository; private final SpecificationUtil walletSpecificationUtil; @@ -102,6 +103,8 @@ public class WalletService extends BaseService { private final CommonService commonService; + private final Map availableSigningServices; + @Qualifier("transactionManager") private final PlatformTransactionManager transactionManager; @@ -223,8 +226,19 @@ private Wallet createWallet(CreateWalletRequest request, boolean authority, Stri validateCreateWallet(request, callerBpn); //create private key pair - IKeyGenerator keyGenerator = new x21559Generator(); - KeyPair keyPair = keyGenerator.generateKey(); + SigningServiceType signingServiceType = null; + if (authority) { + signingServiceType = miwSettings.authoritySigningServiceType(); + } else { + signingServiceType = request.getSigningServiceType(); + } + + KeyCreationConfig keyCreationConfig = KeyCreationConfig.builder() + .keyName(request.getBpn()) + .keyType(KeyType.OCT) + .build(); + SigningService signingService = availableSigningServices.get(signingServiceType); + KeyPair keyPair = signingService.getKey(keyCreationConfig); //create did json Did did = DidWebFactory.fromHostnameAndPath(miwSettings.host(), request.getBpn()); @@ -258,11 +272,11 @@ private Wallet createWallet(CreateWalletRequest request, boolean authority, Stri .name(request.getName()) .did(did.toUri().toString()) .algorithm(StringPool.ED_25519) + .signingServiceType(signingServiceType) .build()); - //Save key - walletKeyService.getRepository().save(WalletKey.builder() + signingService.saveKey(WalletKey.builder() .walletId(wallet.getId()) .keyId(keyId) .referenceKey("dummy ref key, removed once vault setup is ready") diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/KeyProvider.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/KeyProvider.java new file mode 100644 index 000000000..ce1922d1d --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/KeyProvider.java @@ -0,0 +1,53 @@ +/* + * ******************************************************************************* + * 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.signing; + +import org.eclipse.tractusx.managedidentitywallets.dao.entity.WalletKey; +import org.eclipse.tractusx.managedidentitywallets.domain.KeyStorageType; + +/** + * This class will be used by LocalSigningService to retrieve and save keys + * + * @see LocalSigningService + */ +public interface KeyProvider { + + /** + * @param keyName the name of the key that is to be retrieved + * @return the key as a byte-array + * + */ + byte[] getPrivateKey(String keyName); + + /** + * @param walletKey the key to save + */ + void saveKeys(WalletKey walletKey); + + + /** + * @return the type of KeyProvider + * + * @see KeyStorageType + */ + KeyStorageType getKeyStorageType(); +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/LocalKeyProvider.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/LocalKeyProvider.java new file mode 100644 index 000000000..df0f37724 --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/LocalKeyProvider.java @@ -0,0 +1,58 @@ +/* + * ******************************************************************************* + * 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.signing; + +import lombok.RequiredArgsConstructor; +import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; +import org.eclipse.tractusx.managedidentitywallets.dao.entity.WalletKey; +import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletKeyRepository; +import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletRepository; +import org.eclipse.tractusx.managedidentitywallets.domain.KeyStorageType; +import org.eclipse.tractusx.managedidentitywallets.service.WalletKeyService; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class LocalKeyProvider implements KeyProvider { + + private final WalletKeyService walletKeyService; + + private final WalletKeyRepository walletKeyRepository; + + private final WalletRepository walletRepository; + + @Override + public byte[] getPrivateKey(String keyName) { // + Wallet wallet = walletRepository.getByBpn(keyName); + return walletKeyService.getPrivateKeyByWalletIdentifierAsBytes(wallet.getId()); + } + + @Override + public void saveKeys(WalletKey walletKey) { + walletKeyRepository.save(walletKey); + } + + @Override + public KeyStorageType getKeyStorageType() { + return KeyStorageType.DB; + } +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/LocalSigningService.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/LocalSigningService.java new file mode 100644 index 000000000..ae533e6be --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/LocalSigningService.java @@ -0,0 +1,36 @@ +/* + * ******************************************************************************* + * 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.signing; + +/** + * Specialized interface for SigningServices that will sign credentials/presentations locally + * (may retrieve the keys from remote via KeyProvider) + * + * @see SigningService + * @see KeyProvider + */ +public interface LocalSigningService extends SigningService{ + /** + * @param keyProvider the KeyProvider to be used by the implementation + */ + void setKeyProvider(KeyProvider keyProvider); +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/LocalSigningServiceImpl.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/LocalSigningServiceImpl.java new file mode 100644 index 000000000..8a5255485 --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/LocalSigningServiceImpl.java @@ -0,0 +1,217 @@ +/* + * ******************************************************************************* + * 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.signing; + +import com.nimbusds.jose.jwk.KeyType; +import com.nimbusds.jwt.SignedJWT; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import org.apache.commons.lang3.NotImplementedException; +import org.eclipse.tractusx.managedidentitywallets.constant.StringPool; +import org.eclipse.tractusx.managedidentitywallets.dao.entity.WalletKey; +import org.eclipse.tractusx.managedidentitywallets.domain.CredentialCreationConfig; +import org.eclipse.tractusx.managedidentitywallets.domain.KeyCreationConfig; +import org.eclipse.tractusx.managedidentitywallets.domain.PresentationCreationConfig; +import org.eclipse.tractusx.managedidentitywallets.domain.SigningServiceType; +import org.eclipse.tractusx.managedidentitywallets.domain.VerifiableEncoding; +import org.eclipse.tractusx.ssi.lib.crypt.IKeyGenerator; +import org.eclipse.tractusx.ssi.lib.crypt.KeyPair; +import org.eclipse.tractusx.ssi.lib.crypt.octet.OctetKeyPairFactory; +import org.eclipse.tractusx.ssi.lib.crypt.x21559.x21559Generator; +import org.eclipse.tractusx.ssi.lib.crypt.x21559.x21559PrivateKey; +import org.eclipse.tractusx.ssi.lib.exception.InvalidePrivateKeyFormat; +import org.eclipse.tractusx.ssi.lib.exception.KeyGenerationException; +import org.eclipse.tractusx.ssi.lib.exception.UnsupportedSignatureTypeException; +import org.eclipse.tractusx.ssi.lib.jwt.SignedJwtFactory; +import org.eclipse.tractusx.ssi.lib.model.JsonLdObject; +import org.eclipse.tractusx.ssi.lib.model.proof.Proof; +import org.eclipse.tractusx.ssi.lib.model.proof.jws.JWSSignature2020; +import org.eclipse.tractusx.ssi.lib.model.verifiable.Verifiable; +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredentialBuilder; +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.LinkedDataProofGenerator; +import org.eclipse.tractusx.ssi.lib.proof.SignatureType; +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.springframework.stereotype.Component; + +import java.net.URI; +import java.time.Instant; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@Component +public class LocalSigningServiceImpl implements LocalSigningService { + + private KeyProvider keyProvider; + + @Override + public SignerResult createCredential(CredentialCreationConfig config) { + byte[] privateKeyBytes = keyProvider.getPrivateKey(config.getKeyName()); + 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"); + default -> + throw new IllegalArgumentException("encoding %s is not supported".formatted(config.getEncoding())); + + } + } + + @Override + public KeyPair getKey(KeyCreationConfig config) throws KeyGenerationException { + KeyType keyType = Objects.requireNonNull(config.getKeyType()); + switch (keyType.getValue().toUpperCase()) { + case "EC", "RSA" -> + throw new NotImplementedException("%s is not implemented yet".formatted(keyType.toString())); + case "OCT" -> { + IKeyGenerator keyGenerator = new x21559Generator(); + return keyGenerator.generateKey(); + } + default -> throw new IllegalArgumentException("%s is not supported".formatted(keyType.toString())); + } + + } + + @Override + public SigningServiceType getSupportedServiceType() { + return SigningServiceType.LOCAL; + } + + @Override + public SignerResult createPresentation(PresentationCreationConfig config) { + byte[] privateKeyBytes = keyProvider.getPrivateKey(config.getKeyName()); + VerifiableEncoding encoding = Objects.requireNonNull(config.getEncoding()); + SignerResult.SignerResultBuilder resultBuilder = SignerResult.builder().encoding(encoding); + switch (config.getEncoding()) { + case JWT -> { + return resultBuilder.jwt(generateJwtPresentation(config, privateKeyBytes).serialize()).build(); + } + case JSON_LD -> { + try { + return resultBuilder.jsonLd(generateJsonLdPresentation(config, privateKeyBytes)).build(); + } catch (UnsupportedSignatureTypeException | InvalidePrivateKeyFormat e) { + throw new IllegalStateException(e); + } + } + default -> + throw new IllegalArgumentException("encoding %s is not supported".formatted(config.getEncoding())); + } + } + + @Override + public void setKeyProvider(KeyProvider keyProvider) { + this.keyProvider = Objects.requireNonNull(keyProvider); + } + + @Override + public void saveKey(WalletKey key) { + keyProvider.saveKeys(key); + } + + private SignedJWT generateJwtPresentation(PresentationCreationConfig config, byte[] privateKeyBytes) { + SerializedJwtPresentationFactory presentationFactory = new SerializedJwtPresentationFactoryImpl( + new SignedJwtFactory(new OctetKeyPairFactory()), new JsonLdSerializerImpl(), config.getVpIssuerDid()); + + x21559PrivateKey privateKey = null; + try { + privateKey = new x21559PrivateKey(privateKeyBytes); + } catch (InvalidePrivateKeyFormat e) { + throw new IllegalArgumentException(e); + } + return presentationFactory.createPresentation(config.getVpIssuerDid() + , config.getVerifiableCredentials(), config.getAudience(), privateKey); + } + + private VerifiablePresentation generateJsonLdPresentation(PresentationCreationConfig config, byte[] privateKeyBytes) throws UnsupportedSignatureTypeException, InvalidePrivateKeyFormat { + VerifiablePresentationBuilder verifiablePresentationBuilder = + new VerifiablePresentationBuilder().id(URI.create(config.getVpIssuerDid() + "#" + UUID.randomUUID().toString())) + .type(List.of(VerifiablePresentationType.VERIFIABLE_PRESENTATION)) + .verifiableCredentials(config.getVerifiableCredentials()); + + + VerifiablePresentation verifiablePresentation = verifiablePresentationBuilder.build(); + List contexts = verifiablePresentation.getContext().stream().map(URI::toString).collect(Collectors.toList()); + if (!contexts.contains(StringPool.W3_ID_JWS_2020_V1_CONTEXT_URL)) { + contexts.add(StringPool.W3_ID_JWS_2020_V1_CONTEXT_URL); + } + verifiablePresentation.put(JsonLdObject.CONTEXT, contexts); + LinkedDataProofGenerator generator = LinkedDataProofGenerator.newInstance(SignatureType.JWS); + + x21559PrivateKey privateKey = new x21559PrivateKey(privateKeyBytes); + + Proof proof = generator.createProof(verifiablePresentation, config.getVerificationMethod(), + privateKey); + verifiablePresentation.put(Verifiable.PROOF, proof); + return verifiablePresentation; + } + + @SneakyThrows({ UnsupportedSignatureTypeException.class, InvalidePrivateKeyFormat.class }) + private static org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential createVerifiableCredential(CredentialCreationConfig config, byte[] privateKeyBytes) { + //VC Builder + + // if the credential does not contain the JWS proof-context add it + URI jwsUri = URI.create("https://w3id.org/security/suites/jws-2020/v1"); + if (!config.getContexts().contains(jwsUri)) { + config.getContexts().add(jwsUri); + } + + // check if the expiryDate is set + // if its null then it will be ignored from the SSI Lib (VerifiableCredentialBuilder) and will not be added to the VC + Instant expiryInstant = config.getExpiryDate().toInstant(); + + + URI id = URI.create(UUID.randomUUID().toString()); + VerifiableCredentialBuilder builder = new VerifiableCredentialBuilder() + .context(config.getContexts()) + .id(URI.create(config.getIssuerDoc().getId() + "#" + id)) + .type(config.getTypes()) + .issuer(config.getIssuerDoc().getId()) + .expirationDate(expiryInstant) + .issuanceDate(Instant.now()) + .credentialSubject(config.getSubject()); + + + LinkedDataProofGenerator generator = LinkedDataProofGenerator.newInstance(SignatureType.JWS); + URI verificationMethod = config.getIssuerDoc().getVerificationMethods().get(0).getId(); + + JWSSignature2020 proof = + (JWSSignature2020) generator.createProof(builder.build(), verificationMethod, new x21559PrivateKey(privateKeyBytes)); + + + //Adding Proof to VC + builder.proof(proof); + + //Create Credential + return builder.build(); + } + +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/SignerResult.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/SignerResult.java new file mode 100644 index 000000000..4db8e99ca --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/SignerResult.java @@ -0,0 +1,37 @@ +/* + * ******************************************************************************* + * 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.signing; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.eclipse.tractusx.managedidentitywallets.domain.VerifiableEncoding; +import org.eclipse.tractusx.ssi.lib.model.verifiable.Verifiable; + +@Getter +@Setter +@Builder +public class SignerResult { + private VerifiableEncoding encoding; + private Verifiable jsonLd; + private String jwt; +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/SigningService.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/SigningService.java new file mode 100644 index 000000000..21915702e --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/signing/SigningService.java @@ -0,0 +1,75 @@ +/* + * ******************************************************************************* + * 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.signing; + +import org.eclipse.tractusx.managedidentitywallets.dao.entity.WalletKey; +import org.eclipse.tractusx.managedidentitywallets.domain.CredentialCreationConfig; +import org.eclipse.tractusx.managedidentitywallets.domain.KeyCreationConfig; +import org.eclipse.tractusx.managedidentitywallets.domain.PresentationCreationConfig; +import org.eclipse.tractusx.managedidentitywallets.domain.SigningServiceType; +import org.eclipse.tractusx.ssi.lib.crypt.KeyPair; +import org.eclipse.tractusx.ssi.lib.exception.KeyGenerationException; + +/** + * Service used to sign the verifiable credentials and verifiable presentations + */ +public interface SigningService { + /** + * @param config the configuration for creating the credential + * @return SignerResult containing the signed credential + * + * @see CredentialCreationConfig + * @see SignerResult + */ + SignerResult createCredential(CredentialCreationConfig config); + + /** + * @param config the config for creating/retrieving the key + * @return KeyPair containing the public and private key (private key depends on the type of signing service used) + * @throws KeyGenerationException when something goes wrong + * + * @see KeyPair + * @see KeyCreationConfig + */ + KeyPair getKey(KeyCreationConfig config) throws KeyGenerationException; + + /** + * @param key the key to be saved, LocalSigningService implementations may call KeyProvider.saveKey + * + * @see KeyProvider + */ + void saveKey(WalletKey key); + + /** + * @return the implementation's supported type + */ + SigningServiceType getSupportedServiceType(); + + /** + * @param config the configuration for creating the presentation + * @return SignerResult containing the signed presentation + * + * @see PresentationCreationConfig + * @see SignerResult + */ + SignerResult createPresentation(PresentationCreationConfig config); +} 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 13668bf5e..0b25ba7c1 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/CommonUtils.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/CommonUtils.java @@ -21,29 +21,16 @@ package org.eclipse.tractusx.managedidentitywallets.utils; -import lombok.SneakyThrows; import lombok.experimental.UtilityClass; import org.eclipse.tractusx.managedidentitywallets.constant.StringPool; import org.eclipse.tractusx.managedidentitywallets.dao.entity.HoldersCredential; +import org.eclipse.tractusx.managedidentitywallets.domain.CredentialCreationConfig; import org.eclipse.tractusx.managedidentitywallets.exception.BadDataException; -import org.eclipse.tractusx.ssi.lib.crypt.x21559.x21559PrivateKey; -import org.eclipse.tractusx.ssi.lib.exception.InvalidePrivateKeyFormat; -import org.eclipse.tractusx.ssi.lib.exception.UnsupportedSignatureTypeException; -import org.eclipse.tractusx.ssi.lib.model.did.DidDocument; -import org.eclipse.tractusx.ssi.lib.model.proof.jws.JWSSignature2020; 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.model.verifiable.credential.VerifiableCredentialType; -import org.eclipse.tractusx.ssi.lib.proof.LinkedDataProofGenerator; -import org.eclipse.tractusx.ssi.lib.proof.SignatureType; -import java.net.URI; -import java.time.Instant; import java.util.ArrayList; -import java.util.Date; import java.util.List; -import java.util.UUID; import java.util.regex.Pattern; /** @@ -54,7 +41,6 @@ public class CommonUtils { public static final Pattern BPN_NUMBER_PATTERN = Pattern.compile(StringPool.BPN_NUMBER_REGEX); - /** * Gets identifier type. * @@ -70,79 +56,19 @@ public static String getIdentifierType(String identifier) { } } - - /** - * Gets credential. - * - * @param subject the subject - * @param types the types - * @param issuerDoc the issuer doc - * @param privateKeyBytes the private key bytes - * @param holderDid the holder did - * @return the credential - */ - public static HoldersCredential getHoldersCredential(VerifiableCredentialSubject subject, List types, DidDocument issuerDoc, - byte[] privateKeyBytes, String holderDid, List contexts, Date expiryDate, boolean selfIssued) { - List cloneTypes = new ArrayList<>(types); - - // Create VC - VerifiableCredential verifiableCredential = createVerifiableCredential(issuerDoc, types, - subject, privateKeyBytes, contexts, expiryDate); - + public static HoldersCredential convertVerifiableCredential(VerifiableCredential verifiableCredential, CredentialCreationConfig config) { + List cloneTypes = new ArrayList<>(config.getTypes()); cloneTypes.remove(VerifiableCredentialType.VERIFIABLE_CREDENTIAL); // Create Credential return HoldersCredential.builder() - .holderDid(holderDid) - .issuerDid(issuerDoc.getId().toString()) + .holderDid(config.getHolderDid()) + .issuerDid(config.getIssuerDoc().getId().toString()) .type(String.join(",", cloneTypes)) .credentialId(verifiableCredential.getId().toString()) .data(verifiableCredential) - .selfIssued(selfIssued) + .selfIssued(config.isSelfIssued()) .build(); } - @SneakyThrows({UnsupportedSignatureTypeException.class, InvalidePrivateKeyFormat.class}) - private static VerifiableCredential createVerifiableCredential(DidDocument issuerDoc, List verifiableCredentialType, - VerifiableCredentialSubject verifiableCredentialSubject, - byte[] privateKey, List contexts, Date expiryDate) { - //VC Builder - - // if the credential does not contain the JWS proof-context add it - URI jwsUri = URI.create("https://w3id.org/security/suites/jws-2020/v1"); - if (!contexts.contains(jwsUri)) { - contexts.add(jwsUri); - } - - // check if the expiryDate is set - // if its null then it will be ignored from the SSI Lib (VerifiableCredentialBuilder) and will not be added to the VC - Instant expiryInstant = null; - if (expiryDate != null) { - expiryInstant = expiryDate.toInstant(); - } - - URI id = URI.create(UUID.randomUUID().toString()); - VerifiableCredentialBuilder builder = new VerifiableCredentialBuilder() - .context(contexts) - .id(URI.create(issuerDoc.getId() + "#" + id)) - .type(verifiableCredentialType) - .issuer(issuerDoc.getId()) - .expirationDate(expiryInstant) - .issuanceDate(Instant.now()) - .credentialSubject(verifiableCredentialSubject); - - - LinkedDataProofGenerator generator = LinkedDataProofGenerator.newInstance(SignatureType.JWS); - URI verificationMethod = issuerDoc.getVerificationMethods().get(0).getId(); - - JWSSignature2020 proof = - (JWSSignature2020) generator.createProof(builder.build(), verificationMethod, new x21559PrivateKey(privateKey)); - - - //Adding Proof to VC - builder.proof(proof); - - //Create Credential - return builder.build(); - } } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 269aab7ba..fcc27ec5e 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,3 +1,4 @@ + server: port: ${APPLICATION_PORT:8087} shutdown: graceful @@ -75,6 +76,8 @@ miw: authorityWalletBpn: ${AUTHORITY_WALLET_BPN:BPNL000000000000} authorityWalletName: ${AUTHORITY_WALLET_NAME:Catena-X} authorityWalletDid: ${AUTHORITY_WALLET_DID:did:web:localhost:BPNL000000000000} + authoritySigningServiceType: ${AUTHORITY_SIGNING_SERVICE_TYPE:LOCAL} + localSigningKeyStorageType: ${LOCAL_SIGNING_KEY_STORAGE_TYPE:DB} vcContexts: ${VC_SCHEMA_LINK:https://www.w3.org/2018/credentials/v1, https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json} summaryVcContexts: ${SUMMARY_VC_SCHEMA_LINK:https://www.w3.org/2018/credentials/v1, https://catenax-ng.github.io/product-core-schemas/SummaryVC.json} vcExpiryDate: ${VC_EXPIRY_DATE:01-10-2023} #dd-MM-yyyy ie. 01-01-2025 expiry date will be 2024-12-31T18:30:00Z in VC @@ -89,4 +92,4 @@ miw: auth-server-url: ${AUTH_SERVER_URL:http://localhost:8081} auth-url: ${miw.security.auth-server-url}/realms/${miw.security.realm}/protocol/openid-connect/auth token-url: ${miw.security.auth-server-url}/realms/${miw.security.realm}/protocol/openid-connect/token - refresh-token-url: ${miw.security.token-url} \ No newline at end of file + refresh-token-url: ${miw.security.token-url} diff --git a/src/main/resources/db/changelog/changes/init.sql b/src/main/resources/db/changelog/changes/init.sql index d6b396fc6..9e39d47e5 100644 --- a/src/main/resources/db/changelog/changes/init.sql +++ b/src/main/resources/db/changelog/changes/init.sql @@ -77,4 +77,7 @@ COMMENT ON TABLE public.holders_credential IS 'This table will store holders cre COMMENT ON COLUMN public.holders_credential.is_stored IS 'true is VC is stored using store VC api(Not issued by MIW)'; --changeset nitin:2 -ALTER TABLE public.wallet_key ADD key_id varchar(255) NULL; \ No newline at end of file +ALTER TABLE public.wallet_key ADD key_id varchar(255) NULL; + +--changeset pmanaras:3 +ALTER TABLE public.wallet ADD signing_service_type VARCHAR(255) NOT NULL DEFAULT 'LOCAL'; diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/domain/CredentialCreationConfigTest.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/domain/CredentialCreationConfigTest.java new file mode 100644 index 000000000..c7508b635 --- /dev/null +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/domain/CredentialCreationConfigTest.java @@ -0,0 +1,154 @@ +/* + * ******************************************************************************* + * 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.domain; + +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.verifiable.credential.VerifiableCredentialStatus; +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredentialSubject; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mockito; + +import java.net.URI; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class CredentialCreationConfigTest { + + @Test + void shouldBuildWithRequiredAttributes() { + CredentialCreationConfig build = assertDoesNotThrow(() -> CredentialCreationConfig.builder() + .encoding(VerifiableEncoding.JSON_LD) + .expiryDate(new Date()) + .subject(mockCredentialSubject()) + .types(Collections.emptyList()) + .issuerDoc(Mockito.mock(DidDocument.class)) + .holderDid(Mockito.mock(Did.class).toString()) + .contexts(Collections.emptyList()) + .verifiableCredentialStatus(Mockito.mock(VerifiableCredentialStatus.class)) + .vcId(URI.create("yada://test.com")) + .keyName("keyName") + .build()); + assertNotNull(build); + assertNotNull(build.getExpiryDate()); + assertNotNull(build.getSubject()); + assertNotNull(build.getTypes()); + assertNotNull(build.getIssuerDoc()); + assertNotNull(build.getHolderDid()); + assertNotNull(build.getContexts()); + assertNotNull(build.getVerifiableCredentialStatus()); + assertNotNull(build.getVcId()); + assertNotNull(build.getKeyName()); + assertNotNull(build.getEncoding()); + assertFalse(build.isSelfIssued()); + } + + @Test + void shouldBuildWhenVcIdIsString() { + + CredentialCreationConfig build = assertDoesNotThrow(() -> CredentialCreationConfig.builder() + .encoding(VerifiableEncoding.JSON_LD) + .expiryDate(new Date()) + .subject(mockCredentialSubject()) + .types(Collections.emptyList()) + .issuerDoc(Mockito.mock(DidDocument.class)) + .holderDid(Mockito.mock(Did.class).toString()) + .contexts(Collections.emptyList()) + .verifiableCredentialStatus(Mockito.mock(VerifiableCredentialStatus.class)) + .keyName("keyName") + .build()); + } + + @ParameterizedTest + @MethodSource("testConfigs") + void shouldThrowIfRequiredAttributesMissing(TestConfig conf) { + assertThrows(NullPointerException.class, () -> CredentialCreationConfig + .builder().expiryDate(conf.expiryDate) + .subject(conf.subject) + .types(conf.types) + .issuerDoc(conf.issuerDoc) + .holderDid(conf.holderDid) + .contexts(conf.contexts) + .encoding(conf.encoding) + .keyName(conf.keyName)); + + + } + + @Test + void shouldThrowWhenSettingIllegalVcId() { + CredentialCreationConfig.CredentialCreationConfigBuilder builder = CredentialCreationConfig.builder(); + assertThrows(IllegalArgumentException.class, () -> builder.vcId(42)); + } + + @Test + void shouldNotThrowWhenVcIdValid(){ + CredentialCreationConfig.CredentialCreationConfigBuilder builder = CredentialCreationConfig.builder(); + assertDoesNotThrow(() -> builder.vcId("https://test.com")); + assertDoesNotThrow(() -> builder.vcId(URI.create("https://test.com"))); + } + + private static Stream testConfigs() { + return Stream.of( + Arguments.of(new TestConfig(null, null, null, null, null, null, null, null, null)), + Arguments.of(new TestConfig(mockCredentialSubject(), null, null, null, null, null, null, null, null)), + Arguments.of(new TestConfig(mockCredentialSubject(), Collections.emptyList(), null, null, null, null, null, null, null)), + Arguments.of(new TestConfig(mockCredentialSubject(), Collections.emptyList(), new byte[]{}, null, null, null, null, null, null)), + Arguments.of(new TestConfig(mockCredentialSubject(), Collections.emptyList(), new byte[]{}, Mockito.mock(DidDocument.class), null, null, null, null, null)), + Arguments.of(new TestConfig(mockCredentialSubject(), Collections.emptyList(), new byte[]{}, Mockito.mock(DidDocument.class), Mockito.mock(Did.class).toString(), null, null, null, null)), + Arguments.of(new TestConfig(mockCredentialSubject(), Collections.emptyList(), new byte[]{}, Mockito.mock(DidDocument.class), Mockito.mock(Did.class).toString(), Collections.emptyList(), null, null, null)) + ); + } + + private record TestConfig( + VerifiableCredentialSubject subject, + List types, + byte[] privateKey, + DidDocument issuerDoc, + String holderDid, + List contexts, + Date expiryDate, + + String keyName, + + VerifiableEncoding encoding + + ) { + } + + + private static VerifiableCredentialSubject mockCredentialSubject() { + return new VerifiableCredentialSubject(Map.of("id", "42")); + } + +} diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/migration/SetSigningServiceTypeToExistingWalletsTest.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/migration/SetSigningServiceTypeToExistingWalletsTest.java new file mode 100644 index 000000000..fcfc5eccf --- /dev/null +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/migration/SetSigningServiceTypeToExistingWalletsTest.java @@ -0,0 +1,132 @@ +/* + * ******************************************************************************* + * 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.migration; + +import liquibase.Liquibase; +import liquibase.database.Database; +import liquibase.database.DatabaseFactory; +import liquibase.database.jvm.JdbcConnection; +import liquibase.resource.ClassLoaderResourceAccessor; +import lombok.SneakyThrows; +import org.h2.command.query.Select; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.Statement; +import java.sql.Timestamp; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class SetSigningServiceTypeToExistingWalletsTest { + public static final int EXPECTED_WALLET_COUNT = 5; + private static Database database; + + @BeforeAll + @SneakyThrows + public static void beforeAll() { + Connection conn = DriverManager.getConnection( + "jdbc:h2:mem:framework_test;INIT=CREATE SCHEMA IF NOT EXISTS migration", + "admin", + "password"); + + database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(conn)); + } + + @SneakyThrows + @Test + void migrateWallets() { + var connection = (JdbcConnection) database.getConnection(); + + // 1. apply changelog without signing service-type + Liquibase liquibase = new Liquibase("db/signing-service-migration-test/without-changes.xml", new ClassLoaderResourceAccessor(), database); + liquibase.update((String) null); + + // assert that column for signing_service_type does not exist + + List columns = getColumnList(connection); + assertFalse(columns.contains("signing_service_type".toUpperCase())); + + // insert Wallets + insertWallets(connection); + + // assert that there are 5 Wallets created + String sqlCount = "SELECT count(*) as count FROM public.wallet"; + Statement st = connection.createStatement(); + ResultSet count = st.executeQuery(sqlCount); + assertTrue(count.next()); + assertEquals(EXPECTED_WALLET_COUNT, count.getInt("count")); + + // run migration + Liquibase migrate = new Liquibase("db/signing-service-migration-test/signing-service-changelog.xml", new ClassLoaderResourceAccessor(), database); + migrate.update((String) null); + + // assert that column was created + List newColumns = getColumnList(connection); + assertTrue(newColumns.contains("signing_service_type".toUpperCase())); + + // assert that every wallet now has signing_service_type = LOCAL by default + String walletSql = "SELECT * FROM public.wallet"; + Statement walletStatement = connection.createStatement(); + ResultSet walletResult = walletStatement.executeQuery(walletSql); + while(walletResult.next()){ + assertEquals("LOCAL", walletResult.getString("signing_service_type".toUpperCase())); + } + } + + @SneakyThrows + private List getColumnList(JdbcConnection connection){ + String selectColumns = "SHOW COLUMNS FROM public.wallet"; + // COLUMN_NAME | TYPE | IS_NULLABLE | KEY | DEFAULT + ResultSet resultSet = connection.createStatement().executeQuery(selectColumns); + List columns = new ArrayList<>(); + while (resultSet.next()) { + columns.add(resultSet.getString("COLUMN_NAME")); + } + return columns; + } + + @SneakyThrows + private void insertWallets(JdbcConnection connection) { + String insert = "INSERT INTO wallet(id,name,did,bpn,algorithm,did_document,created_at) VALUES(?,?,?,?,?,?,?)"; + PreparedStatement pst = connection.prepareStatement(insert); + + for (int i = 1; i <= EXPECTED_WALLET_COUNT; i++) { + pst.setInt(1, i); + pst.setString(2, "name"+i); + pst.setString(3, "did"+i); + pst.setString(4, "bpn"+i); + pst.setString(5, "algorithm"+i); + pst.setString(6, "document"+i); + pst.setTimestamp(7, Timestamp.from(Instant.now())); + pst.execute(); + } + } + +} diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/TestUtils.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/TestUtils.java index d078b4938..52d1520e7 100644 --- a/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/TestUtils.java +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/TestUtils.java @@ -34,6 +34,8 @@ import org.eclipse.tractusx.managedidentitywallets.dao.repository.HoldersCredentialRepository; import org.eclipse.tractusx.managedidentitywallets.dao.repository.IssuersCredentialRepository; import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletRepository; +import org.eclipse.tractusx.managedidentitywallets.domain.KeyStorageType; +import org.eclipse.tractusx.managedidentitywallets.domain.SigningServiceType; import org.eclipse.tractusx.managedidentitywallets.dto.CreateWalletRequest; import org.eclipse.tractusx.managedidentitywallets.dto.IssueFrameworkCredentialRequest; import org.eclipse.tractusx.managedidentitywallets.dto.IssueMembershipCredentialRequest; @@ -91,6 +93,7 @@ public static Wallet createWallet(String bpn, String did, WalletRepository walle .didDocument(DidDocument.fromJson(didDocument)) .algorithm(StringPool.ED_25519) .name(bpn) + .signingServiceType(SigningServiceType.LOCAL) .build(); return walletRepository.save(wallet); } diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/DismantlerHoldersCredentialTest.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/DismantlerHoldersCredentialTest.java index 37dec0b5d..3ad6216ee 100644 --- a/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/DismantlerHoldersCredentialTest.java +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/DismantlerHoldersCredentialTest.java @@ -229,4 +229,4 @@ private ResponseEntity issueDismantlerCredential(String bpn, String did) return restTemplate.exchange(RestURI.CREDENTIALS_ISSUER_DISMANTLER, HttpMethod.POST, entity, String.class); } -} \ No newline at end of file +} diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/FrameworkHoldersCredentialTest.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/FrameworkHoldersCredentialTest.java index 21e0ab498..f3840507f 100644 --- a/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/FrameworkHoldersCredentialTest.java +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/FrameworkHoldersCredentialTest.java @@ -231,4 +231,4 @@ private void validate(Wallet wallet, String type, ResponseEntity respons //check summary credential TestUtils.checkSummaryCredential(miwSettings.authorityWalletDid(), wallet.getDid(), holdersCredentialRepository, issuersCredentialRepository, type, oldSummaryCredentialId); } -} \ No newline at end of file +} diff --git a/src/test/resources/db/changelog/changes/add-signing-service-column.sql b/src/test/resources/db/changelog/changes/add-signing-service-column.sql new file mode 100644 index 000000000..09cd2c8c1 --- /dev/null +++ b/src/test/resources/db/changelog/changes/add-signing-service-column.sql @@ -0,0 +1,3 @@ +--liquibase formatted sql +--changeset pmanaras:3 +ALTER TABLE public.wallet ADD signing_service_type VARCHAR(255) NOT NULL DEFAULT 'LOCAL'; diff --git a/src/test/resources/db/changelog/changes/without-changes-init.sql b/src/test/resources/db/changelog/changes/without-changes-init.sql new file mode 100644 index 000000000..62c250700 --- /dev/null +++ b/src/test/resources/db/changelog/changes/without-changes-init.sql @@ -0,0 +1,80 @@ +--liquibase formatted sql + +--changeset nitin:1 +CREATE TABLE IF NOT EXISTS public.wallet +( + id bigserial NOT NULL, + name varchar(255) NOT NULL, + did varchar(255) NOT NULL, + bpn varchar(255) NOT NULL, + algorithm varchar(255) NOT NULL DEFAULT 'ED25519'::character varying, + did_document text NOT NULL, + created_at timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + modified_at timestamp(6) NULL, + modified_from varchar(255) NULL, + CONSTRAINT uk_bpn UNIQUE (bpn), + CONSTRAINT uk_did UNIQUE (did), + CONSTRAINT wallet_pkey PRIMARY KEY (id), + CONSTRAINT wallet_fk FOREIGN KEY (modified_from) REFERENCES public.wallet (bpn) ON DELETE SET NULL +); +COMMENT ON TABLE public.wallet IS 'This table will store wallets'; + +CREATE TABLE IF NOT EXISTS public.wallet_key +( + id bigserial NOT NULL, + wallet_id bigserial NOT NULL, + vault_access_token varchar(1000) NOT NULL, + reference_key varchar(255) NOT NULL, + private_key text NOT NULL, + public_key text NOT NULL, + created_at timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + modified_at timestamp(6) NULL, + modified_from varchar(255) NULL, + CONSTRAINT wallet_key_pkey PRIMARY KEY (id), + CONSTRAINT wallet_fk_2 FOREIGN KEY (wallet_id) REFERENCES public.wallet (id) ON DELETE CASCADE, + CONSTRAINT wallet_key_fk FOREIGN KEY (modified_from) REFERENCES public.wallet (bpn) ON DELETE CASCADE +); +COMMENT ON TABLE public.wallet_key IS 'This table will store key pair of wallets'; + + +CREATE TABLE IF NOT EXISTS public.issuers_credential +( + id bigserial NOT NULL, + holder_did varchar(255) NOT NULL, + issuer_did varchar(255) NOT NULL, + credential_id varchar(255) NOT NULL, + credential_data text NOT NULL, + credential_type varchar(255) NULL, + created_at timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + modified_at timestamp(6) NULL, + modified_from varchar(255) NULL, + CONSTRAINT issuers_credential_pkey PRIMARY KEY (id), + CONSTRAINT issuers_credential_fk FOREIGN KEY (modified_from) REFERENCES public.wallet (bpn) ON DELETE SET NULL, + CONSTRAINT issuers_credential_holder_wallet_fk FOREIGN KEY (holder_did) REFERENCES public.wallet (did) ON DELETE CASCADE +); +COMMENT ON TABLE public.issuers_credential IS 'This table will store issuers credentials'; + + +CREATE TABLE IF NOT EXISTS public.holders_credential +( + id bigserial NOT NULL, + holder_did varchar(255) NOT NULL, + issuer_did varchar(255) NOT NULL, + credential_id varchar(255) NOT NULL, + credential_data text NOT NULL, + credential_type varchar(255) NULL, + is_self_issued bool NOT null default false, + is_stored bool NOT null default false, + created_at timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + modified_at timestamp(6) NULL, + modified_from varchar(255) NULL, + CONSTRAINT holders_credential_pkey PRIMARY KEY (id), + CONSTRAINT holders_credential_fk FOREIGN KEY (modified_from) REFERENCES public.wallet (bpn) ON DELETE SET NULL, + CONSTRAINT holders_credential_holder_wallet_fk FOREIGN KEY (holder_did) REFERENCES public.wallet (did) ON DELETE CASCADE +); +COMMENT ON TABLE public.holders_credential IS 'This table will store holders credentials'; + +COMMENT ON COLUMN public.holders_credential.is_stored IS 'true is VC is stored using store VC api(Not issued by MIW)'; + +--changeset nitin:2 +ALTER TABLE public.wallet_key ADD key_id varchar(255) NULL; diff --git a/src/test/resources/db/signing-service-migration-test/signing-service-changelog.xml b/src/test/resources/db/signing-service-migration-test/signing-service-changelog.xml new file mode 100644 index 000000000..347a37e7b --- /dev/null +++ b/src/test/resources/db/signing-service-migration-test/signing-service-changelog.xml @@ -0,0 +1,27 @@ + + + + + diff --git a/src/test/resources/db/signing-service-migration-test/without-changes.xml b/src/test/resources/db/signing-service-migration-test/without-changes.xml new file mode 100644 index 000000000..f9d388147 --- /dev/null +++ b/src/test/resources/db/signing-service-migration-test/without-changes.xml @@ -0,0 +1,6 @@ + + +