From fa53be6223fd094822e659e6a235aafb672e4681 Mon Sep 17 00:00:00 2001 From: JohannesRabauer Date: Wed, 29 May 2024 15:29:37 +0200 Subject: [PATCH 1/6] Implemented Signing with pem --- README.md | 4 +- .../main/java/software/xdev/Application.java | 5 +- .../software/xdev/ApplicationWithPem.java | 58 +++++++ .../src/main/resources/DemoCert.pem | 35 ++++ .../src/main/resources/DemoKey.pem | 52 ++++++ .../src/main/resources/DemoKeystore.jks | Bin 4514 -> 4562 bytes .../src/main/resources/app.properties | 4 +- .../xdev/bzst/dip/client/BzstDipClient.java | 10 +- .../client/exception/SigningException.java | 4 +- .../configuration/BzstDipConfiguration.java | 34 ++-- .../BzstDipConfigurationBuilder.java | 115 +++++++++---- .../configuration/PropertiesSupplier.java | 7 +- .../dip/client/signing/SigningProvider.java | 27 +++ .../client/signing/SigningProviderByJks.java | 132 +++++++++++++++ .../client/signing/SigningProviderByPem.java | 155 ++++++++++++++++++ .../XmlSigner.java} | 98 ++++------- .../webclient/BearerTokenRequester.java | 51 ++---- .../ReportableSellerCsvFileParserTest.java | 5 +- .../signing/SigningProviderByJksTest.java | 75 +++++++++ .../signing/SigningProviderByPemTest.java | 47 ++++++ .../dip/client/signing/XmlSignerTest.java | 14 ++ .../src/test/resources/DemoCert.pem | 35 ++++ .../src/test/resources/DemoKey.pem | 52 ++++++ .../src/test/resources/DemoKeystore.jks | Bin 0 -> 4562 bytes 24 files changed, 844 insertions(+), 175 deletions(-) create mode 100644 bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithPem.java create mode 100644 bzst-dip-java-client-demo/src/main/resources/DemoCert.pem create mode 100644 bzst-dip-java-client-demo/src/main/resources/DemoKey.pem create mode 100644 bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProvider.java create mode 100644 bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByJks.java create mode 100644 bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByPem.java rename bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/{util/SigningUtil.java => signing/XmlSigner.java} (67%) create mode 100644 bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/SigningProviderByJksTest.java create mode 100644 bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/SigningProviderByPemTest.java create mode 100644 bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/XmlSignerTest.java create mode 100644 bzst-dip-java-client/src/test/resources/DemoCert.pem create mode 100644 bzst-dip-java-client/src/test/resources/DemoKey.pem create mode 100644 bzst-dip-java-client/src/test/resources/DemoKeystore.jks diff --git a/README.md b/README.md index d7c00efe..1f61e24d 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ request through these XSD find errors before they are sent to the DIP. See the [examples in the demo package](./src/main/java/software/demo/bzst/dip/client/demo). -### Create keystore file +### Create certificate For authentification at the BZST you have to create a public- and private-key. @@ -58,7 +58,7 @@ First you have to create a **PEM** file as described on the [BZST Website](https://www.bzst.de/SharedDocs/Downloads/DE/EOP_BOP/khb_dip.pdf?__blob=publicationFile&v=9) (see 1.7). -OpenSSL can be downloaded from their [website](https://www.openssl.org/). +OpenSSL can be downloaded from the [website](https://www.openssl.org/). ``` openssl req -newkey rsa-pss -new -nodes -x509 -days 3650 -pkeyopt rsa_keygen_bits:4096 -sigopt rsa_pss_saltlen:32 -keyout key.pem -out cert.pem diff --git a/bzst-dip-java-client-demo/src/main/java/software/xdev/Application.java b/bzst-dip-java-client-demo/src/main/java/software/xdev/Application.java index 199dc5ca..c6de1623 100644 --- a/bzst-dip-java-client-demo/src/main/java/software/xdev/Application.java +++ b/bzst-dip-java-client-demo/src/main/java/software/xdev/Application.java @@ -26,6 +26,7 @@ import software.xdev.bzst.dip.client.model.message.BzstDipOecdLegalAddressType; import software.xdev.bzst.dip.client.model.message.BzstDipTaxes; import software.xdev.bzst.dip.client.model.message.BzstDipTin; +import software.xdev.bzst.dip.client.signing.SigningProviderByJks; @SuppressWarnings("checkstyle:MagicNumber") @@ -52,9 +53,7 @@ public static BzstDipConfiguration createConfiguration() .setClientId("abcd1234-ab12-ab12-ab12-abcdef123456") .setTaxID("123") .setTaxNumber("123") - .setCertificateKeystoreInputStream(() -> ClassLoader.getSystemClassLoader() - .getResourceAsStream("DemoKeystore.jks")) - .setCertificateKeystorePassword("test123") + .setSigningProvider(new SigningProviderByJks("DemoKeystore.jks", "test123")) .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) .setReportingPeriod(LocalDate.now()) diff --git a/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithPem.java b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithPem.java new file mode 100644 index 00000000..29afa784 --- /dev/null +++ b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithPem.java @@ -0,0 +1,58 @@ +package software.xdev; + +import java.io.IOException; +import java.time.LocalDate; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import software.xdev.bzst.dip.client.BzstDipClient; +import software.xdev.bzst.dip.client.model.configuration.BzstDipConfiguration; +import software.xdev.bzst.dip.client.model.configuration.BzstDipConfigurationBuilder; +import software.xdev.bzst.dip.client.model.configuration.BzstDipDpiMessageType; +import software.xdev.bzst.dip.client.model.configuration.BzstDipOecdDocType; +import software.xdev.bzst.dip.client.model.message.BzstDipAddressFix; +import software.xdev.bzst.dip.client.model.message.BzstDipCompleteResult; +import software.xdev.bzst.dip.client.signing.SigningProviderByPem; + + +@SuppressWarnings("checkstyle:MagicNumber") +public final class ApplicationWithPem +{ + private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationWithPem.class); + + public static void main(final String[] args) + throws InterruptedException, IOException + { + final BzstDipConfiguration configuration = createConfiguration(); + final BzstDipClient bzstDipClient = new BzstDipClient(configuration); + final BzstDipCompleteResult bzstDipCompleteResult = + bzstDipClient.sendDipAndQueryResult(Application.createMessage()); + LOGGER.info( + "Sending dip message with transfer number {} {}", + bzstDipCompleteResult.dataTransferNumber(), + bzstDipCompleteResult.isSuccessful() ? "was successful." : "has failed!" + ); + } + + public static BzstDipConfiguration createConfiguration() + { + return new BzstDipConfigurationBuilder() + .setClientId("abcd1234-ab12-ab12-ab12-abcdef123456") + .setTaxID("123") + .setTaxNumber("123") + .setSigningProvider(new SigningProviderByPem("DemoCert.pem", "DemoKey.pem")) + .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) + .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) + .setReportingPeriod(LocalDate.now()) + .setDocTypeIndic(BzstDipOecdDocType.OECD_1) + .setPlatformOperatorOrganizationName("TestOrg") + .setPlatformOperatorPlatformName("TestApp") + .setPlatformOperatorAddress(new BzstDipAddressFix("TestCity")) + .buildAndValidate(); + } + + private ApplicationWithPem() + { + } +} diff --git a/bzst-dip-java-client-demo/src/main/resources/DemoCert.pem b/bzst-dip-java-client-demo/src/main/resources/DemoCert.pem new file mode 100644 index 00000000..50cd8b76 --- /dev/null +++ b/bzst-dip-java-client-demo/src/main/resources/DemoCert.pem @@ -0,0 +1,35 @@ +-----BEGIN CERTIFICATE----- +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 +0IGQKyqO/74AsAKW8tlozi8= +-----END CERTIFICATE----- diff --git a/bzst-dip-java-client-demo/src/main/resources/DemoKey.pem b/bzst-dip-java-client-demo/src/main/resources/DemoKey.pem new file mode 100644 index 00000000..04ecad0f --- /dev/null +++ b/bzst-dip-java-client-demo/src/main/resources/DemoKey.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +FBVDvRBxLws/Qwzoli/Jz/+O40LbSlZP8xP6QwKCAQEAw840WyyLo4Ce4v/3ZvFK +LAp8/Yksy2IeX0uFu0P/Ms80bpP73CU91moTlrPmBMs25rL3mVW/FfrpfVMIVWJc +Z96U60lauU1TXyKeqxMOvxD2c6tTmnDJOU7rZe3/kqiOwez6/m3va7FWI+7Wu9Aq +gmLnkCy72MPZxL5nnLNqG3E3Xqg85RZKJb25tZFuJ9v9N2y17ePsNrlb74XrZ5z3 +qkDOPuOa/0vtv18NKfJE2NNpLVGYhYJpZZgA1eulLgTYIFSLipKpymPw31/pC8nU +2m1jl6pD7IhnnVByTHROLyIKkBPvQItxFwzyhVNWjQzg5UOgyKGy22W5M/OoN8gU +CQKCAQAnN6tA6ztx3fOfyordmZosOCjqX3PgMDrqz0327aUeUYK2YDiKwFf3DNkn +r5pb03QJY6kad+8IIB1Kr6ezdJ7I1p23XSZtwQVvVwx189haWmMbKALJiKgDyk6A +tyUahcDtwtXnXamesP+b4dZHSkEOeLvfXoBHwQPKE2m6Ubdes2ll2nFN50/h7kNe +alVMsSOYeo4sr669gWyPk5iX1S1bRvpI/S+G9qTV/bp1piuzibzqwAhoNER6J1ue +i0ZmGEHbj5paULxhol2BPUrTaW2VSlFyiQiJ/000c3eJvmhAr75tFPWmXowhiOC+ +zoafrCyAHLoMLdwpXQzSl212U04/ +-----END PRIVATE KEY----- diff --git a/bzst-dip-java-client-demo/src/main/resources/DemoKeystore.jks b/bzst-dip-java-client-demo/src/main/resources/DemoKeystore.jks index 714fdab8c83e74fb713f342989761464eb15e44e..8e42906c8e0d160a07570cced6cbe696ee250964 100644 GIT binary patch delta 4367 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 MvgQ9E(E + * This can be done by providing two PEM files ({@link SigningProviderByPem}, + * a JKS file ({@link SigningProviderByJks}) or by implementing a custom + * {@link SigningProvider}. + *

