From f1b4842eda1a1b1b7c97b8cfbfd97e7c8b506eda Mon Sep 17 00:00:00 2001 From: Silvio Giebl Date: Tue, 14 Nov 2023 17:59:20 +0100 Subject: [PATCH] Remove KeyStoreUtil reason: it only provides "hard coded" methods for JKS from files --- .../com/hivemq/client2/util/KeyStoreUtil.java | 91 --------- .../client2/example/Mqtt3ClientExample.java | 191 ------------------ .../client2/example/Mqtt3SmokeTest.java | 123 ----------- .../hivemq/client2/util/KeyStoreUtilTest.java | 83 -------- .../client2/util/TestKeyStoreGenerator.java | 118 ----------- src/test/resources/testkeys/client.csr | 16 -- src/test/resources/testkeys/client.key | 27 --- src/test/resources/testkeys/mosquitto/README | 31 --- .../resources/testkeys/mosquitto/cacerts.jks | Bin 822 -> 0 bytes .../mosquitto/mosquitto.org.client.crt | 18 -- .../mosquitto/mosquitto.org.client.jks | Bin 2135 -> 0 bytes .../testkeys/mosquitto/mosquitto.org.crt | 18 -- 12 files changed, 716 deletions(-) delete mode 100644 src/main/java/com/hivemq/client2/util/KeyStoreUtil.java delete mode 100644 src/test/java/com/hivemq/client2/example/Mqtt3ClientExample.java delete mode 100644 src/test/java/com/hivemq/client2/example/Mqtt3SmokeTest.java delete mode 100644 src/test/java/com/hivemq/client2/util/KeyStoreUtilTest.java delete mode 100644 src/test/java/com/hivemq/client2/util/TestKeyStoreGenerator.java delete mode 100644 src/test/resources/testkeys/client.csr delete mode 100644 src/test/resources/testkeys/client.key delete mode 100644 src/test/resources/testkeys/mosquitto/README delete mode 100644 src/test/resources/testkeys/mosquitto/cacerts.jks delete mode 100644 src/test/resources/testkeys/mosquitto/mosquitto.org.client.crt delete mode 100644 src/test/resources/testkeys/mosquitto/mosquitto.org.client.jks delete mode 100644 src/test/resources/testkeys/mosquitto/mosquitto.org.crt diff --git a/src/main/java/com/hivemq/client2/util/KeyStoreUtil.java b/src/main/java/com/hivemq/client2/util/KeyStoreUtil.java deleted file mode 100644 index 89c1de836..000000000 --- a/src/main/java/com/hivemq/client2/util/KeyStoreUtil.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2018-present HiveMQ and the HiveMQ Community - * - * 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 com.hivemq.client2.util; - -import com.hivemq.client2.internal.util.Checks; -import org.jetbrains.annotations.NotNull; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLException; -import javax.net.ssl.TrustManagerFactory; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; - -/** - * Util for creating {@link TrustManagerFactory TrustManagerFactories} and {@link KeyManagerFactory - * KeyManagerFactories}. - * - * @author Christoph Schäbel - */ -public class KeyStoreUtil { - - private static final @NotNull String KEYSTORE_TYPE = "JKS"; - - public static @NotNull TrustManagerFactory trustManagerFromKeystore( - final @NotNull File trustStoreFile, final @NotNull String trustStorePassword) throws SSLException { - - Checks.notNull(trustStoreFile, "Trust store file"); - try (final FileInputStream fileInputStream = new FileInputStream(trustStoreFile)) { - final KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE); - keyStore.load(fileInputStream, trustStorePassword.toCharArray()); - - final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init(keyStore); - return tmf; - - } catch (final KeyStoreException | IOException e) { - throw new SSLException( - "Not able to open or read trust store '" + trustStoreFile.getAbsolutePath() + "'", e); - } catch (final NoSuchAlgorithmException | CertificateException e) { - throw new SSLException( - "Not able to read certificate from trust store '" + trustStoreFile.getAbsolutePath() + "'", e); - } - } - - public static @NotNull KeyManagerFactory keyManagerFromKeystore( - final @NotNull File keyStoreFile, - final @NotNull String keyStorePassword, - final @NotNull String privateKeyPassword) throws SSLException { - - Checks.notNull(keyStoreFile, "Key store file"); - try (final FileInputStream fileInputStream = new FileInputStream(keyStoreFile)) { - final KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE); - keyStore.load(fileInputStream, keyStorePassword.toCharArray()); - - final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(keyStore, privateKeyPassword.toCharArray()); - return kmf; - - } catch (final UnrecoverableKeyException e) { - throw new SSLException( - "Not able to recover key from key store, please check your private key password and your key store password", - e); - } catch (final KeyStoreException | IOException e) { - throw new SSLException("Not able to open or read key store '" + keyStoreFile.getAbsolutePath() + "'", e); - - } catch (final NoSuchAlgorithmException | CertificateException e) { - throw new SSLException( - "Not able to read certificate from key store '" + keyStoreFile.getAbsolutePath() + "'", e); - } - } -} diff --git a/src/test/java/com/hivemq/client2/example/Mqtt3ClientExample.java b/src/test/java/com/hivemq/client2/example/Mqtt3ClientExample.java deleted file mode 100644 index 0f077af19..000000000 --- a/src/test/java/com/hivemq/client2/example/Mqtt3ClientExample.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright 2018-present HiveMQ and the HiveMQ Community - * - * 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 com.hivemq.client2.example; - -import com.hivemq.client2.mqtt.MqttClient; -import com.hivemq.client2.mqtt.MqttClientBuilder; -import com.hivemq.client2.mqtt.MqttTlsConfig; -import com.hivemq.client2.mqtt.MqttWebSocketConfig; -import com.hivemq.client2.mqtt.datatypes.MqttQos; -import com.hivemq.client2.mqtt.mqtt3.Mqtt3RxClient; -import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3ConnAck; -import com.hivemq.client2.mqtt.mqtt3.message.connect.Mqtt3Connect; -import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3Publish; -import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PublishBuilder; -import com.hivemq.client2.mqtt.mqtt3.message.publish.Mqtt3PublishResult; -import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe; -import com.hivemq.client2.mqtt.mqtt3.message.subscribe.Mqtt3Subscription; -import io.reactivex.rxjava3.core.Completable; -import io.reactivex.rxjava3.core.Flowable; -import io.reactivex.rxjava3.core.Single; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.TrustManagerFactory; -import java.util.UUID; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author Silvio Giebl - * @author David Katz - * @author Christian Hoff - */ -@SuppressWarnings("NullabilityAnnotations") -class Mqtt3ClientExample { - - private final TrustManagerFactory trustManagerFactory; - private final KeyManagerFactory keyManagerFactory; - private final String server; - - private final int port; - private final boolean usesSsl; - private final AtomicInteger receivedCount = new AtomicInteger(); - private final AtomicInteger publishedCount = new AtomicInteger(); - private final String serverPath; - - // create a client with a random UUID and connect to server - Mqtt3ClientExample( - @NotNull final String server, - final int port, - final boolean usesSsl, - @Nullable final TrustManagerFactory trustManagerFactory, - @Nullable final KeyManagerFactory keyManagerFactory, - @Nullable final String serverPath) { - this.server = server; - this.port = port; - this.usesSsl = usesSsl; - this.trustManagerFactory = trustManagerFactory; - this.keyManagerFactory = keyManagerFactory; - this.serverPath = serverPath == null ? "mqtt" : serverPath; - } - - Completable subscribeTo( - final String topic, final MqttQos qos, final int countToPublish, final CountDownLatch subscribedLatch) { - - final Mqtt3RxClient client = getClient(); - - // create a CONNECT message with keep alive of 10 seconds - final Mqtt3Connect connectMessage = Mqtt3Connect.builder().keepAlive(10).build(); - // define what to do on connect, this does not connect yet - final Single connectScenario = - client.connect(connectMessage).doOnSuccess(connAck -> System.out.println("connected subscriber")); - - // create a SUBSCRIBE message for the topic with QoS - final Mqtt3Subscribe subscribeMessage = Mqtt3Subscribe.builder() - .addSubscription(Mqtt3Subscription.builder().topicFilter(topic).maxQos(qos).build()) - .build(); - // define what to do with the publishes that match the subscription. This does not subscribe until rxJava's subscribe is called - // NOTE: you can also subscribe without the stream, and then handle the incoming publishes on client.allPublishes() - final Flowable subscribeScenario = - client.subscribePublishes(subscribeMessage).doOnSingle(subAck -> { - subscribedLatch.countDown(); - System.out.println("subscribed to " + topic + ": return codes: " + subAck.getReturnCodes()); - }).doOnNext(publish -> { - if (publish.getPayload().hasRemaining()) { - final int receivedCount = this.receivedCount.incrementAndGet(); - final String message = new String(publish.getPayloadAsBytes()); - System.out.println( - "received message with payload '" + message + "' on topic '" + publish.getTopic() + - "' received count: " + receivedCount); - } else { - System.out.println("received message without payload on topic '" + publish.getTopic() + "'"); - } - }); - - // define what to do when we disconnect, this does not disconnect yet - final Completable disconnectScenario = - client.disconnect().doOnComplete(() -> System.out.println("disconnected subscriber")); - - // now say we want to connect first and then subscribe, this does not connect and subscribe yet - // only take the first countToPublish publications and then disconnect - return connectScenario.ignoreElement() - .andThen(subscribeScenario) - .take(countToPublish) - .ignoreElements() - .andThen(disconnectScenario); - } - - private boolean isNotUsingMqttPort(final int port) { - return !(port == 1883 || port == 8883 || port == 8884); - } - - Completable publish(final String topic, final MqttQos qos, final int countToPublish) { - final Mqtt3RxClient client = getClient(); - - // create a CONNECT message with keep alive of 10 seconds - final Mqtt3Connect connectMessage = Mqtt3Connect.builder().keepAlive(10).build(); - // define what to do on connect, this does not connect yet - final Single connectScenario = - client.connect(connectMessage).doOnSuccess(connAck -> System.out.println("connected publisher")); - - // create a stub publish and a counter - final Mqtt3PublishBuilder.Complete publishMessageBuilder = Mqtt3Publish.builder().topic(topic).qos(qos); - final AtomicInteger counter = new AtomicInteger(); - // fake a stream of random messages, actually not random, but an incrementing counter ;-) - final Flowable publishFlowable = Flowable.generate(emitter -> { - if (counter.get() < countToPublish) { - emitter.onNext(publishMessageBuilder.payload(("test " + counter.getAndIncrement()).getBytes()).build()); - } else { - emitter.onComplete(); - } - }); - - // define what to publish and what to do when we published a message (e.g. PUBACK received), this does not publish yet - final Flowable publishScenario = client.publish(publishFlowable).doOnNext(publishResult -> { - final int publishedCount = this.publishedCount.incrementAndGet(); - final Mqtt3Publish publish = publishResult.getPublish(); - System.out.println( - "published " + new String(publish.getPayloadAsBytes()) + " published count: " + publishedCount); - }); - - // define what to do when we disconnect, this does not disconnect yet - final Completable disconnectScenario = - client.disconnect().doOnComplete(() -> System.out.println("disconnected publisher")); - - // now we want to connect, then publish and take the corresponding number of pubAcks and disconnect - // if we did not publish anything for 10 seconds also disconnect - return connectScenario.ignoreElement().andThen(publishScenario).ignoreElements().andThen(disconnectScenario); - } - - private Mqtt3RxClient getClient() { - final MqttClientBuilder mqttClientBuilder = - MqttClient.builder().identifier(UUID.randomUUID().toString()).serverHost(server).serverPort(port); - - if (usesSsl) { - mqttClientBuilder.tlsConfig(MqttTlsConfig.builder() - .keyManagerFactory(keyManagerFactory) - .trustManagerFactory(trustManagerFactory) - .build()); - } - - if (isNotUsingMqttPort(port)) { - mqttClientBuilder.webSocketConfig(MqttWebSocketConfig.builder().path(serverPath).build()); - } - - return mqttClientBuilder.useMqttVersion3().buildRx(); - } - - int getReceivedCount() { - return receivedCount.intValue(); - } - - int getPublishedCount() { - return publishedCount.intValue(); - } -} \ No newline at end of file diff --git a/src/test/java/com/hivemq/client2/example/Mqtt3SmokeTest.java b/src/test/java/com/hivemq/client2/example/Mqtt3SmokeTest.java deleted file mode 100644 index 3f0b30a06..000000000 --- a/src/test/java/com/hivemq/client2/example/Mqtt3SmokeTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2018-present HiveMQ and the HiveMQ Community - * - * 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 com.hivemq.client2.example; - -import com.hivemq.client2.mqtt.datatypes.MqttQos; -import com.hivemq.client2.util.KeyStoreUtil; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.TrustManagerFactory; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.UUID; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -/** - * @author David Katz - * @author Christian Hoff - */ -class Mqtt3SmokeTest { - - private static final String KEYSTORE_PATH = "testkeys/mosquitto/mosquitto.org.client.jks"; - private static final String KEYSTORE_PASS = "testkeystore"; - private static final String PRIVATE_KEY_PASS = "testkeystore"; - private static final String TRUSTSTORE_PATH = "testkeys/mosquitto/cacerts.jks"; - private static final String TRUSTSTORE_PASS = "testcas"; - private final String server = "test.mosquitto.org"; - private final MqttQos qos = MqttQos.AT_LEAST_ONCE; - private final String topic; - private final Mqtt3ClientExample subscribeInstance; - private Mqtt3ClientExample publishInstance; - private final int count = 100; - private CountDownLatch receivedLatch; - - Mqtt3SmokeTest() { - topic = UUID.randomUUID().toString(); - subscribeInstance = new Mqtt3ClientExample(server, 1883, false, null, null, null); - } - - @BeforeEach - void subscribe() throws InterruptedException { - final CountDownLatch subscribedLatch = new CountDownLatch(1); - receivedLatch = new CountDownLatch(1); - subscribeInstance.subscribeTo(topic, qos, count, subscribedLatch) - .doOnComplete(() -> receivedLatch.countDown()) - .subscribe(); - assertTrue(subscribedLatch.await(10, TimeUnit.SECONDS)); - } - - @AfterEach - void check() throws InterruptedException { - assertTrue(receivedLatch.await(10, TimeUnit.SECONDS)); - assertEquals(count, publishInstance.getPublishedCount()); - assertEquals(count, subscribeInstance.getReceivedCount()); - } - - @Test - @Disabled("test.mosquitto.org down") - void mqttOverTcp() { - publishInstance = new Mqtt3ClientExample(server, 1883, false, null, null, null); - assertTrue(publishInstance.publish(topic, qos, count).blockingAwait(10, TimeUnit.SECONDS)); - } - - @Test - @Disabled("test.mosquitto.org down") - void mqttOverTls() throws IOException, URISyntaxException { - final TrustManagerFactory trustManagerFactory = KeyStoreUtil.trustManagerFromKeystore( - new File(getClass().getClassLoader().getResource(TRUSTSTORE_PATH).toURI()), TRUSTSTORE_PASS); - - publishInstance = new Mqtt3ClientExample(server, 8883, true, trustManagerFactory, null, null); - assertTrue(publishInstance.publish(topic, qos, count).blockingAwait(10, TimeUnit.SECONDS)); - } - - @Test - @Disabled("test.mosquitto.org down") - void mqttOverTlsWithClientCert() throws IOException, URISyntaxException { - final TrustManagerFactory trustManagerFactory = KeyStoreUtil.trustManagerFromKeystore( - new File(getClass().getClassLoader().getResource(TRUSTSTORE_PATH).toURI()), TRUSTSTORE_PASS); - final KeyManagerFactory keyManagerFactory = KeyStoreUtil.keyManagerFromKeystore( - new File(getClass().getClassLoader().getResource(KEYSTORE_PATH).toURI()), KEYSTORE_PASS, - PRIVATE_KEY_PASS); - - publishInstance = new Mqtt3ClientExample(server, 8884, true, trustManagerFactory, keyManagerFactory, null); - assertTrue(publishInstance.publish(topic, qos, count).blockingAwait(10, TimeUnit.SECONDS)); - } - - @Test - @Disabled("test.mosquitto.org down") - void mqttOverWebSockets() { - publishInstance = new Mqtt3ClientExample(server, 8080, false, null, null, "mqtt"); - assertTrue(publishInstance.publish(topic, qos, count).blockingAwait(10, TimeUnit.SECONDS)); - } - - @Test - @Disabled("test.mosquitto.org down") - void mqttOverWebSocketsEncrypted() { - publishInstance = new Mqtt3ClientExample(server, 8081, true, null, null, "mqtt"); - assertTrue(publishInstance.publish(topic, qos, count).blockingAwait(10, TimeUnit.SECONDS)); - } - -} diff --git a/src/test/java/com/hivemq/client2/util/KeyStoreUtilTest.java b/src/test/java/com/hivemq/client2/util/KeyStoreUtilTest.java deleted file mode 100644 index 4a13e6da9..000000000 --- a/src/test/java/com/hivemq/client2/util/KeyStoreUtilTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2018-present HiveMQ and the HiveMQ Community - * - * 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 com.hivemq.client2.util; - -import org.junit.jupiter.api.Test; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLException; -import javax.net.ssl.TrustManagerFactory; -import java.io.File; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * @author Christoph Schäbel - */ -class KeyStoreUtilTest { - - @Test - public void test_valid_kmf() throws Exception { - final File store = new TestKeyStoreGenerator().generateKeyStore("fun", "JKS", "pw", "pk"); - final KeyManagerFactory kmf = KeyStoreUtil.keyManagerFromKeystore(store, "pw", "pk"); - assertNotNull(kmf.getKeyManagers()); - assertEquals(1, kmf.getKeyManagers().length); - } - - @Test - public void test_wrong_kmf_ks_path() throws Exception { - final File store = new TestKeyStoreGenerator().generateKeyStore("fun", "JKS", "pw", "pk"); - assertThrows( - SSLException.class, - () -> KeyStoreUtil.keyManagerFromKeystore(new File(store.getAbsolutePath() + "wrong"), "pw", "pk")); - } - - @Test - public void test_wrong_kmf_ks_pw() throws Exception { - final File store = new TestKeyStoreGenerator().generateKeyStore("fun", "JKS", "pw", "pk"); - assertThrows(SSLException.class, () -> KeyStoreUtil.keyManagerFromKeystore(store, "wrong", "pk")); - } - - @Test - public void test_wrong_kmf_key_pw() throws Exception { - final File store = new TestKeyStoreGenerator().generateKeyStore("fun", "JKS", "pw", "pk"); - assertThrows(SSLException.class, () -> KeyStoreUtil.keyManagerFromKeystore(store, "pw", "wrong")); - } - - @Test - public void test_valid_tmf() throws Exception { - final File store = new TestKeyStoreGenerator().generateKeyStore("fun", "JKS", "pw", "pk"); - final TrustManagerFactory tmf = KeyStoreUtil.trustManagerFromKeystore(store, "pw"); - assertNotNull(tmf.getTrustManagers()); - assertEquals(1, tmf.getTrustManagers().length); - } - - @Test - public void test_wrong_tmf_ks_path() throws Exception { - final File store = new TestKeyStoreGenerator().generateKeyStore("fun", "JKS", "pw", "pk"); - assertThrows( - SSLException.class, - () -> KeyStoreUtil.trustManagerFromKeystore(new File(store.getAbsolutePath() + "wrong"), "pw")); - } - - @Test - public void test_wrong_tmf_ks_pw() throws Exception { - final File store = new TestKeyStoreGenerator().generateKeyStore("fun", "JKS", "pw", "pk"); - assertThrows(SSLException.class, () -> KeyStoreUtil.trustManagerFromKeystore(store, "wrong")); - } - -} \ No newline at end of file diff --git a/src/test/java/com/hivemq/client2/util/TestKeyStoreGenerator.java b/src/test/java/com/hivemq/client2/util/TestKeyStoreGenerator.java deleted file mode 100644 index 5d1c65f38..000000000 --- a/src/test/java/com/hivemq/client2/util/TestKeyStoreGenerator.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2018-present HiveMQ and the HiveMQ Community - * - * 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 com.hivemq.client2.util; - -import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.cert.X509CertificateHolder; -import org.bouncycastle.cert.X509v3CertificateBuilder; -import org.bouncycastle.crypto.params.AsymmetricKeyParameter; -import org.bouncycastle.crypto.util.PrivateKeyFactory; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.operator.ContentSigner; -import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder; -import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; -import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.math.BigInteger; -import java.security.*; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.Date; - -/** - * @author Christoph Schäbel - */ -public class TestKeyStoreGenerator { - - private static final String KEY_ALIAS = "hivemq-mqtt-client-key"; - - public TestKeyStoreGenerator() { - Security.addProvider(new BouncyCastleProvider()); - } - - public File generateKeyStore( - final String name, - final String keystoreType, - final String keyStorePassword, - final String privateKeyPassword) throws Exception { - - final KeyStore ks = KeyStore.getInstance(keystoreType); - ks.load(null); - - final KeyPair keyPair = generateKeyPair(); - final X509Certificate certificate = generateX509Certificate(keyPair, name); - - final X509Certificate[] certificateChain = {certificate}; - - ks.setKeyEntry(KEY_ALIAS, keyPair.getPrivate(), privateKeyPassword.toCharArray(), certificateChain); - - final File keyStoreFile = File.createTempFile(name, null); - keyStoreFile.deleteOnExit(); - - final FileOutputStream fos = new FileOutputStream(keyStoreFile); - ks.store(fos, keyStorePassword.toCharArray()); - fos.close(); - return keyStoreFile; - } - - private X509Certificate generateX509Certificate(final KeyPair keyPair, final String name) throws Exception { - - //At least 1 attribute is required - final X500Name x500Name = new X500Name("CN=" + name); - - final X509v3CertificateBuilder builder = new X509v3CertificateBuilder( - - x500Name, BigInteger.valueOf(new SecureRandom().nextLong()), - new Date(System.currentTimeMillis() - 10000), new Date(System.currentTimeMillis() + 24L * 3600 * 1000), - x500Name, SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded())); - - final X509CertificateHolder holder = builder.build(createContentSigner(keyPair)); - final org.bouncycastle.asn1.x509.Certificate certificate = holder.toASN1Structure(); - - final InputStream is = new ByteArrayInputStream(certificate.getEncoded()); - - final X509Certificate x509Certificate = - (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is); - is.close(); - return x509Certificate; - } - - private KeyPair generateKeyPair() throws NoSuchProviderException, NoSuchAlgorithmException { - final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC"); - keyPairGenerator.initialize(2048, new SecureRandom()); - return keyPairGenerator.generateKeyPair(); - } - - private ContentSigner createContentSigner(final KeyPair keyPair) throws Exception { - final AlgorithmIdentifier signatureAlgorithmId = - new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256withRSA"); - final AlgorithmIdentifier digestAlgorithmId = - new DefaultDigestAlgorithmIdentifierFinder().find(signatureAlgorithmId); - - final byte[] encoded = keyPair.getPrivate().getEncoded(); - final AsymmetricKeyParameter privateKey = PrivateKeyFactory.createKey(encoded); - - return new BcRSAContentSignerBuilder(signatureAlgorithmId, digestAlgorithmId).build(privateKey); - } - -} \ No newline at end of file diff --git a/src/test/resources/testkeys/client.csr b/src/test/resources/testkeys/client.csr deleted file mode 100644 index 7067fd123..000000000 --- a/src/test/resources/testkeys/client.csr +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN CERTIFICATE REQUEST----- -MIIClzCCAX8CAQAwUjELMAkGA1UEBhMCREUxEDAOBgNVBAgMB0JhdmFyaWExDzAN -BgNVBAcMBk11bmljaDERMA8GA1UECgwIbXF0dC1iZWUxDTALBgNVBAMMBHRlc3Qw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2jAgmV+fT25PevvFUUaOZ -PfNlyvJX6kgwoJCjnjCw1w3yja1/U0XBHj3A3lgf4JH32DXmzvJbeXHOifHrT5PY -biZnTwUo0PeN96TiFea1IUCnh4HDAZVY6s4G9kslHpY7CZEn2fWVHIwaZrS6aZCB -iwgE2FXYJF1sd/bVv8G0UDhmZT1kC1xrDpjt/vW2mSuhMpdzatYmVMMlmP19cHRo -ssEETXkZstOqyeMj8joTyPFmOpK/iCljZERUKielUz2YDR8dhH8k6VwdJsX3Gvkf -I72WIGSf7MKiHwwBkiXpnlwLKQxVH6ZT3XBRxMivBeeXv61Nrg573nE4FM4ArlV7 -AgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAjztfioW0BduAbtHIUma+mMC/GvZg -2PGoR/CzFb1mSnIQpfg4pfmfuAxCvXyeTHS9B38AHwrgpa2GlXNt7qObFceHSCcm -kPowRswcZwKjKy7ZYmmlg69t8h3/8WpSYmAayyd4UQejRvypd2Py62FoUUbwNP0H -WabL4JKCt9RkIzcu0D3r3XHuKf8gZf+67fmHaKXag9Zr/nL9AlCyV1JbMRusa77K -FMJco4XpNLF6jRwNOqucVQYYxHatG3FlPaQrQ7HnFsXz/ZJxLFIVRDOdepFhbi5t -HAkJ+3mXn/2g1O5x+xTo1knC1BM3lNViGghMlwV0y31F8MJ4vYqbWG3d6A== ------END CERTIFICATE REQUEST----- diff --git a/src/test/resources/testkeys/client.key b/src/test/resources/testkeys/client.key deleted file mode 100644 index fed3e9e18..000000000 --- a/src/test/resources/testkeys/client.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAtowIJlfn09uT3r7xVFGjmT3zZcryV+pIMKCQo54wsNcN8o2t -f1NFwR49wN5YH+CR99g15s7yW3lxzonx60+T2G4mZ08FKND3jfek4hXmtSFAp4eB -wwGVWOrOBvZLJR6WOwmRJ9n1lRyMGma0ummQgYsIBNhV2CRdbHf21b/BtFA4ZmU9 -ZAtcaw6Y7f71tpkroTKXc2rWJlTDJZj9fXB0aLLBBE15GbLTqsnjI/I6E8jxZjqS -v4gpY2REVConpVM9mA0fHYR/JOlcHSbF9xr5HyO9liBkn+zCoh8MAZIl6Z5cCykM -VR+mU91wUcTIrwXnl7+tTa4Oe95xOBTOAK5VewIDAQABAoIBAQCtCDUda0vDBKq4 -g9OrMitZsWBKh8GJVfiRp1ES1nqe1WpSFLt1KlC/SlQMwnVT2gFipZ4KJvWRgZ8/ -wIAApZCloVtjp4Jjexh8iFXRPCNQY7GuWwLD/nc7Lm6WKNV33PNYCKx/0tk3OzUO -PXZoEHI6aLf0J7/PPkET9O6TE82fhKQQCiy6Yb3d+DAjVJHwggg2cvM+jVaKAvVZ -YvQkn3SOGt3LlipDDAqEPPLqiRlwwPpGKexNWfRiZ5FXA0dryLedSwWrFy0mXne5 -yMmrwkCGAjWOUcascHkYonundnSKzdH4ktBUvCV70fUEoZ6twa6V1b5Ov7puFWuk -CYnaetxZAoGBAOa67X4SbxeDdsO6G495hKBFTNQXLJ9jdfqyjJKXjVAT6pTZfTaq -uCzoh9U7NWBr6WAvyjV2FVJCZl6eWvZf6ptyMC7zKjy1JWh+M3L6ysAkvg+KqfnJ -HlJ/MBiCAF8dW7//PsNqqREdMHiccMqxkJZuslkrWA+xXRZSGLQBJtOPAoGBAMqK -LF39t65TK9qtZqba+u7+iSt8x6tNJeOiWAb9j1UmddPLfKhZTSwBeNrIOiYlY4E1 -1AU3UsvvTiJPopXIJHZbtIxpjHCX8lhpORhCXcvDN95dhcBm/bDzcNO75Fx1dES2 -gSJRAPs1TTJMUYsCP97Zp918FBy+QAWkNomivPlVAoGBANx3tUMIHjrblXpEtN0N -glsanOT0F+FdSnh4b7YLNi5UOYxtnSXFTyMqNdDcOI6fzmnogFFBOfJWHDdBHS3a -TPSn0b6q/6rudIY6QLMXTPD4qtty5iQVtvGhMrXYUr6P8QGuxaw4mMAPoic9ZNFp -hf0YXTazIfwswAP6AjzN9OmlAoGAHWMg/t5CWXvd4BPK0ijxwd2Sv4mSWwuNlNLI -XPNLabpz3DApPS//34OzKmNk9IX2QxgxVDRrwgVN2/KcD4mDqNyzfLAP3YJeem+C -BkAS5e7EW3JMZtdKtfMMitw3TScJoLKuV/FS6CAavFKQfk/sPoRsM9m9/VGpbmge -Nag0LSUCgYBM3/v3LFtZjus/c+8hw6eo5f5QjSP+tYzahqxuoPjXG9LfBj1AsVat -RCW/kdh4oo2pssMG6q8ZrPSgVaBz3qZIqUO5skTKMtXd1y3x5/apTh1WlWMQ/rcQ -TICTlWc1Ycq5M+S5reBY7JmGr8Hfj+bUuA6rM3uX1dweLtTh06w6ug== ------END RSA PRIVATE KEY----- diff --git a/src/test/resources/testkeys/mosquitto/README b/src/test/resources/testkeys/mosquitto/README deleted file mode 100644 index 154384491..000000000 --- a/src/test/resources/testkeys/mosquitto/README +++ /dev/null @@ -1,31 +0,0 @@ -This are test cryptographic artifacts to be used for internal testing purposes. -They are not to be used for any other purposes. - - -truststore: cacerts.jks -server cert for test.mosquitto.org from http://test.mosquitto.org/ssl/mosquitto.org.crt -password: testcas - -keystore: mosquitto.org.client.jks -client cert signed by http://test.mosquitto.org/ssl/ -password: testkeystore - - -to generate truststore: -keytool -import -trustcacerts -alias mosquitto -file src/test/resources/testkeys/mosquitto/mosquitto.org.crt -keystore src/test/resources/testkeys/cacerts.jks - -to generate keystore: -Given a private key and a cert signed by mosquitto: -openssl pkcs12 -export -in src/test/resources/testkeys/mosquitto/mosquitto.org.client.crt \ --inkey src/test/resources/testkeys/client.key \ --out src/test/resources/testkeys/mosquitto/keystore.p12 \ --name mosquitto.client.keystore \ --CAfile src/test/resources/testkeys/mosquitto/mosquitto.org.crt \ --caname mosquitto.org - -keytool -importkeystore -deststorepass testkeystore \ --destkeystore src/test/resources/testkeys/mosquitto/mosquitto.org.client.jks \ --srckeystore src/test/resources/testkeys/mosquitto/keystore.p12 \ --srcstoretype PKCS12 \ --srcstorepass testkeystore \ --alias mosquitto.client.keystore diff --git a/src/test/resources/testkeys/mosquitto/cacerts.jks b/src/test/resources/testkeys/mosquitto/cacerts.jks deleted file mode 100644 index 1c8f828b85be965f7d951d2194e08a0d5ca0b052..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 822 zcmezO_TO6u1_mY|W(3omx%tI~rI{rq`9P866w`0M46G4)rUsTkMPCe>m_7h;@5qwPB{BO@y-gF)j2Lv903Hs(+kHen`rCqr=qQ4oiN zhc7fQvm`Y|!8XKTNRB0$=AOPZX@o@UWoB=b5n}^BS(NN4l z1f+nOhZpWnz5JqdLwN&PxDz-T#RQ7-(^HEa5=)XZ^7BCo4CKUl4UG)Uj4X|e3=K^! zqr`cQKwNVucQ87+aXxamGO{u-H}(RQw%Ug~eJ#gqRTIiTvX<{$FL>svAOxKa_^ski}a2? zXWTjKt6GL%AQLkq1LNWV13zH6Gl$CZv52vV+$v8|uZ(%C@Wt3waPiBDr&dgP|I9!h zB(2OMVIbCkT>&To$O^Nt8Za|5{zvvOFd;Dmeaf}r+NK?5At9U&-Yt$Hj;odJ_r!~> z49)SKmd=wGR6cy?C&SelT&ia`=c?G&D1Y3Zx_#!=sQv5ay!Y}*SX`z|f2YkSdR@(P#^guqc)UG3?9-kf=>h<{hY{ES diff --git a/src/test/resources/testkeys/mosquitto/mosquitto.org.client.crt b/src/test/resources/testkeys/mosquitto/mosquitto.org.client.crt deleted file mode 100644 index da0a7cf1f..000000000 --- a/src/test/resources/testkeys/mosquitto/mosquitto.org.client.crt +++ /dev/null @@ -1,18 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIC9zCCAmCgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBkDELMAkGA1UEBhMCR0Ix -FzAVBgNVBAgMDlVuaXRlZCBLaW5nZG9tMQ4wDAYDVQQHDAVEZXJieTESMBAGA1UE -CgwJTW9zcXVpdHRvMQswCQYDVQQLDAJDQTEWMBQGA1UEAwwNbW9zcXVpdHRvLm9y -ZzEfMB0GCSqGSIb3DQEJARYQcm9nZXJAYXRjaG9vLm9yZzAeFw0xODA1MTUxMjAw -MjRaFw0xODA4MTMxMjAwMjRaMFIxCzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZh -cmlhMQ8wDQYDVQQHDAZNdW5pY2gxETAPBgNVBAoMCG1xdHQtYmVlMQ0wCwYDVQQD -DAR0ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtowIJlfn09uT -3r7xVFGjmT3zZcryV+pIMKCQo54wsNcN8o2tf1NFwR49wN5YH+CR99g15s7yW3lx -zonx60+T2G4mZ08FKND3jfek4hXmtSFAp4eBwwGVWOrOBvZLJR6WOwmRJ9n1lRyM -Gma0ummQgYsIBNhV2CRdbHf21b/BtFA4ZmU9ZAtcaw6Y7f71tpkroTKXc2rWJlTD -JZj9fXB0aLLBBE15GbLTqsnjI/I6E8jxZjqSv4gpY2REVConpVM9mA0fHYR/JOlc -HSbF9xr5HyO9liBkn+zCoh8MAZIl6Z5cCykMVR+mU91wUcTIrwXnl7+tTa4Oe95x -OBTOAK5VewIDAQABoxowGDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DANBgkqhkiG -9w0BAQsFAAOBgQAfA0jNsuhgwO352yQeLZqBw7OqteSueYLZ7BGMnWupMoh5MXBy -hCu7vhwc5fBWcDZODe9faEkI+ITQJwu557odqyc5fC0itsrgcsPZfjejL38GIIUO -b9CGM9tgIVJCC3z25mLN+h2yHND6dJipy5t+iV53Jicx+SMN3+f9+FRaoA== ------END CERTIFICATE----- diff --git a/src/test/resources/testkeys/mosquitto/mosquitto.org.client.jks b/src/test/resources/testkeys/mosquitto/mosquitto.org.client.jks deleted file mode 100644 index 1425c5c3d9102c8c3ca0deb906236703e38ec4a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2135 zcmYjSc|6oxAD-3HEMgEY2E&YK_>HA3=@nxw$}$L*Wd@@d#z<4QG^4~@Np{MTN%k#U zDOXPVU?L-ano{o^zhhInQ}M-_LWl`P+OD2m}!TyaU-FMp$S# zoyB5k`JScIf>~N;XzVZ+gGm!8e5v8N#vl+J0&rp509t65rVtng)_{nE!Eg|a3!Bfk zpkl9z)@S;*M<$4>6+(s=V;)l?O({!>TYt)=)GAGW%5YI1cW-boL%x`py!b*MDQ%5y z?gG!zl~XH2vnD*$67r(U%RvjAqq@+c_JYF|Rm&9N;jTC2OKFne(ed!DX}29mt6LW5Op?!Z23L_DXtE!>>U-FiDw@h&S8#zKxKGUko|0HEAcT-LjQo{;4`GdIQ>hG{Ke0~O-Jd9E3Zv@H5?i;R;Cz)p1PW( zRmLbjm%eW#EcJ0t6BUXLcy=#PHMlhYW%Ac!5t5&uG)sA$qtoMtyZRHK_*tHeI*CbC zs62Ew5%;YV6u0lq301K?r7J3HC!*Y6;gt1Y2cp}w7YPRaxc#a`Ow7zyP=BH&f6%wc zx&zJ|j19TukdDcix!W|aRB?c83pMQl>SMM_B#9jvuP-fh#y{n@NTGE-tncejoR29- zf8ZT04iRUoIoOUUNOa4^3j4pS)^M+|F~J+#Ca*5)n3V=(*$h<$B#Ad|1ze~04#&yl z=*~|KkDQP2U+n41(yL*upY&YXXt(f4HcuPR5xOovYfPQw`B>A&3ycbVd7iVv1=b>E zQVTg9!0YR}JYA0AC$gS@9l2)Xj!2Tpgi@)CL>zD>oRW0Qyot>`R#j1$m*EkY+3<^b z)ZCZW_A$DgMm;9B+Pp#?%B`olqZf1aZq+3EQC7rT3ewFD(Q_ulD2Lhhq^M{sf4HQ*Hsyjjg#Ip>S>CLd4uYv!+0c6Ce{E90{tc2pAg+%q)3P(Zd+ zsYQ!ZJpRhwyMU`#t`5~Nshwrt($=K$Kdkok&9KQ; z_1BI^m4ogzO0_i+%py(yIEnpuAw8EI(l*ZdbYs;t<^9U$b6Dzvy49$B@zC1sp6n4N zZsUc<+GzY+I)iF%b{84jU{=S8=)EmgVl7uZJ&gaVm>6SIQ8zm?;T02{-B*A$ySq8W zepU4Jsl#&Amn9ih$G#xCjl{;WwbNOItq*>$T>HeT>g-PMcE@|ERcj2a%2IR2Ue9tfU1Neof?*- z%lrLYd~xr}L5IZlRwtE!oZ4$=b+A|1nuFPw3m>UE&xpU2Y%GlPuCTC@@UxYN4I-*V}ZfahzfA-hScrHVe`ofZhAf1`E zNZjt*YA?|`(P2g$ck4B-BsBinWmP)1-V>z%ZQ7N8ZH3Aq8n$F9ldGI?hrW&(^@&!- z{oW{VqnLSF!l}kJw}eF>c3b>Xbz`_1nqT?G;{Lnf{RhX2Os@pCR2vZqCBhhwvfhV& zIfHD&0w48CwP!nJ33t=d2Mh)Exe0I~>jHS?Kp|iV1PlUDLZTYc*3s)IFc<*`0i1Xe z0uU8~QeZ+Dh?N;>42J z6t(+V%s)>;AR*?5Nz#Di4*?X3`hRmXnEoUzpzuEnqG0LWOol&=Y3j}L4PY>|1Oh;D z4~k>}=#%tGIsl-f=e|P?NV@-}faA}51dhoTq}_tP-*GH#=6%kaN%tm+2_Cs)Rmd(p znC=@u5(mWo_9_w-%3=|HXfzTEK>Y0v#-fF>04`YNpUDV*4Ja2Z1`@3Af^flLQ0+|- zyz5NQP~vFglCuLZ-DHK9$0`A(s=BWj8%#-eu!gR9B%H|6}Q z>*?{F8zQg)%7E(0vk_~(O)b^O4g6>(RD|albQ*tqwKiSzzD{abU?1MORV{7nQV1*H zQ47qDE&Hga=*F!@^Qz|4MtS+EFD@bb?NOgk2iS;gTRgb%(r^9nBEGu1)*A{jTsxzWX~Xt+3