Skip to content

Commit

Permalink
ARTEMIS-4528 tls, add support for PEM key store type
Browse files Browse the repository at this point in the history
  • Loading branch information
gtully committed Dec 15, 2023
1 parent 547aa2f commit 7a2137f
Show file tree
Hide file tree
Showing 49 changed files with 495 additions and 79 deletions.
1 change: 1 addition & 0 deletions artemis-core-client-osgi/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
<Embed-Dependency>*;scope=compile|runtime;groupId=org.apache.activemq</Embed-Dependency>
<Import-Package>
org.glassfish.json*;resolution:=optional,
de.dentrassi.crypto.pem;resolution:=optional,
io.netty.buffer;io.netty.*;version="[4.1,5)",
*
</Import-Package>
Expand Down
13 changes: 13 additions & 0 deletions artemis-core-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,19 @@
<groupId>io.netty</groupId>
<artifactId>netty-resolver</artifactId>
</dependency>
<dependency>
<groupId>de.dentrassi.crypto</groupId>
<artifactId>pem-keystore</artifactId>
</dependency>
<!-- bcprov-jdk18on replaces bcprov-jdk15on excluded pem-keystore -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
</dependency>

<!-- The johnzon-core and json-api contents are repackaged in -commons,
However maven can still need them during tests, which run against
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import java.security.cert.X509Certificate;
import java.util.Collection;