*/ - private final Supplier certificateKeystoreInputStream; + private final SigningProvider signingProvider; /** @@ -135,7 +139,6 @@ public class BzstDipConfiguration private final BzstDipAddressFix platformOperatorAddress; public BzstDipConfiguration( - final String certificateKeystorePassword, final String clientId, final String taxID, final String taxNumber, @@ -144,15 +147,14 @@ public BzstDipConfiguration( final BzstDipDpiMessageType messageTypeIndic, final LocalDate reportingPeriod, final BzstDipOecdDocType docType, + final SigningProvider signingProvider, final String platformOperatorDocRefId, final String platformOperatorCorrDocRefId, - final Supplier certificateKeystoreInputStream, final BzstDipQueryResultConfiguration queryResultConfiguration, final String platformOperatorOrganizationName, final String platformOperatorPlatformName, final BzstDipAddressFix platformOperatorAddress) { - this.certificateKeystorePassword = certificateKeystorePassword; this.clientId = clientId; this.taxID = taxID; this.taxNumber = taxNumber; @@ -161,19 +163,15 @@ public BzstDipConfiguration( this.messageTypeIndic = messageTypeIndic; this.reportingPeriod = reportingPeriod; this.docType = docType; + this.signingProvider = signingProvider; this.platformOperatorDocRefId = platformOperatorDocRefId; this.platformOperatorCorrDocRefId = platformOperatorCorrDocRefId; - this.certificateKeystoreInputStream = certificateKeystoreInputStream; this.queryResultConfiguration = queryResultConfiguration; this.platformOperatorOrganizationName = platformOperatorOrganizationName; this.platformOperatorPlatformName = platformOperatorPlatformName; this.platformOperatorAddress = platformOperatorAddress; } - public String getCertificateKeystorePassword() - { - return this.certificateKeystorePassword; - } public String getClientId() { return this.clientId; @@ -224,9 +222,9 @@ public String getPlatformOperatorCorrDocRefId() return this.platformOperatorCorrDocRefId; } - public Supplier getCertificateKeystoreInputStream() + public SigningProvider getSigningProvider() { - return this.certificateKeystoreInputStream; + return this.signingProvider; } public BzstDipQueryResultConfiguration getQueryResultConfiguration() diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilder.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilder.java index cfbb90ac..8156e2e3 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilder.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilder.java @@ -15,14 +15,15 @@ */ package software.xdev.bzst.dip.client.model.configuration; -import java.io.InputStream; import java.time.Duration; import java.time.LocalDate; -import java.util.function.Supplier; import software.xdev.bzst.dip.client.exception.ConfigurationException; import software.xdev.bzst.dip.client.exception.PropertyNotSetException; import software.xdev.bzst.dip.client.model.message.BzstDipAddressFix; +import software.xdev.bzst.dip.client.signing.SigningProvider; +import software.xdev.bzst.dip.client.signing.SigningProviderByJks; +import software.xdev.bzst.dip.client.signing.SigningProviderByPem; /** @@ -36,10 +37,6 @@ public class BzstDipConfigurationBuilder public static final int DEFAULT_DELAY_IN_BETWEEN_RESULTS_CHECKS_IN_MILLIS = 1_000; private final PropertiesSupplier propertiesSupplier; - /** - * @see BzstDipConfiguration#getCertificateKeystorePassword() - */ - private String certificateKeystorePassword; /** * @see BzstDipConfiguration#getClientId() */ @@ -81,9 +78,9 @@ public class BzstDipConfigurationBuilder */ private String platformOperatorCorrDocRefId; /** - * @see BzstDipConfiguration#getCertificateKeystoreInputStream() + * @see BzstDipConfiguration#getSigningProvider() */ - private Supplier certificateKeystoreInputStream; + private SigningProvider signingProvider; /** * @see BzstDipQueryResultConfiguration#delayBeforeCheckingResults */ @@ -119,16 +116,6 @@ public BzstDipConfigurationBuilder() this(new PropertiesSupplier()); } - /** - * @param certificateKeystorePassword {@link #certificateKeystorePassword} - * @return itself - */ - public BzstDipConfigurationBuilder setCertificateKeystorePassword(final String certificateKeystorePassword) - { - this.certificateKeystorePassword = certificateKeystorePassword; - return this; - } - /** * @param clientId {@link #clientId} * @return itself @@ -243,7 +230,7 @@ public BzstDipConfigurationBuilder setDelayBeforeCheckingResults(final Duration * @param retryQueryResultsAmount {@link #retryQueryResultsAmount} * @return itself */ - public BzstDipConfigurationBuilder setRetryQueryResultsAmount(final int retryQueryResultsAmount) + public BzstDipConfigurationBuilder setRetryQueryResultsAmount(final Integer retryQueryResultsAmount) { this.retryQueryResultsAmount = retryQueryResultsAmount; return this; @@ -260,13 +247,12 @@ public BzstDipConfigurationBuilder setDelayInBetweenResultChecks(final Duration } /** - * @param certificateKeystoreInputStream {@link #certificateKeystoreInputStream} + * @param signingProvider {@link #signingProvider} * @return itself */ - public BzstDipConfigurationBuilder setCertificateKeystoreInputStream( - final Supplier certificateKeystoreInputStream) + public BzstDipConfigurationBuilder setSigningProvider(final SigningProvider signingProvider) { - this.certificateKeystoreInputStream = certificateKeystoreInputStream; + this.signingProvider = signingProvider; return this; } @@ -307,10 +293,6 @@ public BzstDipConfigurationBuilder setPlatformOperatorAddress(final BzstDipAddre public BzstDipConfiguration buildAndValidate() { final BzstDipConfiguration configuration = new BzstDipConfiguration( - this.getSetPropertyOrReadFromFile( - this.certificateKeystorePassword, - PropertiesSupplier.PROPERTY_NAME_CERTIFICATE_KEYSTORE_PASSWORD, - ""), this.getSetPropertyOrReadFromFile(this.clientId, PropertiesSupplier.PROPERTY_NAME_CLIENT_ID), this.getSetPropertyOrReadFromFile(this.taxID, PropertiesSupplier.PROPERTY_NAME_TAX_ID), this.getSetPropertyOrReadFromFile(this.taxNumber, PropertiesSupplier.PROPERTY_NAME_TAX_NUMBER), @@ -331,6 +313,7 @@ public BzstDipConfiguration buildAndValidate() this.getSetPropertyOrReadFromFileOecdDocType( this.docTypeIndic, PropertiesSupplier.PROPERTY_NAME_DOC_TYPE_INDIC), + this.getSigningProvider(this.signingProvider), this.getSetPropertyOrReadFromFile( this.platformOperatorDocRefId, PropertiesSupplier.PROPERTY_NAME_PLATFORM_OPERATOR_DOC_REF_ID, @@ -339,9 +322,6 @@ public BzstDipConfiguration buildAndValidate() this.platformOperatorCorrDocRefId, PropertiesSupplier.PROPERTY_NAME_PLATFORM_OPERATOR_CORR_DOC_REF_ID, ""), - this.getInputStreamSupplier( - this.certificateKeystoreInputStream, - PropertiesSupplier.PROPERTY_NAME_CERTIFICATE_KEYSTORE_FILE), new BzstDipQueryResultConfiguration( this.getSetPropertyOrReadFromFileDuration( this.delayBeforeCheckingResults, @@ -383,16 +363,81 @@ private void validateConfiguration(final BzstDipConfiguration configuration) } } - private Supplier getInputStreamSupplier( - final Supplier builderProperty, - final String propertyNameInFile) + private SigningProvider getSigningProvider(final SigningProvider builderProperty) { if(builderProperty != null) { return builderProperty; } - final String inputFile = this.getSetPropertyOrReadFromFile(null, propertyNameInFile); - return () -> ClassLoader.getSystemClassLoader().getResourceAsStream(inputFile); + final SigningProviderByJks signingProviderByJks = this.createJksKeyProvider(); + if(signingProviderByJks != null) + { + return signingProviderByJks; + } + + final SigningProviderByPem signingProviderByPem = this.createPemKeyProvider(); + if(signingProviderByPem != null) + { + return signingProviderByPem; + } + throw new ConfigurationException("A signing provider must be set"); + } + + private SigningProviderByJks createJksKeyProvider() + { + final String jksKeystorePassword = + this.propertiesSupplier.getPropertyFromConfig(PropertiesSupplier.PROPERTY_NAME_SIGNING_JKS_KEYSTORE_PASSWORD); + final String jksKeystoreFile = + this.propertiesSupplier.getPropertyFromConfig(PropertiesSupplier.PROPERTY_NAME_SIGNING_JKS_KEYSTORE_FILE); + if(jksKeystorePassword == null && jksKeystoreFile == null) + { + return null; + } + if(jksKeystorePassword != null && jksKeystoreFile != null) + { + return new SigningProviderByJks( + jksKeystoreFile, + jksKeystorePassword + ); + } + if(jksKeystoreFile == null) + { + throw new ConfigurationException( + "Invalid configuration of JKS Keystore: Keystore password is set, but the keystore file is not."); + } + throw new ConfigurationException( + "Invalid configuration of JKS Keystore: Keystore file is set, but the keystore password is not."); + } + + private SigningProviderByPem createPemKeyProvider() + { + final String signatureAlgorithm = this.getSetPropertyOrReadFromFile( + null, + PropertiesSupplier.PROPERTY_NAME_SIGNING_PEM_SIGNATURE_ALGORITHM, + SigningProviderByPem.DEFAULT_PRIVATE_KEY_ALGORITHM); + final String pemCertificateFile = + this.propertiesSupplier.getPropertyFromConfig(PropertiesSupplier.PROPERTY_NAME_SIGNING_PEM_CERTIFICATE_FILE); + final String pemPrivateKeyFile = + this.propertiesSupplier.getPropertyFromConfig(PropertiesSupplier.PROPERTY_NAME_SIGNING_PEM_PRIVATE_KEY_FILE); + if(pemCertificateFile == null && pemPrivateKeyFile == null) + { + return null; + } + if(pemCertificateFile != null && pemPrivateKeyFile != null) + { + return new SigningProviderByPem( + pemCertificateFile, + pemPrivateKeyFile, + signatureAlgorithm + ); + } + if(pemCertificateFile == null) + { + throw new ConfigurationException( + "Invalid configuration of PEM Signature: The private key is set, but the certificate file is not."); + } + throw new ConfigurationException( + "Invalid configuration of PEM Signature: The certificate file is set, but the private key is not."); } private BzstDipAddressFix getSetPropertyOrReadFromFileAddress(final BzstDipAddressFix builderProperty) diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/PropertiesSupplier.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/PropertiesSupplier.java index c89b777b..0077579f 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/PropertiesSupplier.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/PropertiesSupplier.java @@ -29,8 +29,11 @@ @SuppressWarnings({"unused", "UnusedReturnValue"}) public class PropertiesSupplier { - public static final String PROPERTY_NAME_CERTIFICATE_KEYSTORE_PASSWORD = "certificate.keystore.password"; - public static final String PROPERTY_NAME_CERTIFICATE_KEYSTORE_FILE = "certificate.keystore.file"; + public static final String PROPERTY_NAME_SIGNING_JKS_KEYSTORE_PASSWORD = "signing.jks.keystore.password"; + public static final String PROPERTY_NAME_SIGNING_JKS_KEYSTORE_FILE = "signing.jks.keystore.file"; + public static final String PROPERTY_NAME_SIGNING_PEM_CERTIFICATE_FILE = "signing.pem.certificate.file"; + public static final String PROPERTY_NAME_SIGNING_PEM_PRIVATE_KEY_FILE = "signing.pem.private.key.file"; + public static final String PROPERTY_NAME_SIGNING_PEM_SIGNATURE_ALGORITHM = "signing.pem.signature.algorithm"; public static final String PROPERTY_NAME_CLIENT_ID = "client.id"; public static final String PROPERTY_NAME_TAX_ID = "tax.id"; public static final String PROPERTY_NAME_TAX_NUMBER = "tax.number"; diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProvider.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProvider.java new file mode 100644 index 00000000..e0a68f83 --- /dev/null +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProvider.java @@ -0,0 +1,27 @@ +/* + * Copyright © 2024 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://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. + */ +package software.xdev.bzst.dip.client.signing; + +import java.security.PrivateKey; +import java.security.cert.X509Certificate; + + +public interface SigningProvider +{ + X509Certificate getCertificate(); + + PrivateKey getPrivateKey(); +} diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByJks.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByJks.java new file mode 100644 index 00000000..8154bcf2 --- /dev/null +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByJks.java @@ -0,0 +1,132 @@ +/* + * Copyright © 2024 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://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. + */ +package software.xdev.bzst.dip.client.signing; + +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.util.function.Supplier; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import software.xdev.bzst.dip.client.exception.SigningException; + + +public class SigningProviderByJks implements SigningProvider +{ + private static final Logger LOGGER = LoggerFactory.getLogger(SigningProviderByJks.class); + public static final String KEYSTORE_TYPE = "JKS"; + private final Supplier certificateKeystoreInputStream; + private final String certificateKeystorePassword; + private X509Certificate certificate; + private PrivateKey privateKey; + + public SigningProviderByJks( + final String certificateKeystorePath, + final String certificateKeystorePassword + ) + { + this( + () -> ClassLoader.getSystemClassLoader().getResourceAsStream(certificateKeystorePath), + certificateKeystorePassword + ); + } + + public SigningProviderByJks( + final Supplier certificateKeystoreInputStream, + final String certificateKeystorePassword + ) + { + this.certificateKeystoreInputStream = certificateKeystoreInputStream; + this.certificateKeystorePassword = certificateKeystorePassword; + } + + @Override + public X509Certificate getCertificate() + { + if(this.certificate == null) + { + this.initKeys(); + } + return this.certificate; + } + + @Override + public PrivateKey getPrivateKey() + { + if(this.privateKey == null) + { + this.initKeys(); + } + return this.privateKey; + } + + private void initKeys() + { + try(final InputStream keystoreInputStream = this.certificateKeystoreInputStream.get()) + { + // Get private key + final KeyStore.PrivateKeyEntry privateKeyEntry = + this.getPrivateKeyEntry( + keystoreInputStream, + this.certificateKeystorePassword, + KEYSTORE_TYPE + ); + this.certificate = (X509Certificate)privateKeyEntry.getCertificate(); + this.privateKey = privateKeyEntry.getPrivateKey(); + } + catch(final IOException e) + { + throw new SigningException("Could not read keystore.", e); + } + } + + /** + * Reads the given {@link InputStream} with the corresponding password and returns it as + * {@link KeyStore.PrivateKeyEntry}. + */ + private KeyStore.PrivateKeyEntry getPrivateKeyEntry( + final InputStream keyStoreInputStream, + final String keyStorePassword, + final String type) + { + try + { + LOGGER.debug("Loading keystore file..."); + final KeyStore ks = KeyStore.getInstance(type); + ks.load(keyStoreInputStream, keyStorePassword.toCharArray()); + + final KeyStore.PrivateKeyEntry certificate = (KeyStore.PrivateKeyEntry)ks.getEntry( + "certificate", + new KeyStore.PasswordProtection(keyStorePassword.toCharArray())); + + if(certificate == null) + { + throw new SigningException("The private key entry in the keystore is null."); + } + return certificate; + } + catch(final Exception e) + { + throw new SigningException( + "Something wrong happened while getting the private key entry from the keystore.", + e); + } + } +} diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByPem.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByPem.java new file mode 100644 index 00000000..64960e61 --- /dev/null +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByPem.java @@ -0,0 +1,155 @@ +/* + * Copyright © 2024 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://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. + */ +package software.xdev.bzst.dip.client.signing; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.security.KeyFactory; +import java.security.PrivateKey; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.function.Supplier; + +import org.apache.hc.client5.http.utils.Base64; + +import software.xdev.bzst.dip.client.exception.SigningException; + + +public class SigningProviderByPem implements SigningProvider +{ + public static final String DEFAULT_PRIVATE_KEY_ALGORITHM = "RSASSA-PSS"; + private final Supplier certificatePemInputStream; + private final Supplier privateKeyPemInputStream; + private final String privateKeyAlgorithm; + private X509Certificate certificate; + private PrivateKey privateKey; + + public SigningProviderByPem( + final String certificatePemFilePath, + final String privateKeyPemFilePath + ) + { + this( + certificatePemFilePath, + privateKeyPemFilePath, + DEFAULT_PRIVATE_KEY_ALGORITHM + ); + } + + public SigningProviderByPem( + final String certificatePemFilePath, + final String privateKeyPemFilePath, + final String privateKeyAlgorithm + ) + { + this( + () -> ClassLoader.getSystemClassLoader().getResourceAsStream(certificatePemFilePath), + () -> ClassLoader.getSystemClassLoader().getResourceAsStream(privateKeyPemFilePath), + privateKeyAlgorithm + ); + } + + public SigningProviderByPem( + final Supplier certificatePemInputStream, + final Supplier privateKeyPemInputStream + ) + { + this( + certificatePemInputStream, + privateKeyPemInputStream, + DEFAULT_PRIVATE_KEY_ALGORITHM + ); + } + + public SigningProviderByPem( + final Supplier certificatePemInputStream, + final Supplier privateKeyPemInputStream, + final String privateKeyAlgorithm) + { + this.certificatePemInputStream = certificatePemInputStream; + this.privateKeyPemInputStream = privateKeyPemInputStream; + this.privateKeyAlgorithm = privateKeyAlgorithm; + } + + @Override + public X509Certificate getCertificate() + { + if(this.certificate == null) + { + this.initKeys(); + } + return this.certificate; + } + + @Override + public PrivateKey getPrivateKey() + { + if(this.privateKey == null) + { + this.initKeys(); + } + return this.privateKey; + } + + private void initKeys() + { + try + { + this.certificate = this.readCertificate(this.certificatePemInputStream.get()); + } + catch(final Exception e) + { + throw new SigningException("Could not read certificate.", e); + } + try + { + this.privateKey = this.readPrivateKey(this.privateKeyPemInputStream.get()); + } + catch(final Exception e) + { + throw new SigningException("Could not read private key.", e); + } + } + + private X509Certificate readCertificate(final InputStream certificateInputStream) + throws CertificateException, IOException + { + try(certificateInputStream) + { + final CertificateFactory fact = CertificateFactory.getInstance("X.509"); + return (X509Certificate)fact.generateCertificate(certificateInputStream); + } + } + + private PrivateKey readPrivateKey(final InputStream privateKeyInputStream) throws Exception + { + final String key = new String(privateKeyInputStream.readAllBytes(), Charset.defaultCharset()); + + final String privateKeyPEM = key + .replace("-----BEGIN PRIVATE KEY-----", "") + .replaceAll(System.lineSeparator(), "") + .replace("-----END PRIVATE KEY-----", ""); + + final byte[] encoded = Base64.decodeBase64(privateKeyPEM); + + final KeyFactory keyFactory = KeyFactory.getInstance(this.privateKeyAlgorithm); + final PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded); + return keyFactory.generatePrivate(keySpec); + } +} diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/util/SigningUtil.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/XmlSigner.java similarity index 67% rename from bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/util/SigningUtil.java rename to bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/XmlSigner.java index 1b24afe5..2c8eeb1c 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/util/SigningUtil.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/XmlSigner.java @@ -13,17 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package software.xdev.bzst.dip.client.util; +package software.xdev.bzst.dip.client.signing; import static java.util.Collections.singletonList; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.security.InvalidAlgorithmParameterException; -import java.security.KeyStore; import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collections; @@ -60,33 +59,32 @@ import software.xdev.bzst.dip.client.exception.SigningException; import software.xdev.bzst.dip.client.factory.DocumentBuilderFactoryNoExternalEntities; import software.xdev.bzst.dip.client.factory.TransformerFactoryExtension; -import software.xdev.bzst.dip.client.model.configuration.BzstDipConfiguration; /** * Helps with signing XML-Documents */ -public final class SigningUtil +public final class XmlSigner { - private static final Logger LOGGER = LoggerFactory.getLogger(SigningUtil.class); + private static final Logger LOGGER = LoggerFactory.getLogger(XmlSigner.class); private static final String DIGEST_METHOD = DigestMethod.SHA256; private static final String SIGNATURE_METHOD = SignatureMethod.SHA256_RSA_MGF1; - public static final String KEYSTORE_TYPE = "JKS"; - private SigningUtil() + private final SigningProvider certAndKeyProvider; + + public XmlSigner(final SigningProvider certAndKeyProvider) { + this.certAndKeyProvider = certAndKeyProvider; } /** - * Signs an unsigned xml string with the corresponding keystore from the - * {@link BzstDipConfiguration#certificateKeystoreInputStream} + * Signs an unsigned xml string with the corresponding {@link SigningProvider}. * * @return the signed xml document as string */ - public static String signXMLDocument(final String unsignedXmlString, final BzstDipConfiguration configuration) + public String signXMLDocument(final String unsignedXmlString) { - try(final InputStream keystoreInputStream = configuration.getCertificateKeystoreInputStream().get(); - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + try(final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); final ByteArrayInputStream unsignedXmlByteArrayInputStream = new ByteArrayInputStream(unsignedXmlString.getBytes(StandardCharsets.UTF_8))) { @@ -97,22 +95,17 @@ public static String signXMLDocument(final String unsignedXmlString, final BzstD final Document newDocument = dbf.newDocumentBuilder().newDocument(); final XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance("DOM"); - // Get private key - final KeyStore.PrivateKeyEntry privateKeyEntry = - getPrivateKeyEntry( - keystoreInputStream, - configuration.getCertificateKeystorePassword(), - KEYSTORE_TYPE - ); + final X509Certificate certificate = this.certAndKeyProvider.getCertificate(); + final PrivateKey privateKey = this.certAndKeyProvider.getPrivateKey(); // Sign context - createDomSignContext(privateKeyEntry, newDocument, xmlSignatureFactory, dipXmlDocument); + this.createDomSignContext(certificate, privateKey, newDocument, xmlSignatureFactory, dipXmlDocument); final Result outputTarget = new StreamResult(outputStream); final TransformerFactory transformerFactory = TransformerFactoryExtension.newInstance(); transformerFactory.newTransformer().transform(new DOMSource(newDocument), outputTarget); - if(!validateSignature(newDocument, xmlSignatureFactory, privateKeyEntry)) + if(!this.validateSignature(newDocument, xmlSignatureFactory, certificate)) { throw new SigningException("The validation of the signature from the XML document has failed."); } @@ -125,8 +118,9 @@ public static String signXMLDocument(final String unsignedXmlString, final BzstD } } - private static void createDomSignContext( - final KeyStore.PrivateKeyEntry privateKeyEntry, + private void createDomSignContext( + final X509Certificate certificate, + final PrivateKey privateKey, final Document newDocument, final XMLSignatureFactory xmlSignatureFactory, final Document dipXmlDocument @@ -139,16 +133,16 @@ private static void createDomSignContext( { // Sign info - final SignedInfo signedInfo = createSignedInfo(xmlSignatureFactory); + final SignedInfo signedInfo = this.createSignedInfo(xmlSignatureFactory); // Key info - final KeyInfo keyInfo = createKeyInfo(privateKeyEntry, xmlSignatureFactory); + final KeyInfo keyInfo = this.createKeyInfo(certificate, xmlSignatureFactory); final DOMStructure content = new DOMStructure(dipXmlDocument.getDocumentElement()); final XMLObject signedObject = xmlSignatureFactory.newXMLObject(Collections.singletonList(content), "object", null, null); - final DOMSignContext domSignContext = new DOMSignContext(privateKeyEntry.getPrivateKey(), newDocument); + final DOMSignContext domSignContext = new DOMSignContext(privateKey, newDocument); domSignContext.setDefaultNamespacePrefix("ds"); final XMLSignature xmlSignature = xmlSignatureFactory.newXMLSignature(signedInfo, keyInfo, @@ -156,7 +150,7 @@ private static void createDomSignContext( xmlSignature.sign(domSignContext); } - private static SignedInfo createSignedInfo(final XMLSignatureFactory xmlSignatureFactory) + private SignedInfo createSignedInfo(final XMLSignatureFactory xmlSignatureFactory) throws InvalidAlgorithmParameterException, NoSuchAlgorithmException { @@ -172,25 +166,24 @@ private static SignedInfo createSignedInfo(final XMLSignatureFactory xmlSignatur ); } - private static KeyInfo createKeyInfo( - final KeyStore.PrivateKeyEntry privateKeyEntry, + private KeyInfo createKeyInfo( + final X509Certificate certificate, final XMLSignatureFactory xmlSignatureFactory) { - final X509Certificate cert = (X509Certificate)privateKeyEntry.getCertificate(); final KeyInfoFactory kif = xmlSignatureFactory.getKeyInfoFactory(); final List x509Content = new ArrayList<>(); - x509Content.add(cert.getSubjectX500Principal().getName()); - x509Content.add(cert); + x509Content.add(certificate.getSubjectX500Principal().getName()); + x509Content.add(certificate); final X509Data xd = kif.newX509Data(x509Content); return kif.newKeyInfo(singletonList(xd)); } - private static boolean validateSignature( + private boolean validateSignature( final Document doc, final XMLSignatureFactory fac, - final KeyStore.PrivateKeyEntry privateKeyEntry) + final X509Certificate certificate) throws MarshalException, XMLSignatureException { LOGGER.debug("Validating xml signature..."); @@ -205,7 +198,7 @@ private static boolean validateSignature( // Create a DOMValidateContext and specify a KeySelector // and document context. final DOMValidateContext valContext = new DOMValidateContext( - privateKeyEntry.getCertificate().getPublicKey(), + certificate.getPublicKey(), nl.item(0)); // Unmarshal the XMLSignature. @@ -215,37 +208,4 @@ private static boolean validateSignature( // Validate the XMLSignature. return s.validate(valContext); } - - /** - * Reads the given {@link InputStream} with the corresponding password - * and returns it as {@link KeyStore.PrivateKeyEntry}. - */ - public static KeyStore.PrivateKeyEntry getPrivateKeyEntry( - final InputStream keyStoreInputStream, - final String keyStorePassword, - final String type) - { - try - { - LOGGER.debug("Loading keystore file..."); - final KeyStore ks = KeyStore.getInstance(type); - ks.load(keyStoreInputStream, keyStorePassword.toCharArray()); - - final KeyStore.PrivateKeyEntry certificate = (KeyStore.PrivateKeyEntry)ks.getEntry( - "certificate", - new KeyStore.PasswordProtection(keyStorePassword.toCharArray())); - - if(certificate == null) - { - throw new SigningException("The private key entry in the keystore is null."); - } - return certificate; - } - catch(final Exception e) - { - throw new SigningException( - "Something wrong happened while getting the private key entry from the keystore.", - e); - } - } } diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/webclient/BearerTokenRequester.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/webclient/BearerTokenRequester.java index d60f004a..5b9aad65 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/webclient/BearerTokenRequester.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/webclient/BearerTokenRequester.java @@ -15,9 +15,6 @@ */ package software.xdev.bzst.dip.client.webclient; -import java.io.IOException; -import java.io.InputStream; -import java.security.KeyStore; import java.security.PrivateKey; import java.time.Duration; import java.util.Date; @@ -32,10 +29,8 @@ import com.fasterxml.jackson.core.type.TypeReference; import io.jsonwebtoken.Jwts; -import software.xdev.bzst.dip.client.exception.EncryptionException; import software.xdev.bzst.dip.client.generated.api.MdEinreichenProviderApi; import software.xdev.bzst.dip.client.model.configuration.BzstDipConfiguration; -import software.xdev.bzst.dip.client.util.SigningUtil; /** @@ -101,34 +96,22 @@ public String getAccessTokenWithBearerPrefix() private String createRequestToken() { LOGGER.debug("Creating jwt token..."); - try(final InputStream keystoreInputStream = this.configuration.getCertificateKeystoreInputStream().get()) - { - final KeyStore.PrivateKeyEntry privateKeyEntry = SigningUtil.getPrivateKeyEntry( - keystoreInputStream, - this.configuration.getCertificateKeystorePassword(), - SigningUtil.KEYSTORE_TYPE - ); - - final PrivateKey privateKey = privateKeyEntry.getPrivateKey(); - final String clientId = this.configuration.getClientId(); - LOGGER.debug("Using client id: {}", clientId); - - return Jwts.builder() - .issuer(clientId) - .subject(clientId) - .audience().add( - this.configuration.getRealmEnvironmentBaseUrl() + MDS_POSTFIX) - .and() - .issuedAt(new Date()) - .expiration(new Date(System.currentTimeMillis() + Duration.ofMinutes(5).toMillis())) - .id(UUID.randomUUID().toString()) - .notBefore(new Date(System.currentTimeMillis() - Duration.ofMinutes(1).toMillis())) - .signWith(privateKey, Jwts.SIG.RS256) - .compact(); - } - catch(final IOException ioException) - { - throw new EncryptionException("An error occurred while creating the request token.", ioException); - } + + final PrivateKey privateKey = this.configuration.getSigningProvider().getPrivateKey(); + final String clientId = this.configuration.getClientId(); + LOGGER.debug("Using client id: {}", clientId); + + return Jwts.builder() + .issuer(clientId) + .subject(clientId) + .audience().add( + this.configuration.getRealmEnvironmentBaseUrl() + MDS_POSTFIX) + .and() + .issuedAt(new Date()) + .expiration(new Date(System.currentTimeMillis() + Duration.ofMinutes(5).toMillis())) + .id(UUID.randomUUID().toString()) + .notBefore(new Date(System.currentTimeMillis() - Duration.ofMinutes(1).toMillis())) + .signWith(privateKey, Jwts.SIG.RS256) + .compact(); } } diff --git a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ReportableSellerCsvFileParserTest.java b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ReportableSellerCsvFileParserTest.java index d0037075..981fea04 100644 --- a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ReportableSellerCsvFileParserTest.java +++ b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ReportableSellerCsvFileParserTest.java @@ -31,6 +31,7 @@ import software.xdev.bzst.dip.client.model.configuration.BzstDipOecdDocType; import software.xdev.bzst.dip.client.model.message.BzstDipAddressFix; import software.xdev.bzst.dip.client.parser.ReportableSellerCsvFileParser; +import software.xdev.bzst.dip.client.signing.SigningProviderByJks; import software.xdev.bzst.dip.client.xmldocument.model.CorrectableReportableSellerType; @@ -40,9 +41,7 @@ class ReportableSellerCsvFileParserTest .setClientId("TestClient") .setTaxID("123") .setTaxNumber("123") - .setCertificateKeystorePassword("test123") - .setCertificateKeystoreInputStream(() -> ClassLoader.getSystemClassLoader() - .getResourceAsStream("DemoKeystore.jks")) + .setSigningProvider(new SigningProviderByJks("DemoKeystore.jks", "test123")) .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) .setReportingPeriod(LocalDate.now()) diff --git a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/SigningProviderByJksTest.java b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/SigningProviderByJksTest.java new file mode 100644 index 00000000..3ea2c999 --- /dev/null +++ b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/SigningProviderByJksTest.java @@ -0,0 +1,75 @@ +/* + * Copyright © 2024 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://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. + */ +package software.xdev.bzst.dip.client.signing; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import software.xdev.bzst.dip.client.exception.SigningException; + + +class SigningProviderByJksTest +{ + + public static final String CERTIFICATE_KEYSTORE_PASSWORD = "test123"; + public static final String CERTIFICATE_KEYSTORE_PATH = "DemoKeystore.jks"; + + @Test + void getCertificate() + { + final SigningProviderByJks signingProviderByJks = new SigningProviderByJks( + CERTIFICATE_KEYSTORE_PATH, + CERTIFICATE_KEYSTORE_PASSWORD + ); + Assertions.assertNotNull(signingProviderByJks.getCertificate()); + } + + @Test + void getPrivateKey() + { + final SigningProviderByJks signingProviderByJks = new SigningProviderByJks( + CERTIFICATE_KEYSTORE_PATH, + CERTIFICATE_KEYSTORE_PASSWORD + ); + Assertions.assertNotNull(signingProviderByJks.getPrivateKey()); + } + + @Test + void getPrivateKey_wrongPassword() + { + final SigningProviderByJks signingProviderByJks = new SigningProviderByJks( + CERTIFICATE_KEYSTORE_PATH, + "wrongPwd" + ); + Assertions.assertThrows( + SigningException.class, + () -> signingProviderByJks.getPrivateKey() + ); + } + + @Test + void getCertificate_wrongPassword() + { + final SigningProviderByJks signingProviderByJks = new SigningProviderByJks( + CERTIFICATE_KEYSTORE_PATH, + "wrongPwd" + ); + Assertions.assertThrows( + SigningException.class, + () -> signingProviderByJks.getCertificate() + ); + } +} diff --git a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/SigningProviderByPemTest.java b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/SigningProviderByPemTest.java new file mode 100644 index 00000000..1b191483 --- /dev/null +++ b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/SigningProviderByPemTest.java @@ -0,0 +1,47 @@ +/* + * Copyright © 2024 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://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. + */ +package software.xdev.bzst.dip.client.signing; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + + +class SigningProviderByPemTest +{ + + public static final String DEMO_CERT_PEM = "DemoCert.pem"; + public static final String DEMO_KEY_PEM = "DemoKey.pem"; + + @Test + void getCertificate() + { + final SigningProviderByPem signingProviderByPem = new SigningProviderByPem( + DEMO_CERT_PEM, + DEMO_KEY_PEM + ); + Assertions.assertNotNull(signingProviderByPem.getCertificate()); + } + + @Test + void getPrivateKey() + { + final SigningProviderByPem signingProviderByPem = new SigningProviderByPem( + DEMO_CERT_PEM, + DEMO_KEY_PEM + ); + Assertions.assertNotNull(signingProviderByPem.getPrivateKey()); + } +} diff --git a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/XmlSignerTest.java b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/XmlSignerTest.java new file mode 100644 index 00000000..b5330064 --- /dev/null +++ b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/XmlSignerTest.java @@ -0,0 +1,14 @@ +package software.xdev.bzst.dip.client.signing; + +import org.junit.jupiter.api.Test; + + +class XmlSignerTest +{ + + @Test + void signXMLDocument() + { + // TODO + } +} diff --git a/bzst-dip-java-client/src/test/resources/DemoCert.pem b/bzst-dip-java-client/src/test/resources/DemoCert.pem new file mode 100644 index 00000000..50cd8b76 --- /dev/null +++ b/bzst-dip-java-client/src/test/resources/DemoCert.pem @@ -0,0 +1,35 @@ +-----BEGIN CERTIFICATE----- +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 +0IGQKyqO/74AsAKW8tlozi8= +-----END CERTIFICATE----- diff --git a/bzst-dip-java-client/src/test/resources/DemoKey.pem b/bzst-dip-java-client/src/test/resources/DemoKey.pem new file mode 100644 index 00000000..04ecad0f --- /dev/null +++ b/bzst-dip-java-client/src/test/resources/DemoKey.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +FBVDvRBxLws/Qwzoli/Jz/+O40LbSlZP8xP6QwKCAQEAw840WyyLo4Ce4v/3ZvFK +LAp8/Yksy2IeX0uFu0P/Ms80bpP73CU91moTlrPmBMs25rL3mVW/FfrpfVMIVWJc +Z96U60lauU1TXyKeqxMOvxD2c6tTmnDJOU7rZe3/kqiOwez6/m3va7FWI+7Wu9Aq +gmLnkCy72MPZxL5nnLNqG3E3Xqg85RZKJb25tZFuJ9v9N2y17ePsNrlb74XrZ5z3 +qkDOPuOa/0vtv18NKfJE2NNpLVGYhYJpZZgA1eulLgTYIFSLipKpymPw31/pC8nU +2m1jl6pD7IhnnVByTHROLyIKkBPvQItxFwzyhVNWjQzg5UOgyKGy22W5M/OoN8gU +CQKCAQAnN6tA6ztx3fOfyordmZosOCjqX3PgMDrqz0327aUeUYK2YDiKwFf3DNkn +r5pb03QJY6kad+8IIB1Kr6ezdJ7I1p23XSZtwQVvVwx189haWmMbKALJiKgDyk6A +tyUahcDtwtXnXamesP+b4dZHSkEOeLvfXoBHwQPKE2m6Ubdes2ll2nFN50/h7kNe +alVMsSOYeo4sr669gWyPk5iX1S1bRvpI/S+G9qTV/bp1piuzibzqwAhoNER6J1ue +i0ZmGEHbj5paULxhol2BPUrTaW2VSlFyiQiJ/000c3eJvmhAr75tFPWmXowhiOC+ +zoafrCyAHLoMLdwpXQzSl212U04/ +-----END PRIVATE KEY----- diff --git a/bzst-dip-java-client/src/test/resources/DemoKeystore.jks b/bzst-dip-java-client/src/test/resources/DemoKeystore.jks new file mode 100644 index 0000000000000000000000000000000000000000..8e42906c8e0d160a07570cced6cbe696ee250964 GIT binary patch literal 4562 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 Date: Fri, 31 May 2024 08:18:02 +0200 Subject: [PATCH 2/6] Added Tests and documentation for PEM Signing --- README.md | 26 ++++---- bzst-dip-java-client/pom.xml | 9 ++- .../client/exception/EncryptionException.java | 36 ---------- .../dip/client/signing/SigningProvider.java | 3 + .../client/signing/SigningProviderByJks.java | 3 + .../client/signing/SigningProviderByPem.java | 16 ++++- .../dip/client/ConfigurationTestUtil.java | 66 +++++++++++++++++++ .../ReportableSellerCsvFileParserTest.java | 27 ++------ .../dip/client/signing/XmlSignerTest.java | 56 ++++++++++++++-- 9 files changed, 165 insertions(+), 77 deletions(-) delete mode 100644 bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/exception/EncryptionException.java create mode 100644 bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ConfigurationTestUtil.java diff --git a/README.md b/README.md index 1f61e24d..f3de6791 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,20 @@ OpenSSL can be downloaded from the [website](https://www.openssl.org/). openssl req -newkey rsa-pss -new -nodes -x509 -days 3650 -pkeyopt rsa_keygen_bits:4096 -sigopt rsa_pss_saltlen:32 -keyout key.pem -out cert.pem ``` -Next you have to convert that file to a **PKCS12** file. +You also have to set the public key in the [BZST online.portal](https://online.portal.bzst.de/). +Exporting the public key with OpenSSL is easy: + +``` +openssl rsa -in key.pem -pubout > publicKey.pub +``` + +Now you can already use these two files to sign your requests. See +the [example with PEM signing](./bzst-dip-java-client-demo\src\main\java\software\xdev\ApplicationWithPem.java). + +### Create Java KeyStore (JKS) + +If you want to go one step further you can use the Java KeyStore. Then you have to convert the `cert.pem` file to a * +*PKCS12** file. ``` openssl pkcs12 -export -in cert.pem -inkey key.pem -out certificate.p12 -name "certificate" @@ -85,13 +98,6 @@ certificate.keystore.password=SECRET_PASSWORD certificate.keystore.file=cert.jks ``` -You also have to set the public key in the [BZST online.portal](https://online.portal.bzst.de/). -Exporting the public key with OpenSSL is easy: - -``` -openssl rsa -in key.pem -pubout > publicKey.pub -``` - ### Client ID It's also important to use the client id provided by [BZST online.portal](https://online.portal.bzst.de/) @@ -117,9 +123,7 @@ public static BzstDipConfiguration createConfiguration() .setClientId("abcd1234-ab12-ab12-ab12-abcdef123456") .setTaxID("123") .setTaxNumber("123") - .setCertificateKeystoreInputStream(() -> ClassLoader.getSystemClassLoader() - .getResourceAsStream("DemoKeystore.jks")) - .setCertificateKeystorePassword("test123") + .setSigningProvider(new SigningProviderByJks("DemoKeystore.jks", "test123")) .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) .setReportingPeriod(LocalDate.now()) diff --git a/bzst-dip-java-client/pom.xml b/bzst-dip-java-client/pom.xml index 1c1ce779..0482be60 100644 --- a/bzst-dip-java-client/pom.xml +++ b/bzst-dip-java-client/pom.xml @@ -57,6 +57,7 @@ src/generated/** + 5.10.2 @@ -144,7 +145,13 @@ org.junit.jupiter junit-jupiter-api - 5.10.2 + ${junit-jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-params + ${junit-jupiter.version} test diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/exception/EncryptionException.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/exception/EncryptionException.java deleted file mode 100644 index 1c403689..00000000 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/exception/EncryptionException.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright © 2024 XDEV Software (https://xdev.software) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://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. - */ -package software.xdev.bzst.dip.client.exception; - -import software.xdev.bzst.dip.client.model.configuration.BzstDipConfiguration; - - -/** - * Is used for exception that occur during encryption in - * {@link software.xdev.bzst.dip.client.util.WebClientUtil#createRequestToken(BzstDipConfiguration)}. - */ -public class EncryptionException extends RuntimeException -{ - public EncryptionException(final String message) - { - super(message); - } - - public EncryptionException(final String message, final Throwable cause) - { - super(message, cause); - } -} diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProvider.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProvider.java index e0a68f83..71e97d73 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProvider.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProvider.java @@ -19,6 +19,9 @@ import java.security.cert.X509Certificate; +/** + * Provides a certificate and a private key to use in the {@link XmlSigner}. + */ public interface SigningProvider { X509Certificate getCertificate(); diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByJks.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByJks.java index 8154bcf2..7b7e8350 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByJks.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByJks.java @@ -28,6 +28,9 @@ import software.xdev.bzst.dip.client.exception.SigningException; +/** + * Provides a certificate and a private key to use in the {@link XmlSigner} by reading the JKS-Keystore and a password. + */ public class SigningProviderByJks implements SigningProvider { private static final Logger LOGGER = LoggerFactory.getLogger(SigningProviderByJks.class); diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByPem.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByPem.java index 64960e61..131829d1 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByPem.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByPem.java @@ -17,7 +17,7 @@ import java.io.IOException; import java.io.InputStream; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.cert.CertificateException; @@ -31,6 +31,12 @@ import software.xdev.bzst.dip.client.exception.SigningException; +/** + * Provides a certificate and a private key to use in the {@link XmlSigner} by reading two PEM files. + *

+ * Default algorithm while reading the private key is {@link DEFAULT_PRIVATE_KEY_ALGORITHM}. + *

+ */ public class SigningProviderByPem implements SigningProvider { public static final String DEFAULT_PRIVATE_KEY_ALGORITHM = "RSASSA-PSS"; @@ -40,6 +46,9 @@ public class SigningProviderByPem implements SigningProvider private X509Certificate certificate; private PrivateKey privateKey; + /** + * Uses the default algorithm while reading the private key: {@link DEFAULT_PRIVATE_KEY_ALGORITHM}. + */ public SigningProviderByPem( final String certificatePemFilePath, final String privateKeyPemFilePath @@ -65,6 +74,9 @@ public SigningProviderByPem( ); } + /** + * Uses the default algorithm while reading the private key: {@link DEFAULT_PRIVATE_KEY_ALGORITHM}. + */ public SigningProviderByPem( final Supplier certificatePemInputStream, final Supplier privateKeyPemInputStream @@ -139,7 +151,7 @@ private X509Certificate readCertificate(final InputStream certificateInputStream private PrivateKey readPrivateKey(final InputStream privateKeyInputStream) throws Exception { - final String key = new String(privateKeyInputStream.readAllBytes(), Charset.defaultCharset()); + final String key = new String(privateKeyInputStream.readAllBytes(), StandardCharsets.UTF_8); final String privateKeyPEM = key .replace("-----BEGIN PRIVATE KEY-----", "") diff --git a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ConfigurationTestUtil.java b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ConfigurationTestUtil.java new file mode 100644 index 00000000..9f9ab845 --- /dev/null +++ b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ConfigurationTestUtil.java @@ -0,0 +1,66 @@ +/* + * Copyright © 2024 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://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. + */ +package software.xdev.bzst.dip.client; + +import java.time.LocalDate; + +import software.xdev.bzst.dip.client.model.configuration.BzstDipConfiguration; +import software.xdev.bzst.dip.client.model.configuration.BzstDipConfigurationBuilder; +import software.xdev.bzst.dip.client.model.configuration.BzstDipDpiMessageType; +import software.xdev.bzst.dip.client.model.configuration.BzstDipOecdDocType; +import software.xdev.bzst.dip.client.model.message.BzstDipAddressFix; +import software.xdev.bzst.dip.client.signing.SigningProviderByJks; +import software.xdev.bzst.dip.client.signing.SigningProviderByPem; + + +public class ConfigurationTestUtil +{ + private ConfigurationTestUtil() + { + } + + public static BzstDipConfiguration getConfigurationWithJksSigning() + { + return createBuilderWithoutSigning() + .setSigningProvider(new SigningProviderByJks("DemoKeystore.jks", "test123")) + .buildAndValidate(); + } + + public static BzstDipConfiguration getConfigurationWithPemSigning() + { + return createBuilderWithoutSigning() + .setSigningProvider(new SigningProviderByPem("DemoCert.pem", "DemoKey.pem")) + .buildAndValidate(); + } + + private static BzstDipConfigurationBuilder createBuilderWithoutSigning() + { + return new BzstDipConfigurationBuilder() + .setClientId("TestClient") + .setTaxID("123") + .setTaxNumber("123") + .setSigningProvider(new SigningProviderByPem("DemoKey.pem", "DemoCert.pem")) + .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) + .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) + .setReportingPeriod(LocalDate.now()) + .setDocTypeIndic(BzstDipOecdDocType.OECD_1) + .setPlatformOperatorOrganizationName("TestOrg") + .setPlatformOperatorPlatformName("TestApp") + .setPlatformOperatorAddress( + new BzstDipAddressFix("TestCity") + ); + } +} diff --git a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ReportableSellerCsvFileParserTest.java b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ReportableSellerCsvFileParserTest.java index 981fea04..1ed7d981 100644 --- a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ReportableSellerCsvFileParserTest.java +++ b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ReportableSellerCsvFileParserTest.java @@ -16,42 +16,21 @@ package software.xdev.bzst.dip.client; import static org.junit.jupiter.api.Assertions.assertEquals; +import static software.xdev.bzst.dip.client.ConfigurationTestUtil.getConfigurationWithJksSigning; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.time.LocalDate; import java.util.List; import org.junit.jupiter.api.Test; -import software.xdev.bzst.dip.client.model.configuration.BzstDipConfiguration; -import software.xdev.bzst.dip.client.model.configuration.BzstDipConfigurationBuilder; -import software.xdev.bzst.dip.client.model.configuration.BzstDipDpiMessageType; -import software.xdev.bzst.dip.client.model.configuration.BzstDipOecdDocType; -import software.xdev.bzst.dip.client.model.message.BzstDipAddressFix; import software.xdev.bzst.dip.client.parser.ReportableSellerCsvFileParser; -import software.xdev.bzst.dip.client.signing.SigningProviderByJks; import software.xdev.bzst.dip.client.xmldocument.model.CorrectableReportableSellerType; class ReportableSellerCsvFileParserTest { - private final BzstDipConfiguration configuration = new BzstDipConfigurationBuilder() - .setClientId("TestClient") - .setTaxID("123") - .setTaxNumber("123") - .setSigningProvider(new SigningProviderByJks("DemoKeystore.jks", "test123")) - .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) - .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) - .setReportingPeriod(LocalDate.now()) - .setDocTypeIndic(BzstDipOecdDocType.OECD_1) - .setPlatformOperatorOrganizationName("TestOrg") - .setPlatformOperatorPlatformName("TestApp") - .setPlatformOperatorAddress( - new BzstDipAddressFix("TestCity") - ) - .buildAndValidate(); @Test void shouldParseSuccessfullyTest() throws IOException @@ -59,7 +38,9 @@ void shouldParseSuccessfullyTest() throws IOException final String resourceName = "src/test/resources/TestCsvData.csv"; final List reportableSeller = - ReportableSellerCsvFileParser.parseCsvData(Files.readString(Path.of(resourceName)), this.configuration); + ReportableSellerCsvFileParser.parseCsvData( + Files.readString(Path.of(resourceName)), + getConfigurationWithJksSigning()); // Check size assertEquals(2, reportableSeller.size()); diff --git a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/XmlSignerTest.java b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/XmlSignerTest.java index b5330064..c455d365 100644 --- a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/XmlSignerTest.java +++ b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/XmlSignerTest.java @@ -1,14 +1,62 @@ +/* + * Copyright © 2024 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://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. + */ package software.xdev.bzst.dip.client.signing; -import org.junit.jupiter.api.Test; +import java.util.List; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import software.xdev.bzst.dip.client.ConfigurationTestUtil; +import software.xdev.bzst.dip.client.model.configuration.BzstDipConfiguration; +import software.xdev.bzst.dip.client.xmldocument.XMLDocumentBodyCreator; +import software.xdev.bzst.dip.client.xmldocument.XMLDocumentCreator; class XmlSignerTest { + private static Stream provideConfigurations() + { + return Stream.of( + Arguments.of(ConfigurationTestUtil.getConfigurationWithJksSigning()), + Arguments.of(ConfigurationTestUtil.getConfigurationWithPemSigning()) + ); + } - @Test - void signXMLDocument() + @ParameterizedTest + @MethodSource("provideConfigurations") + void signXMLDocument(final BzstDipConfiguration configuration) { - // TODO + final XMLDocumentCreator xmlDocumentCreator = new XMLDocumentCreator(configuration); + final String unsignedXml = xmlDocumentCreator.buildXMLDocument( + List.of(), + XMLDocumentBodyCreator.createPlatformOperatorFromConfiguration(configuration) + ); + + final XmlSigner xmlSigner = new XmlSigner(configuration.getSigningProvider()); + final String signedXml = xmlSigner.signXMLDocument(unsignedXml); + + Assertions.assertNotNull(signedXml); + Assertions.assertTrue(signedXml.contains("SignedInfo")); + Assertions.assertTrue(signedXml.contains("SignatureValue")); + Assertions.assertTrue(signedXml.contains( + "CN=xdev.software,O=XDEV Software GmbH,L=city,ST=Bavaria,C=DE")); + Assertions.assertTrue(signedXml.contains("X509Certificate")); } } From a10f383de15150002f751d61203fa35d1655332c Mon Sep 17 00:00:00 2001 From: JohannesRabauer Date: Fri, 31 May 2024 08:45:10 +0200 Subject: [PATCH 3/6] Fixed merge --- .../software/xdev/ApplicationWithPem.java | 2 +- bzst-dip-java-client/pom.xml | 6 -- .../BzstDipConfigurationValidator.java | 4 -- .../client/signing/SigningProviderByJks.java | 6 +- .../client/signing/SigningProviderByPem.java | 10 ++- .../dip/client/ConfigurationTestUtil.java | 2 +- .../BzstDipConfigurationBuilderTest.java | 62 ++++--------------- 7 files changed, 24 insertions(+), 68 deletions(-) diff --git a/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithPem.java b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithPem.java index 29afa784..850f1c13 100644 --- a/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithPem.java +++ b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithPem.java @@ -39,7 +39,7 @@ public static BzstDipConfiguration createConfiguration() { return new BzstDipConfigurationBuilder() .setClientId("abcd1234-ab12-ab12-ab12-abcdef123456") - .setTaxID("123") + .setTaxID("86095742719") .setTaxNumber("123") .setSigningProvider(new SigningProviderByPem("DemoCert.pem", "DemoKey.pem")) .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) diff --git a/bzst-dip-java-client/pom.xml b/bzst-dip-java-client/pom.xml index 27d7f65f..0482be60 100644 --- a/bzst-dip-java-client/pom.xml +++ b/bzst-dip-java-client/pom.xml @@ -154,12 +154,6 @@ ${junit-jupiter.version} test
- - org.junit.jupiter - junit-jupiter-params - 5.10.2 - test - org.apache.logging.log4j log4j-slf4j2-impl diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationValidator.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationValidator.java index d15e1b5a..843ac5e4 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationValidator.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationValidator.java @@ -25,9 +25,6 @@ public class BzstDipConfigurationValidator { public static void validateConfiguration(final BzstDipConfiguration configuration) { - checkForNullOrBlank( - PropertiesSupplier.PROPERTY_NAME_CERTIFICATE_KEYSTORE_PASSWORD, - configuration.getCertificateKeystorePassword()); checkForNullOrBlank( PropertiesSupplier.PROPERTY_NAME_CLIENT_ID, configuration.getClientId()); checkForNullOrBlank( @@ -40,7 +37,6 @@ public static void validateConfiguration(final BzstDipConfiguration configuratio checkForNull(PropertiesSupplier.PROPERTY_NAME_ENVIRONMENT, configuration.getEnvironment()); checkForNull(PropertiesSupplier.PROPERTY_NAME_MESSAGE_TYPE_INDIC, configuration.getMessageTypeIndic()); checkForNull(PropertiesSupplier.PROPERTY_NAME_DOC_TYPE_INDIC, configuration.getDocType()); - checkForNull("certificate keystore input", configuration.getCertificateKeystoreInputStream()); checkForNullOrBlank( PropertiesSupplier.PROPERTY_NAME_PLATFORM_OPERATOR_ORGANIZATION, configuration.getPlatformOperatorOrganizationName()); diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByJks.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByJks.java index 7b7e8350..11bf5661 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByJks.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByJks.java @@ -20,6 +20,7 @@ import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.X509Certificate; +import java.util.Objects; import java.util.function.Supplier; import org.slf4j.Logger; @@ -49,6 +50,7 @@ public SigningProviderByJks( () -> ClassLoader.getSystemClassLoader().getResourceAsStream(certificateKeystorePath), certificateKeystorePassword ); + Objects.requireNonNull(certificateKeystorePath); } public SigningProviderByJks( @@ -56,8 +58,8 @@ public SigningProviderByJks( final String certificateKeystorePassword ) { - this.certificateKeystoreInputStream = certificateKeystoreInputStream; - this.certificateKeystorePassword = certificateKeystorePassword; + this.certificateKeystoreInputStream = Objects.requireNonNull(certificateKeystoreInputStream); + this.certificateKeystorePassword = Objects.requireNonNull(certificateKeystorePassword); } @Override diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByPem.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByPem.java index 131829d1..13395c9d 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByPem.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByPem.java @@ -24,6 +24,7 @@ import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Objects; import java.util.function.Supplier; import org.apache.hc.client5.http.utils.Base64; @@ -72,6 +73,9 @@ public SigningProviderByPem( () -> ClassLoader.getSystemClassLoader().getResourceAsStream(privateKeyPemFilePath), privateKeyAlgorithm ); + Objects.requireNonNull(certificatePemFilePath); + Objects.requireNonNull(privateKeyPemFilePath); + Objects.requireNonNull(privateKeyAlgorithm); } /** @@ -94,9 +98,9 @@ public SigningProviderByPem( final Supplier privateKeyPemInputStream, final String privateKeyAlgorithm) { - this.certificatePemInputStream = certificatePemInputStream; - this.privateKeyPemInputStream = privateKeyPemInputStream; - this.privateKeyAlgorithm = privateKeyAlgorithm; + this.certificatePemInputStream = Objects.requireNonNull(certificatePemInputStream); + this.privateKeyPemInputStream = Objects.requireNonNull(privateKeyPemInputStream); + this.privateKeyAlgorithm = Objects.requireNonNull(privateKeyAlgorithm); } @Override diff --git a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ConfigurationTestUtil.java b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ConfigurationTestUtil.java index 9f9ab845..a179e018 100644 --- a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ConfigurationTestUtil.java +++ b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ConfigurationTestUtil.java @@ -50,7 +50,7 @@ private static BzstDipConfigurationBuilder createBuilderWithoutSigning() { return new BzstDipConfigurationBuilder() .setClientId("TestClient") - .setTaxID("123") + .setTaxID("86095742719") .setTaxNumber("123") .setSigningProvider(new SigningProviderByPem("DemoKey.pem", "DemoCert.pem")) .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) diff --git a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilderTest.java b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilderTest.java index d15cff7c..920506bb 100644 --- a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilderTest.java +++ b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilderTest.java @@ -22,6 +22,7 @@ import software.xdev.bzst.dip.client.exception.ConfigurationException; import software.xdev.bzst.dip.client.model.message.BzstDipAddressFix; +import software.xdev.bzst.dip.client.signing.SigningProviderByJks; class BzstDipConfigurationBuilderTest @@ -44,9 +45,7 @@ void buildAndValidate_goodValue() .setClientId("abcd1234-ab12-ab12-ab12-abcdef123456") .setTaxID("86095742719") .setTaxNumber("123") - .setCertificateKeystoreInputStream(() -> ClassLoader.getSystemClassLoader() - .getResourceAsStream("DemoKeystore.jks")) - .setCertificateKeystorePassword("test123") + .setSigningProvider(new SigningProviderByJks("DemoKeystore.jks", "test123")) .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) .setReportingPeriod(LocalDate.now()) @@ -66,9 +65,7 @@ void buildAndValidate_missingClientId() () -> new BzstDipConfigurationBuilder() .setTaxID("86095742719") .setTaxNumber("123") - .setCertificateKeystoreInputStream(() -> ClassLoader.getSystemClassLoader() - .getResourceAsStream("DemoKeystore.jks")) - .setCertificateKeystorePassword("test123") + .setSigningProvider(new SigningProviderByJks("DemoKeystore.jks", "test123")) .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) .setReportingPeriod(LocalDate.now()) @@ -88,9 +85,7 @@ void buildAndValidate_missingTaxId() () -> new BzstDipConfigurationBuilder() .setClientId("abcd1234-ab12-ab12-ab12-abcdef123456") .setTaxNumber("123") - .setCertificateKeystoreInputStream(() -> ClassLoader.getSystemClassLoader() - .getResourceAsStream("DemoKeystore.jks")) - .setCertificateKeystorePassword("test123") + .setSigningProvider(new SigningProviderByJks("DemoKeystore.jks", "test123")) .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) .setReportingPeriod(LocalDate.now()) @@ -110,9 +105,7 @@ void buildAndValidate_missingTaxNumber() () -> new BzstDipConfigurationBuilder() .setClientId("abcd1234-ab12-ab12-ab12-abcdef123456") .setTaxID("86095742719") - .setCertificateKeystoreInputStream(() -> ClassLoader.getSystemClassLoader() - .getResourceAsStream("DemoKeystore.jks")) - .setCertificateKeystorePassword("test123") + .setSigningProvider(new SigningProviderByJks("DemoKeystore.jks", "test123")) .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) .setReportingPeriod(LocalDate.now()) @@ -125,7 +118,7 @@ void buildAndValidate_missingTaxNumber() } @Test - void buildAndValidate_missingKeystore() + void buildAndValidate_missingSigningProvider() { Assertions.assertThrows( ConfigurationException.class, @@ -133,29 +126,6 @@ void buildAndValidate_missingKeystore() .setClientId("abcd1234-ab12-ab12-ab12-abcdef123456") .setTaxID("86095742719") .setTaxNumber("123") - .setCertificateKeystorePassword("test123") - .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) - .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) - .setReportingPeriod(LocalDate.now()) - .setDocTypeIndic(BzstDipOecdDocType.OECD_1) - .setPlatformOperatorOrganizationName("TestOrg") - .setPlatformOperatorPlatformName("TestApp") - .setPlatformOperatorAddress(new BzstDipAddressFix("TestCity")) - .buildAndValidate() - ); - } - - @Test - void buildAndValidate_missingKeystorePassword() - { - Assertions.assertThrows( - ConfigurationException.class, - () -> new BzstDipConfigurationBuilder() - .setClientId("abcd1234-ab12-ab12-ab12-abcdef123456") - .setTaxID("86095742719") - .setTaxNumber("123") - .setCertificateKeystoreInputStream(() -> ClassLoader.getSystemClassLoader() - .getResourceAsStream("DemoKeystore.jks")) .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) .setReportingPeriod(LocalDate.now()) @@ -175,9 +145,7 @@ void buildAndValidate_defaultRealmBaseUrl() .setClientId("abcd1234-ab12-ab12-ab12-abcdef123456") .setTaxID("86095742719") .setTaxNumber("123") - .setCertificateKeystoreInputStream(() -> ClassLoader.getSystemClassLoader() - .getResourceAsStream("DemoKeystore.jks")) - .setCertificateKeystorePassword("test123") + .setSigningProvider(new SigningProviderByJks("DemoKeystore.jks", "test123")) .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) .setReportingPeriod(LocalDate.now()) .setDocTypeIndic(BzstDipOecdDocType.OECD_1) @@ -197,9 +165,7 @@ void buildAndValidate_missingMessageTypeIndic() .setClientId("abcd1234-ab12-ab12-ab12-abcdef123456") .setTaxID("86095742719") .setTaxNumber("123") - .setCertificateKeystoreInputStream(() -> ClassLoader.getSystemClassLoader() - .getResourceAsStream("DemoKeystore.jks")) - .setCertificateKeystorePassword("test123") + .setSigningProvider(new SigningProviderByJks("DemoKeystore.jks", "test123")) .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) .setReportingPeriod(LocalDate.now()) .setDocTypeIndic(BzstDipOecdDocType.OECD_1) @@ -219,9 +185,7 @@ void buildAndValidate_wrongReportingPeriod() .setClientId("abcd1234-ab12-ab12-ab12-abcdef123456") .setTaxID("86095742719") .setTaxNumber("123") - .setCertificateKeystoreInputStream(() -> ClassLoader.getSystemClassLoader() - .getResourceAsStream("DemoKeystore.jks")) - .setCertificateKeystorePassword("test123") + .setSigningProvider(new SigningProviderByJks("DemoKeystore.jks", "test123")) .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) .setReportingPeriod(LocalDate.now().plusDays(1)) @@ -242,9 +206,7 @@ void buildAndValidate_missingReportingPeriod() .setClientId("abcd1234-ab12-ab12-ab12-abcdef123456") .setTaxID("86095742719") .setTaxNumber("123") - .setCertificateKeystoreInputStream(() -> ClassLoader.getSystemClassLoader() - .getResourceAsStream("DemoKeystore.jks")) - .setCertificateKeystorePassword("test123") + .setSigningProvider(new SigningProviderByJks("DemoKeystore.jks", "test123")) .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) .setDocTypeIndic(BzstDipOecdDocType.OECD_1) @@ -264,9 +226,7 @@ void buildAndValidate_missingAddress() .setClientId("abcd1234-ab12-ab12-ab12-abcdef123456") .setTaxID("86095742719") .setTaxNumber("123") - .setCertificateKeystoreInputStream(() -> ClassLoader.getSystemClassLoader() - .getResourceAsStream("DemoKeystore.jks")) - .setCertificateKeystorePassword("test123") + .setSigningProvider(new SigningProviderByJks("DemoKeystore.jks", "test123")) .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) .setReportingPeriod(LocalDate.now()) From f24045a8da4c6d51ceabd376a9a70dfbf20b8d60 Mon Sep 17 00:00:00 2001 From: JohannesRabauer Date: Wed, 8 Jan 2025 15:05:11 +0100 Subject: [PATCH 4/6] Merge fix --- .../software/xdev/ApplicationWithCesop.java | 4 +-- .../software/xdev/ApplicationWithDac7.java | 1 + .../software/xdev/ApplicationWithPem.java | 6 ++-- .../xdev/bzst/dip/client/BzstDipClient.java | 8 ++--- .../configuration/BzstDipConfiguration.java | 2 +- .../BzstDipConfigurationBuilder.java | 13 ++------ .../webclient/BearerTokenRequester.java | 30 ------------------- .../dip/client/ConfigurationTestUtil.java | 4 +-- .../ReportableSellerCsvFileParserTest.java | 6 ++-- .../BzstDipConfigurationBuilderTest.java | 7 ++--- 10 files changed, 23 insertions(+), 58 deletions(-) diff --git a/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithCesop.java b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithCesop.java index 92d47ed7..468d2ce3 100644 --- a/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithCesop.java +++ b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithCesop.java @@ -48,6 +48,7 @@ import software.xdev.bzst.dip.client.model.message.dac7.BzstDipCompleteResult; import software.xdev.bzst.dip.client.model.message.dac7.BzstDipCountryCode; import software.xdev.bzst.dip.client.model.message.dac7.BzstDipCurrency; +import software.xdev.bzst.dip.client.signing.SigningProviderByJks; @SuppressWarnings("checkstyle:MagicNumber") @@ -75,8 +76,7 @@ public static BzstDipConfiguration createConfiguration() .setClientId("abcd1234-ab12-ab12-ab12-abcdef123456") .setTaxID("86095742719") .setTaxNumber("123") - .setCertificateKeystoreInputStream(() -> ClassLoader.getSystemClassLoader() - .getResourceAsStream("DemoKeystore.jks")) + .setSigningProvider(new SigningProviderByJks("DemoKeystore.jks", "test123")) .setCertificateKeystorePassword("test123") .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) .setMessageTypeIndicCesop(BzstCesopMessageTypeIndicEnum.CESOP_101) diff --git a/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithDac7.java b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithDac7.java index 99831315..bcbf5162 100644 --- a/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithDac7.java +++ b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithDac7.java @@ -26,6 +26,7 @@ import software.xdev.bzst.dip.client.model.message.dac7.BzstDipOecdLegalAddressType; import software.xdev.bzst.dip.client.model.message.dac7.BzstDipTaxes; import software.xdev.bzst.dip.client.model.message.dac7.BzstDipTin; +import software.xdev.bzst.dip.client.signing.SigningProviderByJks; @SuppressWarnings("checkstyle:MagicNumber") diff --git a/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithPem.java b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithPem.java index 850f1c13..4f97ea43 100644 --- a/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithPem.java +++ b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithPem.java @@ -11,8 +11,8 @@ import software.xdev.bzst.dip.client.model.configuration.BzstDipConfigurationBuilder; import software.xdev.bzst.dip.client.model.configuration.BzstDipDpiMessageType; import software.xdev.bzst.dip.client.model.configuration.BzstDipOecdDocType; -import software.xdev.bzst.dip.client.model.message.BzstDipAddressFix; -import software.xdev.bzst.dip.client.model.message.BzstDipCompleteResult; +import software.xdev.bzst.dip.client.model.message.dac7.BzstDipAddressFix; +import software.xdev.bzst.dip.client.model.message.dac7.BzstDipCompleteResult; import software.xdev.bzst.dip.client.signing.SigningProviderByPem; @@ -27,7 +27,7 @@ public static void main(final String[] args) final BzstDipConfiguration configuration = createConfiguration(); final BzstDipClient bzstDipClient = new BzstDipClient(configuration); final BzstDipCompleteResult bzstDipCompleteResult = - bzstDipClient.sendDipAndQueryResult(Application.createMessage()); + bzstDipClient.sendDipAndQueryResult(ApplicationWithDac7.createMessage()); LOGGER.info( "Sending dip message with transfer number {} {}", bzstDipCompleteResult.dataTransferNumber(), diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/BzstDipClient.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/BzstDipClient.java index 544bff15..00c667ca 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/BzstDipClient.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/BzstDipClient.java @@ -293,12 +293,12 @@ private BzstDipSendingResult sendDipOnlyInternal( ) { final XMLDocumentCreator xmlDocumentCreator = new XMLDocumentCreator(this.configuration); - final String signedXML = - SigningUtil.signXMLDocument( + final String signedXML = new XmlSigner(this.configuration.getSigningProvider()) + .signXMLDocument( xmlDocumentCreator.buildXMLDocument( paymentDataBodyType - ), - this.configuration); + ) + ); LOGGER.debug("Created following XML-Document:\n{}", signedXML); LOGGER.debug("XML data will now be uploaded..."); diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfiguration.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfiguration.java index 7f7fe311..6abcd3be 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfiguration.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfiguration.java @@ -19,12 +19,12 @@ import java.security.cert.X509Certificate; import java.time.LocalDate; import java.time.ZonedDateTime; -import java.util.function.Supplier; import software.xdev.bzst.dip.client.model.message.cesop.BzstCesopMessageTypeEnum; import software.xdev.bzst.dip.client.model.message.cesop.BzstCesopMessageTypeIndicEnum; import software.xdev.bzst.dip.client.model.message.dac7.BzstDipAddressFix; import software.xdev.bzst.dip.client.model.message.dac7.BzstDipCountryCode; +import software.xdev.bzst.dip.client.signing.SigningProvider; /** diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilder.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilder.java index e8fbfe46..b4615995 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilder.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilder.java @@ -19,18 +19,16 @@ import java.time.LocalDate; import java.time.ZonedDateTime; import java.util.UUID; -import java.util.function.Supplier; import software.xdev.bzst.dip.client.exception.ConfigurationException; import software.xdev.bzst.dip.client.exception.PropertyNotSetException; -import software.xdev.bzst.dip.client.model.message.BzstDipAddressFix; -import software.xdev.bzst.dip.client.signing.SigningProvider; -import software.xdev.bzst.dip.client.signing.SigningProviderByJks; -import software.xdev.bzst.dip.client.signing.SigningProviderByPem; import software.xdev.bzst.dip.client.model.message.cesop.BzstCesopMessageTypeEnum; import software.xdev.bzst.dip.client.model.message.cesop.BzstCesopMessageTypeIndicEnum; import software.xdev.bzst.dip.client.model.message.dac7.BzstDipAddressFix; import software.xdev.bzst.dip.client.model.message.dac7.BzstDipCountryCode; +import software.xdev.bzst.dip.client.signing.SigningProvider; +import software.xdev.bzst.dip.client.signing.SigningProviderByJks; +import software.xdev.bzst.dip.client.signing.SigningProviderByPem; /** @@ -164,11 +162,6 @@ public class BzstDipConfigurationBuilder */ private BzstCesopMessageTypeIndicEnum messageTypeIndicCesop; - public void setRetryQueryResultsAmount(final Integer retryQueryResultsAmount) - { - this.retryQueryResultsAmount = retryQueryResultsAmount; - } - public BzstDipConfigurationBuilder setReportingPeriodCesopQuarter(final int reportingPeriodCesopQuarter) { this.reportingPeriodCesopQuarter = reportingPeriodCesopQuarter; diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/webclient/BearerTokenRequester.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/webclient/BearerTokenRequester.java index f70fc459..5b9aad65 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/webclient/BearerTokenRequester.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/webclient/BearerTokenRequester.java @@ -113,35 +113,5 @@ private String createRequestToken() .notBefore(new Date(System.currentTimeMillis() - Duration.ofMinutes(1).toMillis())) .signWith(privateKey, Jwts.SIG.RS256) .compact(); - try(final InputStream keystoreInputStream = this.configuration.getCertificateKeystoreInputStream().get()) - { - final KeyStore.PrivateKeyEntry privateKeyEntry = SigningUtil.getPrivateKeyEntry( - keystoreInputStream, - this.configuration.getKeyStorePrivateKeyAlias(), - this.configuration.getCertificateKeystorePassword(), - SigningUtil.KEYSTORE_TYPE - ); - - final PrivateKey privateKey = privateKeyEntry.getPrivateKey(); - final String clientId = this.configuration.getClientId(); - LOGGER.debug("Using client id: {}", clientId); - - return Jwts.builder() - .issuer(clientId) - .subject(clientId) - .audience().add( - this.configuration.getRealmEnvironmentBaseUrl() + MDS_POSTFIX) - .and() - .issuedAt(new Date()) - .expiration(new Date(System.currentTimeMillis() + Duration.ofMinutes(5).toMillis())) - .id(UUID.randomUUID().toString()) - .notBefore(new Date(System.currentTimeMillis() - Duration.ofMinutes(1).toMillis())) - .signWith(privateKey, Jwts.SIG.RS256) - .compact(); - } - catch(final IOException ioException) - { - throw new EncryptionException("An error occurred while creating the request token.", ioException); - } } } diff --git a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ConfigurationTestUtil.java b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ConfigurationTestUtil.java index a179e018..c496b505 100644 --- a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ConfigurationTestUtil.java +++ b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ConfigurationTestUtil.java @@ -21,12 +21,12 @@ import software.xdev.bzst.dip.client.model.configuration.BzstDipConfigurationBuilder; import software.xdev.bzst.dip.client.model.configuration.BzstDipDpiMessageType; import software.xdev.bzst.dip.client.model.configuration.BzstDipOecdDocType; -import software.xdev.bzst.dip.client.model.message.BzstDipAddressFix; +import software.xdev.bzst.dip.client.model.message.dac7.BzstDipAddressFix; import software.xdev.bzst.dip.client.signing.SigningProviderByJks; import software.xdev.bzst.dip.client.signing.SigningProviderByPem; -public class ConfigurationTestUtil +public final class ConfigurationTestUtil { private ConfigurationTestUtil() { diff --git a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ReportableSellerCsvFileParserTest.java b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ReportableSellerCsvFileParserTest.java index a6e1444d..79cbb552 100644 --- a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ReportableSellerCsvFileParserTest.java +++ b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ReportableSellerCsvFileParserTest.java @@ -23,6 +23,7 @@ import java.io.StringReader; import java.nio.file.Files; import java.nio.file.Path; +import java.time.LocalDate; import java.util.List; import org.junit.jupiter.api.Assertions; @@ -41,6 +42,8 @@ import software.xdev.bzst.dip.client.model.configuration.BzstDipOecdDocType; import software.xdev.bzst.dip.client.model.message.dac7.BzstDipAddressFix; import software.xdev.bzst.dip.client.parser.ReportableSellerCsvFileParser; +import software.xdev.bzst.dip.client.signing.SigningProvider; +import software.xdev.bzst.dip.client.signing.SigningProviderByPem; import software.xdev.bzst.dip.client.xmldocument.model.CorrectableReportableSellerType; @@ -58,8 +61,7 @@ class ReportableSellerCsvFileParserTest .setTaxID("86095742719") .setTaxNumber("123") .setCertificateKeystorePassword("test123") - .setCertificateKeystoreInputStream(() -> ClassLoader.getSystemClassLoader() - .getResourceAsStream("DemoKeystore.jks")) + .setSigningProvider(new SigningProviderByPem("DemoKey.pem", "DemoCert.pem")) .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) .setReportingPeriod(LocalDate.now()) diff --git a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilderTest.java b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilderTest.java index 6bfbe4a0..b5da2f72 100644 --- a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilderTest.java +++ b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilderTest.java @@ -21,9 +21,9 @@ import org.junit.jupiter.api.Test; import software.xdev.bzst.dip.client.exception.ConfigurationException; -import software.xdev.bzst.dip.client.model.message.BzstDipAddressFix; -import software.xdev.bzst.dip.client.signing.SigningProviderByJks; import software.xdev.bzst.dip.client.model.message.dac7.BzstDipAddressFix; +import software.xdev.bzst.dip.client.signing.SigningProviderByJks; +import software.xdev.bzst.dip.client.signing.SigningProviderByPem; @SuppressWarnings("MethodName") @@ -169,9 +169,8 @@ void buildAndValidate_cesop() .setClientId("abcd1234-ab12-ab12-ab12-abcdef123456") .setTaxID("86095742719") .setTaxNumber("123") - .setCertificateKeystoreInputStream(() -> ClassLoader.getSystemClassLoader() - .getResourceAsStream("DemoKeystore.jks")) .setCertificateKeystorePassword("test123") + .setSigningProvider(new SigningProviderByPem("DemoKey.pem", "DemoCert.pem")) .setMessageTypeIndic(BzstDipDpiMessageType.DPI_401) .setReportingPeriod(LocalDate.now()) .setDocTypeIndic(BzstDipOecdDocType.OECD_1) From 8bd8faa48eb707efeb07617ec5e2ca4110b5bcbd Mon Sep 17 00:00:00 2001 From: JohannesRabauer Date: Wed, 8 Jan 2025 15:06:29 +0100 Subject: [PATCH 5/6] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45a0e888..2b67a05e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ * Now supports the CESOP-Format (and the DAC7-Format). * Uses a client that is auto generated by OpenAPI. This makes the library more robust for future changes of the API. +* Certificates can now be defined with a ``SigningProvider``. # 1.0.3 From 7509e1e432fb30fe48ca8f8665ad5ae719da45ec Mon Sep 17 00:00:00 2001 From: JohannesRabauer Date: Wed, 8 Jan 2025 15:19:05 +0100 Subject: [PATCH 6/6] Fix checkstyle --- .../BzstDipConfigurationBuilder.java | 74 +++++++------------ .../ReportableSellerCsvFileParserTest.java | 1 - .../signing/SigningProviderByJksTest.java | 4 +- 3 files changed, 29 insertions(+), 50 deletions(-) diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilder.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilder.java index b4615995..b32dd494 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilder.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/BzstDipConfigurationBuilder.java @@ -34,7 +34,7 @@ /** * Builder construct for the {@link BzstDipConfiguration}. */ -@SuppressWarnings({"unused", "UnusedReturnValue"}) +@SuppressWarnings({"unused", "UnusedReturnValue", "PMD.GodClass"}) public class BzstDipConfigurationBuilder { public static final int DEFAULT_DELAY_BEFORE_CHECKING_RESULTS_IN_MILLIS = 1_000; @@ -436,38 +436,31 @@ public BzstDipConfiguration buildAndValidate() this.getSetPropertyOrReadFromFileTransmittingCountry( this.transmittingCountry, PropertiesSupplier.PROPERTY_NAME_TRANSMITTING_COUNTRY, - BzstDipCountryCode.DE - ), + BzstDipCountryCode.DE), this.getSetPropertyOrReadFromFileMessageType( this.messageType, PropertiesSupplier.PROPERTY_NAME_MESSAGE_TYPE, - BzstCesopMessageTypeEnum.PMT - ), + BzstCesopMessageTypeEnum.PMT), this.getSetPropertyOrReadFromFile( this.messageRefId, PropertiesSupplier.PROPERTY_NAME_MESSAGE_REF_ID, - UUID.randomUUID().toString() - ), + UUID.randomUUID().toString()), this.getSetPropertyOrReadFromFile( this.reportingPeriodCesopYear, PropertiesSupplier.PROPERTY_NAME_REPORTING_PERIOD_CESOP_YEAR, - String.valueOf(LocalDate.now().getYear()) - ), + String.valueOf(LocalDate.now().getYear())), this.getSetPropertyOrReadFromFileInteger( this.reportingPeriodCesopQuarter, PropertiesSupplier.PROPERTY_NAME_REPORTING_PERIOD_CESOP_QUARTER, - 1 - ), + 1), this.getSetPropertyOrReadFromFileTimestamp( this.timestamp, PropertiesSupplier.PROPERTY_NAME_TIMESTAMP, - ZonedDateTime.now() - ), + ZonedDateTime.now()), this.getSetPropertyOrReadFromFileMessageTypeIndicCesop( this.messageTypeIndicCesop, PropertiesSupplier.PROPERTY_NAME_MESSAGE_TYPE_INDIC, - BzstCesopMessageTypeIndicEnum.CESOP_100 - ), + BzstCesopMessageTypeIndicEnum.CESOP_100), this.getSetPropertyOrReadFromFileApplicationCode( this.applicationCode, PropertiesSupplier.PROPERTY_NAME_APPLICATION_CODE, @@ -525,32 +518,26 @@ public BzstDipConfiguration buildAndValidate() this.getSetPropertyOrReadFromFileDuration( this.delayInBetweenResultChecks, PropertiesSupplier.PROPERTY_NAME_DELAY_IN_BETWEEN_RESULT_CHECKS_IN_MS, - Duration.ofMillis(DEFAULT_DELAY_IN_BETWEEN_RESULTS_CHECKS_IN_MILLIS)) - ), + Duration.ofMillis(DEFAULT_DELAY_IN_BETWEEN_RESULTS_CHECKS_IN_MILLIS))), this.getSetPropertyOrReadFromFile( this.platformOperatorOrganizationName, PropertiesSupplier.PROPERTY_NAME_PLATFORM_OPERATOR_ORGANIZATION), this.getSetPropertyOrReadFromFile( this.platformOperatorPlatformName, PropertiesSupplier.PROPERTY_NAME_PLATFORM_OPERATOR_PLATFORM), - this.getSetPropertyOrReadFromFileAddress(this.platformOperatorAddress) - ); + this.getSetPropertyOrReadFromFileAddress(this.platformOperatorAddress)); BzstDipConfigurationValidator.validateConfiguration(configuration); return configuration; } private void validateConfiguration(final BzstDipConfiguration configuration) { - if( - configuration.getDocType().isNewTransmission() - && (configuration.getPlatformOperatorDocRefId() == null - || configuration.getPlatformOperatorDocRefId().isBlank()) - ) + if(configuration.getDocType().isNewTransmission() && (configuration.getPlatformOperatorDocRefId() == null + || configuration.getPlatformOperatorDocRefId().isBlank())) { throw new ConfigurationException( PropertiesSupplier.PROPERTY_NAME_PLATFORM_OPERATOR_DOC_REF_ID, - "When sending a new transmission (OECD_0) a DocRefId must be set!" - ); + "When sending a new transmission (OECD_0) a DocRefId must be set!"); } } @@ -577,7 +564,9 @@ private SigningProvider getSigningProvider(final SigningProvider builderProperty private SigningProviderByJks createJksKeyProvider() { final String jksKeystorePassword = - this.propertiesSupplier.getPropertyFromConfig(PropertiesSupplier.PROPERTY_NAME_SIGNING_JKS_KEYSTORE_PASSWORD); + this.propertiesSupplier.getPropertyFromConfig( + PropertiesSupplier.PROPERTY_NAME_SIGNING_JKS_KEYSTORE_PASSWORD + ); final String jksKeystoreFile = this.propertiesSupplier.getPropertyFromConfig(PropertiesSupplier.PROPERTY_NAME_SIGNING_JKS_KEYSTORE_FILE); if(jksKeystorePassword == null && jksKeystoreFile == null) @@ -586,10 +575,7 @@ private SigningProviderByJks createJksKeyProvider() } if(jksKeystorePassword != null && jksKeystoreFile != null) { - return new SigningProviderByJks( - jksKeystoreFile, - jksKeystorePassword - ); + return new SigningProviderByJks(jksKeystoreFile, jksKeystorePassword); } if(jksKeystoreFile == null) { @@ -607,20 +593,20 @@ private SigningProviderByPem createPemKeyProvider() PropertiesSupplier.PROPERTY_NAME_SIGNING_PEM_SIGNATURE_ALGORITHM, SigningProviderByPem.DEFAULT_PRIVATE_KEY_ALGORITHM); final String pemCertificateFile = - this.propertiesSupplier.getPropertyFromConfig(PropertiesSupplier.PROPERTY_NAME_SIGNING_PEM_CERTIFICATE_FILE); + this.propertiesSupplier.getPropertyFromConfig( + PropertiesSupplier.PROPERTY_NAME_SIGNING_PEM_CERTIFICATE_FILE + ); final String pemPrivateKeyFile = - this.propertiesSupplier.getPropertyFromConfig(PropertiesSupplier.PROPERTY_NAME_SIGNING_PEM_PRIVATE_KEY_FILE); + this.propertiesSupplier.getPropertyFromConfig( + PropertiesSupplier.PROPERTY_NAME_SIGNING_PEM_PRIVATE_KEY_FILE + ); if(pemCertificateFile == null && pemPrivateKeyFile == null) { return null; } if(pemCertificateFile != null && pemPrivateKeyFile != null) { - return new SigningProviderByPem( - pemCertificateFile, - pemPrivateKeyFile, - signatureAlgorithm - ); + return new SigningProviderByPem(pemCertificateFile, pemPrivateKeyFile, signatureAlgorithm); } if(pemCertificateFile == null) { @@ -667,8 +653,7 @@ private BzstDipAddressFix getSetPropertyOrReadFromFileAddress(final BzstDipAddre this.getSetPropertyOrReadFromFile( null, PropertiesSupplier.PROPERTY_NAME_PLATFORM_OPERATOR_ADDRESS_CITY), - null - ); + null); } private LocalDate getSetPropertyOrReadFromFileDate( @@ -750,9 +735,7 @@ private BzstDipOecdDocType getSetPropertyOrReadFromFileOecdDocType( { return builderProperty; } - return BzstDipOecdDocType.valueOf(this.getSetPropertyOrReadFromFile( - null, - propertyNameInFile)); + return BzstDipOecdDocType.valueOf(this.getSetPropertyOrReadFromFile(null, propertyNameInFile)); } private BzstDipDpiMessageType getSetPropertyOrReadFromFileDpiMessageType( @@ -763,10 +746,7 @@ private BzstDipDpiMessageType getSetPropertyOrReadFromFileDpiMessageType( { return builderProperty; } - final String propertyValue = this.getSetPropertyOrReadFromFile( - null, - propertyNameInFile, - null); + final String propertyValue = this.getSetPropertyOrReadFromFile(null, propertyNameInFile, null); if(propertyValue != null) { return BzstDipDpiMessageType.valueOf(propertyValue); diff --git a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ReportableSellerCsvFileParserTest.java b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ReportableSellerCsvFileParserTest.java index 79cbb552..32fe3a02 100644 --- a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ReportableSellerCsvFileParserTest.java +++ b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ReportableSellerCsvFileParserTest.java @@ -42,7 +42,6 @@ import software.xdev.bzst.dip.client.model.configuration.BzstDipOecdDocType; import software.xdev.bzst.dip.client.model.message.dac7.BzstDipAddressFix; import software.xdev.bzst.dip.client.parser.ReportableSellerCsvFileParser; -import software.xdev.bzst.dip.client.signing.SigningProvider; import software.xdev.bzst.dip.client.signing.SigningProviderByPem; import software.xdev.bzst.dip.client.xmldocument.model.CorrectableReportableSellerType; diff --git a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/SigningProviderByJksTest.java b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/SigningProviderByJksTest.java index 3ea2c999..052ef9a3 100644 --- a/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/SigningProviderByJksTest.java +++ b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/SigningProviderByJksTest.java @@ -48,7 +48,7 @@ void getPrivateKey() } @Test - void getPrivateKey_wrongPassword() + void getPrivateKeyWrongPassword() { final SigningProviderByJks signingProviderByJks = new SigningProviderByJks( CERTIFICATE_KEYSTORE_PATH, @@ -61,7 +61,7 @@ void getPrivateKey_wrongPassword() } @Test - void getCertificate_wrongPassword() + void getCertificateWrongPassword() { final SigningProviderByJks signingProviderByJks = new SigningProviderByJks( CERTIFICATE_KEYSTORE_PATH,