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 diff --git a/README.md b/README.md index 35d86a9c..c5485384 100644 --- a/README.md +++ b/README.md @@ -40,19 +40,32 @@ Our library validates each request through these XSD find errors before they are See the [examples in the demo package](./bzst-dip-java-client-demo/src/main/java/software/xdev/). -### Create keystore file +### Create certificate For authentification at the BZST you have to create a public- and private-key. First you have to create a **PEM** file as described on the [BZST Website](https://www.bzst.de/DE/Service/Portalinformation/Massendaten/DIP/dip_node.html) (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 ``` -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" @@ -71,13 +84,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/) @@ -99,9 +105,7 @@ public static BzstDipConfiguration createConfiguration() .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()) 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 ff896c8c..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") @@ -53,9 +54,7 @@ public static BzstDipConfiguration createConfiguration() .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()) 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..4f97ea43 --- /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.dac7.BzstDipAddressFix; +import software.xdev.bzst.dip.client.model.message.dac7.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(ApplicationWithDac7.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("86095742719") + .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 714fdab8..8e42906c 100644 Binary files a/bzst-dip-java-client-demo/src/main/resources/DemoKeystore.jks and b/bzst-dip-java-client-demo/src/main/resources/DemoKeystore.jks differ diff --git a/bzst-dip-java-client-demo/src/main/resources/app.properties b/bzst-dip-java-client-demo/src/main/resources/app.properties index af7e7fd0..9327f104 100644 --- a/bzst-dip-java-client-demo/src/main/resources/app.properties +++ b/bzst-dip-java-client-demo/src/main/resources/app.properties @@ -8,8 +8,8 @@ application.code= message.type=DPI402 reporting.period=2023-12-31 doc.type=OECD2 -certificate.keystore.password=test123 -certificate.keystore.file=DemoKeystore.jks +signing.jks.keystore.password=test123 +signing.jks.keystore.file=DemoKeystore.jks delay.before.checking.results.in.millis= retry.query.results.amount= diff --git a/bzst-dip-java-client/pom.xml b/bzst-dip-java-client/pom.xml index 1df116bb..6f849833 100644 --- a/bzst-dip-java-client/pom.xml +++ b/bzst-dip-java-client/pom.xml @@ -57,6 +57,7 @@ src/generated/** + 5.10.2 @@ -149,13 +150,13 @@ org.junit.jupiter junit-jupiter-api - 5.10.3 + ${junit-jupiter.version} test org.junit.jupiter junit-jupiter-params - 5.10.3 + ${junit-jupiter.version} test 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 4f193f55..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 @@ -33,7 +33,7 @@ import software.xdev.bzst.dip.client.model.message.dac7.BzstDipSendingResult; import software.xdev.bzst.dip.client.model.message.dac7.BzstDipSingleTransferResult; import software.xdev.bzst.dip.client.parser.ReportableSellerCsvFileParser; -import software.xdev.bzst.dip.client.util.SigningUtil; +import software.xdev.bzst.dip.client.signing.XmlSigner; import software.xdev.bzst.dip.client.webclient.WebClient; import software.xdev.bzst.dip.client.xmldocument.XMLDocumentBodyCreator; import software.xdev.bzst.dip.client.xmldocument.XMLDocumentCreator; @@ -267,13 +267,13 @@ 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( correctableReportableSellerTypes, correctablePlatformOperatorType - ), - this.configuration); + ) + ); LOGGER.debug("Created following XML-Document:\n{}", signedXML); LOGGER.debug("XML data will now be uploaded..."); @@ -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/exception/SigningException.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/exception/SigningException.java index da9c8600..4bf2a59d 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/exception/SigningException.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/exception/SigningException.java @@ -15,11 +15,11 @@ */ package software.xdev.bzst.dip.client.exception; -import software.xdev.bzst.dip.client.util.SigningUtil; +import software.xdev.bzst.dip.client.signing.XmlSigner; /** - * Is used while signing HTTP requests in {@link SigningUtil}. + * Is used while signing HTTP requests in {@link XmlSigner}. */ public class SigningException extends RuntimeException { 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 fd2e346a..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 @@ -15,15 +15,16 @@ */ package software.xdev.bzst.dip.client.model.configuration; -import java.io.InputStream; +import java.security.PrivateKey; +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; /** @@ -123,8 +124,7 @@ public enum SupportedApplicationCode private final String keyStorePrivateKeyAlias; /** * Is used for identifying this client to the BZST API. A valid issuer/clientId is defined by the BZST and must - * have - * been received from them. + * have been received from them. *