import de.dentrassi.crypto.pem.PemKeyStoreProvider;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
Expand Down Expand Up @@ -332,6 +333,7 @@ private static KeyStore loadKeystore(final String keystoreProvider,
final String keystoreType,
final String keystorePath,
final String keystorePassword) throws Exception {
checkPemProviderLoaded(keystoreType);
KeyStore ks = keystoreProvider == null ? KeyStore.getInstance(keystoreType) : KeyStore.getInstance(keystoreType, keystoreProvider);
InputStream in = null;
try {
Expand All @@ -351,6 +353,14 @@ private static KeyStore loadKeystore(final String keystoreProvider,
return ks;
}

private static void checkPemProviderLoaded(String keystoreType) {
if (keystoreType != null && keystoreType.startsWith("PEM")) {
if (Security.getProvider("PEM") == null) {
Security.insertProviderAt(new PemKeyStoreProvider(), Integer.parseInt(System.getProperty("artemis.pemProvider.insertAt", "0")));
}
}
}

private KeyManager[] loadKeyManagers() throws Exception {
KeyManagerFactory factory = loadKeyManagerFactory();
if (factory == null) {
Expand Down
1 change: 1 addition & 0 deletions artemis-jms-client-osgi/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
<Embed-Dependency>*;scope=compile|runtime;groupId=org.apache.activemq</Embed-Dependency>
<Import-Package>
org.glassfish.json*;resolution:=optional,
de.dentrassi.crypto.pem;resolution:=optional,
io.netty.buffer;io.netty.*;version="[4.1,5)",
*
</Import-Package>
Expand Down
1 change: 1 addition & 0 deletions artemis-server-osgi/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
<Import-Package>
org.glassfish.json*;resolution:=optional,
org.postgresql*;resolution:=optional,
de.dentrassi.crypto.pem;resolution:=optional,
io.netty.buffer;io.netty.*;version="[4.1,5)",
java.net.http*;resolution:=optional,
com.sun.net.httpserver*;resolution:=optional,
Expand Down
6 changes: 0 additions & 6 deletions artemis-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -290,12 +290,6 @@
<version>${mockserver.version}</version>
<scope>test</scope>
</dependency>
<!-- bcprov-jdk18on replaces bcprov-jdk15on excluded from apacheds-protocol-ldap -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<profiles>
Expand Down
4 changes: 2 additions & 2 deletions docs/user-manual/configuring-transports.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ The ActiveMQ-specific system property is useful if another component on the clie

keyStoreType::
The type of keystore being used.
For example, `JKS`, `JCEKS`, `PKCS12`, etc.
For example, `JKS`, `JCEKS`, `PKCS12`, `PEM` etc.
This value can also be set via the "javax.net.ssl.keyStoreType" system property or the ActiveMQ-specific "org.apache.activemq.ssl.keyStoreType" system property.
The ActiveMQ-specific system property is useful if another component on the client is already making use of the standard Java system property.
Default is `JKS`.
Expand Down Expand Up @@ -356,7 +356,7 @@ The ActiveMQ-specific system property is useful if another component on the clie

trustStoreType::
The type of truststore being used.
For example, `JKS`, `JCEKS`, `PKCS12`, etc.
For example, `JKS`, `JCEKS`, `PKCS12`, `PEM` etc.
This value can also be set via the "javax.net.ssl.trustStoreType" system property or the ActiveMQ-specific "org.apache.activemq.ssl.trustStoreType" system property.
The ActiveMQ-specific system property is useful if another component on the client is already making use of the standard Java system property.
Default is `JKS`.
Expand Down
19 changes: 18 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
<curator.version>5.5.0</curator.version>
<zookeeper.version>3.8.3</zookeeper.version>
<woodstox.version>4.4.0</woodstox.version>
<pem-keystore.version>2.2.2</pem-keystore.version>

<!-- docs -->
<asciidoctor.maven.plugin.version>2.2.4</asciidoctor.maven.plugin.version>
Expand Down Expand Up @@ -412,7 +413,23 @@
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>de.dentrassi.crypto</groupId>
<artifactId>pem-keystore</artifactId>
<version>${pem-keystore.version}</version>
<!-- Eclipse Public License - v 1.0 -->
<exclusions>
<!-- exclude bcprov-jdk15on to avoid conflicts with bcprov-jdk18on -->
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.activemq.artemis.tests.integration.ssl;

import java.lang.management.ManagementFactory;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.activemq.artemis.api.core.ActiveMQNotConnectedException;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
import org.apache.activemq.artemis.core.security.Role;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServers;
import org.apache.activemq.artemis.core.settings.HierarchicalRepository;
import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager;
import org.apache.activemq.artemis.tests.integration.security.SecurityTest;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.utils.RandomUtil;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
* See the tests/security-resources/build.sh script for details on the security resources used.
*/
public class SslPEMTest extends ActiveMQTestBase {

static {
String path = System.getProperty("java.security.auth.login.config");
if (path == null) {
URL resource = SecurityTest.class.getClassLoader().getResource("login.config");
if (resource != null) {
path = resource.getFile();
System.setProperty("java.security.auth.login.config", path);
}
}
}

private TransportConfiguration tc;
private SimpleString QUEUE;

@Test
public void testPemKeyAndTrustStore() throws Exception {

tc.getParams().put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
tc.getParams().put(TransportConstants.KEYSTORE_TYPE_PROP_NAME, "PEM");
tc.getParams().put(TransportConstants.KEYSTORE_PATH_PROP_NAME, "client-key-cert.pem");
tc.getParams().put(TransportConstants.PORT_PROP_NAME, "61617");

ServerLocator producerLocator;
ClientSessionFactory producerSessionFactory;
ClientSession producerSession;

// first without trust store
try {
producerLocator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc));
producerSessionFactory = createSessionFactory(producerLocator);
producerSessionFactory.createSession(false, true, true);
} catch (ActiveMQNotConnectedException expected) {
}

// configure trust
tc.getParams().put(TransportConstants.TRUSTSTORE_TYPE_PROP_NAME, "PEM");
tc.getParams().put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, "server-ca-cert.pem");
producerLocator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(tc));
producerSessionFactory = createSessionFactory(producerLocator);

producerSession = producerSessionFactory.createSession(false, true, true);

producerSession.createQueue(new QueueConfiguration(QUEUE).setDurable(false));
ClientProducer producer = producerSession.createProducer(QUEUE);

ClientMessage message = createTextMessage(producerSession, RandomUtil.randomString());
producer.send(message);

ServerLocator consumerLocator = addServerLocator(ActiveMQClient.createServerLocator("tcp://localhost:61616"));
ClientSessionFactory consumerSessionFactory = createSessionFactory(consumerLocator);
ClientSession consumerSession = consumerSessionFactory.createSession("consumer", "consumerPassword", false, true, true, consumerLocator.isPreAcknowledge(), consumerLocator.getAckBatchSize());
ClientConsumer consumer = consumerSession.createConsumer(QUEUE);
consumerSession.start();

Message m = consumer.receive(1000);
Assert.assertNotNull(m);
}

@Override
@Before
public void setUp() throws Exception {
super.setUp();
QUEUE = new SimpleString(getName());

Map<String, Object> params = new HashMap<>();
params.put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
params.put(TransportConstants.KEYSTORE_TYPE_PROP_NAME, "PEMCFG");
params.put(TransportConstants.KEYSTORE_PATH_PROP_NAME, "server-pem-props-config.txt");
params.put(TransportConstants.TRUSTSTORE_TYPE_PROP_NAME, "PEM");
params.put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, "client-ca-cert.pem");
params.put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, true);
params.put(TransportConstants.PORT_PROP_NAME, "61617");
ConfigurationImpl config = createBasicConfig();
config.addAcceptorConfiguration(new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params));
config.addAcceptorConfiguration(new TransportConfiguration(NETTY_ACCEPTOR_FACTORY));
config.setSecurityEnabled(true);

ActiveMQSecurityManager securityManager = new ActiveMQJAASSecurityManager("DualAuthenticationPropertiesLogin", "DualAuthenticationCertLogin");
ActiveMQServer server = addServer(ActiveMQServers.newActiveMQServer(config, ManagementFactory.getPlatformMBeanServer(), securityManager, false));

HierarchicalRepository<Set<Role>> securityRepository = server.getSecurityRepository();
Role sendRole = new Role("producers", true, false, true, false, true, false, false, false, true, false);
Role receiveRole = new Role("consumers", false, true, false, false, false, false, false, false, false, false);
Set<Role> roles = new HashSet<>();
roles.add(sendRole);
roles.add(receiveRole);
securityRepository.addMatch(QUEUE.toString(), roles);

server.start();
waitForServerToStart(server);
tc = new TransportConfiguration(NETTY_CONNECTOR_FACTORY);
}
}
14 changes: 14 additions & 0 deletions tests/security-resources/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,20 @@ keytool -storetype pkcs12 -keystore unknown-client-keystore.p12 -storepass $STOR
keytool -importkeystore -srckeystore unknown-client-keystore.p12 -destkeystore unknown-client-keystore.jceks -srcstoretype pkcs12 -deststoretype jceks -srcstorepass securepass -deststorepass securepass
keytool -importkeystore -srckeystore unknown-client-keystore.p12 -destkeystore unknown-client-keystore.jks -srcstoretype pkcs12 -deststoretype jks -srcstorepass securepass -deststorepass securepass

# PEM versions
## separate private and public cred pem files combined for the keystore via prop
openssl pkcs12 -in server-keystore.p12 -out server-cert.pem -clcerts -nokeys -password pass:$STORE_PASS
openssl pkcs12 -in server-keystore.p12 -out server-key.pem -nocerts -nodes -password pass:$STORE_PASS

## PEMCFG properties format
echo source.key=classpath:server-key.pem > server-pem-props-config.txt
echo source.cert=classpath:server-cert.pem >> server-pem-props-config.txt

## combined pem file for client
openssl pkcs12 -in client-keystore.p12 -out client-key-cert.pem -nodes -password pass:$STORE_PASS
keytool -storetype pkcs12 -keystore server-ca-keystore.p12 -storepass $STORE_PASS -alias server-ca -exportcert -rfc > server-ca-cert.pem
keytool -storetype pkcs12 -keystore client-ca-keystore.p12 -storepass $STORE_PASS -alias client-ca -exportcert -rfc > client-ca-cert.pem