* See Kommunikationshandbuch DIP-Standard 1.4 - Section 2.2.1:
@@ -195,9 +195,14 @@ public enum SupportedApplicationCode private final BzstDipOecdDocType docType; /** - * Defines the input of which the keystore is read. This can be any input as long as it is an {@link InputStream}. + * Defines a way to get a {@link X509Certificate} and an {@link PrivateKey} for signing the xml to send. + *

+ * 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; /** * Must get set if {@link #docType} is {@link BzstDipOecdDocType#OECD_0}.
The id references the xml document @@ -247,9 +252,9 @@ 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, @@ -274,9 +279,9 @@ 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; @@ -343,9 +348,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 91d04f3d..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 @@ -15,24 +15,26 @@ */ package software.xdev.bzst.dip.client.model.configuration; -import java.io.InputStream; import java.time.Duration; 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.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; /** * 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; @@ -93,9 +95,9 @@ public class BzstDipConfigurationBuilder */ private String platformOperatorCorrDocRefId; /** - * @see BzstDipConfiguration#getCertificateKeystoreInputStream() + * @see BzstDipConfiguration#getSigningProvider() */ - private Supplier certificateKeystoreInputStream; + private SigningProvider signingProvider; /** * @see BzstDipQueryResultConfiguration#delayBeforeCheckingResults */ @@ -160,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; @@ -362,7 +359,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; @@ -379,13 +376,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; } @@ -440,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, @@ -508,6 +497,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, @@ -516,9 +506,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, @@ -531,30 +518,103 @@ 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 Supplier getInputStreamSupplier( - final Supplier builderProperty, - final String propertyNameInFile) + private void validateConfiguration(final BzstDipConfiguration configuration) + { + 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!"); + } + } + + 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) @@ -593,8 +653,7 @@ private BzstDipAddressFix getSetPropertyOrReadFromFileAddress(final BzstDipAddre this.getSetPropertyOrReadFromFile( null, PropertiesSupplier.PROPERTY_NAME_PLATFORM_OPERATOR_ADDRESS_CITY), - null - ); + null); } private LocalDate getSetPropertyOrReadFromFileDate( @@ -676,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( @@ -689,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/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 8d41e29e..29849f4c 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 @@ -29,9 +29,6 @@ private 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( @@ -46,7 +43,6 @@ public static void validateConfiguration(final BzstDipConfiguration configuratio PropertiesSupplier.PROPERTY_NAME_REALM_ENVIRONMENT_BASE_URL, configuration.getRealmEnvironmentBaseUrl()); checkForNull(PropertiesSupplier.PROPERTY_NAME_ENVIRONMENT, configuration.getEnvironment()); 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/model/configuration/PropertiesSupplier.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/configuration/PropertiesSupplier.java index d12dea18..11b3feac 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,6 +29,11 @@ @SuppressWarnings({"unused", "UnusedReturnValue"}) public class PropertiesSupplier { + 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_CERTIFICATE_KEYSTORE_PASSWORD = "certificate.keystore.password"; public static final String PROPERTY_NAME_KEYSTORE_PRIVATE_KEY_ALIAS = "certificate.keystore.private.key.alias"; public static final String PROPERTY_NAME_CERTIFICATE_KEYSTORE_FILE = "certificate.keystore.file"; 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/signing/SigningProvider.java similarity index 58% rename from bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/exception/EncryptionException.java rename to bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProvider.java index 689275ce..71e97d73 100644 --- 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/signing/SigningProvider.java @@ -13,23 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package software.xdev.bzst.dip.client.exception; +package software.xdev.bzst.dip.client.signing; -import software.xdev.bzst.dip.client.webclient.BearerTokenRequester; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; /** - * Is used for exception that occur during encryption in {@link BearerTokenRequester#getAccessToken()}. + * Provides a certificate and a private key to use in the {@link XmlSigner}. */ -public class EncryptionException extends RuntimeException +public interface SigningProvider { - public EncryptionException(final String message) - { - super(message); - } + X509Certificate getCertificate(); - public EncryptionException(final String message, final Throwable cause) - { - super(message, cause); - } + 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..11bf5661 --- /dev/null +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByJks.java @@ -0,0 +1,137 @@ +/* + * 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.Objects; +import java.util.function.Supplier; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +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); + 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 + ); + Objects.requireNonNull(certificateKeystorePath); + } + + public SigningProviderByJks( + final Supplier certificateKeystoreInputStream, + final String certificateKeystorePassword + ) + { + this.certificateKeystoreInputStream = Objects.requireNonNull(certificateKeystoreInputStream); + this.certificateKeystorePassword = Objects.requireNonNull(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..13395c9d --- /dev/null +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/signing/SigningProviderByPem.java @@ -0,0 +1,171 @@ +/* + * 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.StandardCharsets; +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.Objects; +import java.util.function.Supplier; + +import org.apache.hc.client5.http.utils.Base64; + +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"; + private final Supplier certificatePemInputStream; + private final Supplier privateKeyPemInputStream; + private final String privateKeyAlgorithm; + 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 + ) + { + 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 + ); + Objects.requireNonNull(certificatePemFilePath); + Objects.requireNonNull(privateKeyPemFilePath); + Objects.requireNonNull(privateKeyAlgorithm); + } + + /** + * Uses the default algorithm while reading the private key: {@link DEFAULT_PRIVATE_KEY_ALGORITHM}. + */ + 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 = Objects.requireNonNull(certificatePemInputStream); + this.privateKeyPemInputStream = Objects.requireNonNull(privateKeyPemInputStream); + this.privateKeyAlgorithm = Objects.requireNonNull(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(), StandardCharsets.UTF_8); + + 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 827503fb..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,23 +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.getKeyStorePrivateKeyAlias(), - 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."); } @@ -126,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 @@ -140,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, @@ -157,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 { @@ -173,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..."); @@ -206,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. @@ -216,38 +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 keystorePrivateKeyEntryAlias, - 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( - keystorePrivateKeyEntryAlias, - 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 51b3d52d..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,35 +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.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); - } + + 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/ConfigurationTestUtil.java b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/ConfigurationTestUtil.java new file mode 100644 index 00000000..c496b505 --- /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.dac7.BzstDipAddressFix; +import software.xdev.bzst.dip.client.signing.SigningProviderByJks; +import software.xdev.bzst.dip.client.signing.SigningProviderByPem; + + +public final 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("86095742719") + .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 4b184b45..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 @@ -16,6 +16,7 @@ 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.io.Reader; @@ -41,12 +42,14 @@ 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.SigningProviderByPem; import software.xdev.bzst.dip.client.xmldocument.model.CorrectableReportableSellerType; @SuppressWarnings("MethodName") class ReportableSellerCsvFileParserTest { + public static final String TEST_CSV_FILE = "src/test/resources/TestCsvData.csv"; public static final String TEST_CSV_FILE_WITH_COMMA_SEPERATOR = "src/test/resources/TestCsvDataWithCommaSeperator.csv"; @@ -57,8 +60,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()) @@ -78,7 +80,8 @@ void shouldParseSuccessfullyTest() throws IOException, CsvValidationException final String csvData = Files.readString(Path.of(resourceName)); final List reportableSeller = - new ReportableSellerCsvFileParser(this.configuration).parseCsvData(csvData); + new ReportableSellerCsvFileParser(getConfigurationWithJksSigning()) + .parseCsvData(csvData); // Check size assertEquals(2, reportableSeller.size()); 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 a5284f9d..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 @@ -22,6 +22,8 @@ import software.xdev.bzst.dip.client.exception.ConfigurationException; 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") @@ -46,9 +48,7 @@ void buildAndValidate_goodValue() .setTaxID("86095742719") .setValidateTaxID(false) .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()) @@ -68,9 +68,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()) @@ -90,9 +88,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()) @@ -112,9 +108,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()) @@ -127,7 +121,7 @@ void buildAndValidate_missingTaxNumber() } @Test - void buildAndValidate_missingKeystore() + void buildAndValidate_missingSigningProvider() { Assertions.assertThrows( ConfigurationException.class, @@ -135,29 +129,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()) @@ -177,9 +148,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) @@ -200,12 +169,12 @@ 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) + .setRealmEnvironmentBaseUrl(BzstDipConfiguration.ENDPOINT_URL_TEST) .setPlatformOperatorOrganizationName("TestOrg") .setPlatformOperatorPlatformName("TestApp") .setPlatformOperatorAddress(new BzstDipAddressFix("TestCity")) @@ -222,9 +191,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)) @@ -245,9 +212,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) @@ -267,9 +232,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()) 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..052ef9a3 --- /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 getPrivateKeyWrongPassword() + { + final SigningProviderByJks signingProviderByJks = new SigningProviderByJks( + CERTIFICATE_KEYSTORE_PATH, + "wrongPwd" + ); + Assertions.assertThrows( + SigningException.class, + () -> signingProviderByJks.getPrivateKey() + ); + } + + @Test + void getCertificateWrongPassword() + { + 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..c455d365 --- /dev/null +++ b/bzst-dip-java-client/src/test/java/software/xdev/bzst/dip/client/signing/XmlSignerTest.java @@ -0,0 +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 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()) + ); + } + + @ParameterizedTest + @MethodSource("provideConfigurations") + void signXMLDocument(final BzstDipConfiguration configuration) + { + 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")); + } +} 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----- +MIIGDTCCA8GgAwIBAgIUG7/UrJcPXln7veZrUjABqaCAbh8wQQYJKoZIhvcNAQEK +MDSgDzANBglghkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEF +AKIDAgEgMGMxCzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ0wCwYDVQQH +DARjaXR5MRswGQYDVQQKDBJYREVWIFNvZnR3YXJlIEdtYkgxFjAUBgNVBAMMDXhk +ZXYuc29mdHdhcmUwHhcNMjQwNTI5MTMwODMxWhcNMzQwNTI3MTMwODMxWjBjMQsw +CQYDVQQGEwJERTEQMA4GA1UECAwHQmF2YXJpYTENMAsGA1UEBwwEY2l0eTEbMBkG +A1UECgwSWERFViBTb2Z0d2FyZSBHbWJIMRYwFAYDVQQDDA14ZGV2LnNvZnR3YXJl +MIICIDALBgkqhkiG9w0BAQoDggIPADCCAgoCggIBALhAndCGFrJXO0ZNAxmrgW32 +YdsBOEcxkXxZMZoD4VZdHMflj7QbzsYuXn2Emndpz9wUYLzowv+rItK6H/xct66f +hei9Gz4JeIOp1CGz5a6gH3eQLL7cYOtlBJoxYLQaWaCg0z5ZNRgS4h2ub8yKLBx+ ++or5ne7AjGnei0UyNSvBrWwU0b+rAF3dC3LvXuvNrOGFvMv9y0DHfQ2CEZNErWx+ +LMq/VezRPkF8qmaxPmKBZ/ODDsI3mQ0ATJSshr2vuDjIaM7ZWPG9x2H3aFaJvz64 +YPN3PjqexM6hBs6S2mrbC9Dx3x1NbxH3wqHfeqXiuPFBU3NcZxzw5qtd/p/63Sfd +YL1ouKX7WX3NDUFx1XMfZXWrOinzvNT5QPV13GpKW1ec8ZJZbfxDp/0rRp8WTY2R +XSuuWnriBWefnlFPwDAR5srHaETTZoD/ydsLNS5s3o/TRG6RgGbpzo6bZVMIZ62h ++77e78h8MiGIzWa2vsx6mgOr4/CMyxXaSKrGJmjlnRY/SuC3eNY+mS98ANL7EeE+ +PtakCG1hAjpso0OPZkUl6cyCqeb4JbDIxGckUsKw6PTczYitO78QroteDpt+cX/Q +DzbcYn8mg6jtFfCkDzXbRlhF+sJZj1zbVtmg80rnXlsJN/8sF0i3imq4A/+7i+v/ +/E1yH8dU2X4LyDWFLo2fAgMBAAGjUzBRMB0GA1UdDgQWBBQS4GBqywGNaQYc0XbR +Csw61hNmOTAfBgNVHSMEGDAWgBQS4GBqywGNaQYc0XbRCsw61hNmOTAPBgNVHRMB +Af8EBTADAQH/MEEGCSqGSIb3DQEBCjA0oA8wDQYJYIZIAWUDBAIBBQChHDAaBgkq +hkiG9w0BAQgwDQYJYIZIAWUDBAIBBQCiAwIBIAOCAgEApjV0UZZLSWFSZuRCwSu9 +QeozeRAU+/GnC0WNATJmLE+CIwXyHZPYaCIus6R9/NaRg6bdmYBgqtYBHF18YoWE +iFNUuLlkzEU0jkKPUvWg5heVeyUvGxqwRP318P3VGTtx2ovvO1rAeuRNQ5/cr0Nf +UYhxIuA9ym9aHOCgmdnsbySmX9BH6kum5Dnna1Ofk+ipM0wf+tBrGPR/0+8yvWn8 +V1gwPOypn+zBs0FlLKzAqQtLgau3PEgHdbLOfHuW0fV2KVVVwO4h5SjuUJPhJAMF +Fy5f5azQ9I5eNiaTpOMT9bI/Vn7XqvRY8YIjsSeAMcqpBygMmQFVjwRJhfyIPL1j +9MN7fF5xVBUn14C2CEwgndJ5AD3S6UrSVhRWmWs/Q4FisyPvclds+Tr2q/zpFLuX +uMwDDABJ12qw5kB8G1bAyi8TgAcHUAVh2TDK8vgN0/om68Em9HzFSEe63SKTYfEy +Mss908jGIDsrsbRoQAbdg0XDnK/3OO/M+/0tRZYAZ+gceQoFOS9d2s5StoGO7nn9 +rlSRj+hA6XlNvb6Dc6we9tHSaN1qxqK4GXymKkS6dfWuvdgxjtFr/H3kDcdzTN0u +6pEUnAFcyU/Z+/XyNRvmdl31CwstHajAdTtWGqdkQmugvhE9GMI5LYzglycAbnoN +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 00000000..8e42906c Binary files /dev/null and b/bzst-dip-java-client/src/test/resources/DemoKeystore.jks differ