# Clean up working files
# -----------------------
rm -f *.crt *.csr openssl-*
21 changes: 21 additions & 0 deletions tests/security-resources/client-ca-cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDcDCCAligAwIBAgIEJbym6DANBgkqhkiG9w0BAQsFADBfMREwDwYDVQQKEwhB
Y3RpdmVNUTEQMA4GA1UECxMHQXJ0ZW1pczE4MDYGA1UEAxMvQWN0aXZlTVEgQXJ0
ZW1pcyBDbGllbnQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwIBcNMjMxMjA3MTY0
ODUyWhgPMzAyMzA0MDkxNjQ4NTJaMF8xETAPBgNVBAoTCEFjdGl2ZU1RMRAwDgYD
VQQLEwdBcnRlbWlzMTgwNgYDVQQDEy9BY3RpdmVNUSBBcnRlbWlzIENsaWVudCBD
ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAIaj9LoncxRCfTayohTMSqWCutkAXE8rTDKbpmrTt3RMkmqJw2sO3tn0
CZkcfkf+1eXsJHRoH9uhUZI7Cc+vGFCfWF9RTi4aCjYFtTXmb0FAsOl1TTRjDgWb
eyUYI25KpVBz57JD3GlFlFo0tLQkc/C1QWU3dlpU5INh5vo/1Si4hrVSX8/Hun8q
daZg4bjfUGnNa0H5nPfkCaZjAamAKp6L50e0cLS4PQCPhVMdH6uU2CEJDxNURN3i
tD6z3YJReFpxNM3HmDwLgUxQcvByQ60Qc90aUihKqXKj8rlFJn76d/kkH3xj2n5t
msY4/GNxh+P0W8whH4C7uglo/vSaDbMCAwEAAaMyMDAwHQYDVR0OBBYEFKUM1JFb
FBp0jlZ9Cb6UbaPQAOr7MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD
ggEBAFmb6rDuirRpEpO/+jXRqq3A4gqMW4Qbjqb61pIQyNim+0Z+RDwQn4nfnZxY
CaAlRiwg7Ihr85brwHcAC2YG/ir3AEcY70r15xIFCiRkDo47r8cXhTAiQfVBjd1j
m1Bo1w1Sae/Vhe/Jryuqz7C+lXads6xWr9x+RoKb9IDgRhz6aVUBQfkyuusm3D+c
RN7i3IRD2ypf1dEAH51+n+U3gEtWbztA2R1MFCGq/pWfEbMaI7fkBu77h6e/Okwq
dNAbXMYlKvv/BgkmzPvHWtepa/1vWZmyC1t0Oo3jNBrUMPCrkQwHbSMl9vMQwICJ
LnIXqz1dSY/M11jjOVS8ZoZ0gdE=
-----END CERTIFICATE-----
Binary file modified tests/security-resources/client-ca-keystore.p12
Binary file not shown.
Binary file modified tests/security-resources/client-ca-truststore.jceks
Binary file not shown.
Binary file modified tests/security-resources/client-ca-truststore.jks
Binary file not shown.
Binary file modified tests/security-resources/client-ca-truststore.p12
Binary file not shown.
54 changes: 27 additions & 27 deletions tests/security-resources/client-ca.pem
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
Bag Attributes
friendlyName: client-ca
localKeyID: 54 69 6D 65 20 31 36 32 38 32 30 33 36 33 37 31 38 36
localKeyID: 54 69 6D 65 20 31 37 30 31 39 36 37 37 33 32 36 35 35
Key Attributes: <No Attributes>
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCf8s5tfHnara0G
c0qtw7VdaQjXxBhfH6AQ/XbTOzHMF6FtTzWWTEq6wqoUuP1Y4WLob67O3ZRQ+RMN
V+C4eFgH9e7LlZ6gU7DWEk40WkKVQ/sTW3/4ul/F7ScFtyTvZ4zvNa6Qr0np4rB+
SJlOy5yBZlNgmU2H+J/OsxEJDkw+Q+lz1Q/d6QevnfgBu5/Ka/aYtia2fPduufIf
Dn/UbLe+AANnO8z1NQ9ocOSgCcuocOmCssSZNGFXtf8qjMhZypO2c/bmZnuki+yQ
QhnD+yrOPbJMgcfL3jIesjNCu5kapmEGJBeGFtEgilegLYpYVTvF3RURjaqy2t3j
Y36sysXZAgMBAAECggEAHIzIj/5x+biac9ZMdCvEycGf1HOqLgCFH8M+XIHqZ5Wo
OMy0sfk4NZHdrgk/H4hLkVWuDDq86J8s6WrQL907SWB6mVhBkjieDfgCgZHC5MXX
oSLp+sm5oqisGHcSXrFLFL+uQyEmvlq6SjBHPStW6joLk+iJUEXusISB++3TaiGI
2LnHu0AZR+TNGk9tf+K48mlfpRimqq+Bugh7Sgh7uis9bwXn1p1Nz5hZDbBLGVMv
wgsC6xvvZJwNrUW7mgmVuytcCivR1Q/Tt1d8cim1bt+a/ZfRD6utexcfaZ47l5+3
WPFb7UkMlXioZzrxDjlKO8J8qBcxcd8brqp5mX3KKQKBgQDRM0I18K4QCsw1zZFa
Zu7DjmLdxsgWSmpvmHVY2iFyUDI5NVcx7HU0ACd0lRU9IFnAIDzlNPnjyaShRQxW
IrPG+zFifmwyqNVRJfZdrm1ZkLba5CgJ+vVQbZF+lEh3M/mKID1CfLk4O/xZKeho
xXn3Nika/BqHNJlFJsvytoLdrwKBgQDDuu+K0KdILWsDTnVLOY3mjXKfJjw3P5MI
/dyoWFtW4M4xQ172aSVNZ11AHaiaDQ1KRXgVcUvmMVXQXXB+01DA/DArreDmREnT
gBwenTApjT/lblRBkcei6VtM5BLQ46uXueYzTJJ419WwYc0GaXG7lnipcz+L0C2a
thEsMrG+9wKBgAjJr3FWn+k6muNztDRo+ISseYi5bfRJwfjYHa3S0+7aYZG3pOcK
+M1raDzkelTsA/knIYe7Vvfzo3/Gx8LiiEzGhoeNqfvizbsv7g53Yk6N3rCJPwlU
SnPLdn4runOPcl8UBZ7CYIF1O59/PC0ShpIU61sf1flyAzI9c/nJIuwvAoGAWG6b
T9KZ4ehzUxkdsZEdZa8+vF0gE64rloJsMbtJ+WS0hFl2DErRSbmLzi4YQRHokUf1
y2pW6ngb13qAGy0KbUcD1JhI5oCwAlj9W2+VlRB2cAh7FOzyj85zK7hYL/zNSE37
je3ot6R8raZiZaU6d5Cyj4y8h0TVdfMQqzF0UV0CgYEAhpNPBVxNfwX/hFKdFQKA
1yDHTQiLhC8N0xfkI4FRQUdviVmy/LLRHincjtievo7bpE0sn87q990LK4B4L4dJ
y6024cPPCxrz1p2i43B0CuS7JwCL7UxaDQnHc/zwLYjZZJhYnZmfdjzThIturKEw
pUfEMSr5rFelUKg2aZjVAqM=
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCGo/S6J3MUQn02
sqIUzEqlgrrZAFxPK0wym6Zq07d0TJJqicNrDt7Z9AmZHH5H/tXl7CR0aB/boVGS
OwnPrxhQn1hfUU4uGgo2BbU15m9BQLDpdU00Yw4Fm3slGCNuSqVQc+eyQ9xpRZRa
NLS0JHPwtUFlN3ZaVOSDYeb6P9UouIa1Ul/Px7p/KnWmYOG431BpzWtB+Zz35Amm
YwGpgCqei+dHtHC0uD0Aj4VTHR+rlNghCQ8TVETd4rQ+s92CUXhacTTNx5g8C4FM
UHLwckOtEHPdGlIoSqlyo/K5RSZ++nf5JB98Y9p+bZrGOPxjcYfj9FvMIR+Au7oJ
aP70mg2zAgMBAAECggEAdj5/qw0CUASkmuj+120jEYBiQDnE1/KalMeFu8P8FbM5
0z7x1I/Wv2tHEqSncusnRynASks3z1c5oEchMrf/jq6imfN5yZss5IzWvGOHybLa
q+1MxHlJ0zrdR5KPa0k7LhDcpv5aEEn/I8mt+ZcaC4fjytSOqH5twcS1aYmt1ngR
aQKd3UkB5AhxbHcx3V4iX9opdy0NhwaimAGY+U7yVE7tc58n/ZA5FPF2GImuyQOS
F12LytmtDIkMjSmBERNlU+67t79rx5a91Tavy8Hz0htEzNQ4wulG/v+Jqnbdh7j7
dpCN7EvTDQ08jDihuUpFPVo1UF9Atrn3c3zJuGy8gQKBgQDGQO7EeHUZzb+yyF+M
9XP+8R9Sb/4qoDMpAIn/5le9sN/riYQbCctQ2HmbxMGm3vu7FUl8MrRvCLCiASK8
5ng4oP3pel3P4jUvnVy57WzgfkmdKhSB1sxojtMOibLZgP09bRT/Q1bTKLJtA5GY
imt3cg0fF0YD0UI8GaNEmNxFUQKBgQCt251PKK3GzCo1J6iheiwSMkuG47WBcnLL
1oYl61TH7z/pKEs4GGCE31xn7+P88QY7XftNmJkuh91u0SMdCf4w3yHYzz62OdZL
go9tov5F06K1kkOmQ23ORtTbGnNlrNBTsDYIjnoufWMIf66RsAO9d7k3f/o4bXBa
88rLCpDxwwKBgQClxT+g+pP32olzJYZ35/lw8A9fsBNXcxK0MyYw2lr9WvsxCJB0
x1DBLfEpZXEDZioY+aizd/ZVbW+8VrTEPPXDbCJD6rSskZolUTBqqvNCF3bYOoph
MslCmEI0QsFQi0G07hQDiTv9XmcrLjO81+kaPDxqhdxebsgyVsGlJyfvsQKBgEZY
9KARH6+u8O0tLOiZ3LdILpNYFBtayeR82y8At/9maX/YVAdQpc1d67AKuz+f7xua
fZL6ShEv3IN4kDKx1m7D+pgV05Q8dt965rpAF479gXriwgjGg+nRc1NssoDTmkAi
rtprfDjPd4D62RIOHJVPmlxApmiqr6m9t7LMhbWtAoGBAITtzDRoOwDGwA3UB3cR
ObFmijIzfjqxU0Q3T4QZe6gbLE1ExEdXMcMX/JhU6n4LJ/FcAf7/dwm15xqIQmzK
iqmRb8Nnk0li1pUxusZ2jt5W4DGmafim7XdzDaLpSukws51Zj7WpiFDBBaQbww7k
0yWnt8ORrQTF6/2ZESuODqK0
-----END PRIVATE KEY-----

0 comments on commit 7a2137f

Please sign in to comment.