mirror of https://github.com/hyperledger/besu
Remove P2P TLS (experimental) feature (#7942)
parent
792c6569cd
commit
63496dbc6c
@ -1,60 +0,0 @@ |
||||
/* |
||||
* Copyright contributors to Hyperledger Besu. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.tests.acceptance.dsl.node.configuration.pki; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileInputStream; |
||||
import java.io.FileOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.UncheckedIOException; |
||||
import java.nio.file.Path; |
||||
import java.util.Properties; |
||||
|
||||
public class PKCS11Utils { |
||||
|
||||
public static Path initNSSConfigFile(final Path srcFilePath) { |
||||
// load nss file as Properties
|
||||
final Properties nssProp = new Properties(); |
||||
try (InputStream input = new FileInputStream(srcFilePath.toFile())) { |
||||
nssProp.load(input); |
||||
String nssDbPath = srcFilePath.getParent().resolve("nssdb").toAbsolutePath().toString(); |
||||
nssProp.setProperty("nssSecmodDirectory", nssDbPath); |
||||
} catch (final IOException e) { |
||||
throw new UncheckedIOException(e); |
||||
} |
||||
|
||||
// store modified config into temporary file
|
||||
final Path targetFilePath = createTemporaryFile("nsscfg"); |
||||
try (FileOutputStream outputStream = new FileOutputStream(targetFilePath.toFile())) { |
||||
nssProp.store(outputStream, null); |
||||
} catch (final IOException e) { |
||||
throw new UncheckedIOException(e); |
||||
} |
||||
|
||||
return targetFilePath; |
||||
} |
||||
|
||||
private static Path createTemporaryFile(final String suffix) { |
||||
final File tempFile; |
||||
try { |
||||
tempFile = File.createTempFile("temp", suffix); |
||||
tempFile.deleteOnExit(); |
||||
} catch (IOException e) { |
||||
throw new RuntimeException("Error creating temporary file", e); |
||||
} |
||||
return tempFile.toPath(); |
||||
} |
||||
} |
@ -1,163 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.cli.options; |
||||
|
||||
import static java.util.Arrays.asList; |
||||
import static org.hyperledger.besu.cli.DefaultCommandValues.DEFAULT_KEYSTORE_TYPE; |
||||
import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_FILE_FORMAT_HELP; |
||||
|
||||
import org.hyperledger.besu.cli.util.CommandLineUtils; |
||||
import org.hyperledger.besu.ethereum.api.tls.FileBasedPasswordProvider; |
||||
import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; |
||||
|
||||
import java.nio.file.Path; |
||||
import java.util.Optional; |
||||
|
||||
import org.slf4j.Logger; |
||||
import picocli.CommandLine; |
||||
import picocli.CommandLine.Option; |
||||
import picocli.CommandLine.ParameterException; |
||||
|
||||
/** The P2P TLS Config Cli Options. */ |
||||
public class P2PTLSConfigOptions { |
||||
@Option( |
||||
names = {"--Xp2p-tls-enabled"}, |
||||
hidden = true, |
||||
description = "Enable P2P TLS functionality (default: ${DEFAULT-VALUE})") |
||||
private final Boolean p2pTLSEnabled = false; |
||||
|
||||
@SuppressWarnings({ |
||||
"FieldCanBeFinal", |
||||
"FieldMayBeFinal" |
||||
}) // p2pTLSKeyStoreType requires non-final Strings.
|
||||
@Option( |
||||
names = {"--Xp2p-tls-keystore-type"}, |
||||
hidden = true, |
||||
paramLabel = "<NAME>", |
||||
description = "P2P service keystore type. Required if P2P TLS is enabled.") |
||||
private String p2pTLSKeyStoreType = DEFAULT_KEYSTORE_TYPE; |
||||
|
||||
@Option( |
||||
names = {"--Xp2p-tls-keystore-file"}, |
||||
hidden = true, |
||||
paramLabel = MANDATORY_FILE_FORMAT_HELP, |
||||
description = "Keystore containing key/certificate for the P2P service.") |
||||
private final Path p2pTLSKeyStoreFile = null; |
||||
|
||||
@Option( |
||||
names = {"--Xp2p-tls-keystore-password-file"}, |
||||
hidden = true, |
||||
paramLabel = MANDATORY_FILE_FORMAT_HELP, |
||||
description = |
||||
"File containing password to unlock keystore for the P2P service. Required if P2P TLS is enabled.") |
||||
private final Path p2pTLSKeyStorePasswordFile = null; |
||||
|
||||
@SuppressWarnings({ |
||||
"FieldCanBeFinal", |
||||
"FieldMayBeFinal" |
||||
}) // p2pTLSTrustStoreType requires non-final Strings.
|
||||
@Option( |
||||
names = {"--Xp2p-tls-truststore-type"}, |
||||
hidden = true, |
||||
paramLabel = "<NAME>", |
||||
description = "P2P service truststore type.") |
||||
private String p2pTLSTrustStoreType = DEFAULT_KEYSTORE_TYPE; |
||||
|
||||
@Option( |
||||
names = {"--Xp2p-tls-truststore-file"}, |
||||
hidden = true, |
||||
paramLabel = MANDATORY_FILE_FORMAT_HELP, |
||||
description = "Truststore containing trusted certificates for the P2P service.") |
||||
private final Path p2pTLSTrustStoreFile = null; |
||||
|
||||
@Option( |
||||
names = {"--Xp2p-tls-truststore-password-file"}, |
||||
hidden = true, |
||||
paramLabel = MANDATORY_FILE_FORMAT_HELP, |
||||
description = "File containing password to unlock truststore for the P2P service.") |
||||
private final Path p2pTLSTrustStorePasswordFile = null; |
||||
|
||||
@Option( |
||||
names = {"--Xp2p-tls-crl-file"}, |
||||
hidden = true, |
||||
paramLabel = MANDATORY_FILE_FORMAT_HELP, |
||||
description = "Certificate revocation list for the P2P service.") |
||||
private final Path p2pCrlFile = null; |
||||
|
||||
@Option( |
||||
names = {"--Xp2p-tls-clienthello-sni"}, |
||||
hidden = true, |
||||
description = |
||||
"Whether to send a SNI header in the TLS ClientHello message (default: ${DEFAULT-VALUE})") |
||||
private final Boolean p2pTlsClientHelloSniHeaderEnabled = false; |
||||
|
||||
/** Default constructor. */ |
||||
P2PTLSConfigOptions() {} |
||||
|
||||
/** |
||||
* Generate P2p tls configuration. |
||||
* |
||||
* @param commandLine the command line object to report exceptions |
||||
* @return the optional TLSConfiguration |
||||
*/ |
||||
public Optional<TLSConfiguration> p2pTLSConfiguration(final CommandLine commandLine) { |
||||
if (!p2pTLSEnabled) { |
||||
return Optional.empty(); |
||||
} |
||||
|
||||
if (p2pTLSKeyStoreType == null) { |
||||
throw new ParameterException( |
||||
commandLine, "Keystore type is required when p2p TLS is enabled"); |
||||
} |
||||
|
||||
if (p2pTLSKeyStorePasswordFile == null) { |
||||
throw new ParameterException( |
||||
commandLine, |
||||
"File containing password to unlock keystore is required when p2p TLS is enabled"); |
||||
} |
||||
|
||||
return Optional.of( |
||||
TLSConfiguration.Builder.tlsConfiguration() |
||||
.withKeyStoreType(p2pTLSKeyStoreType) |
||||
.withKeyStorePath(p2pTLSKeyStoreFile) |
||||
.withKeyStorePasswordSupplier(new FileBasedPasswordProvider(p2pTLSKeyStorePasswordFile)) |
||||
.withKeyStorePasswordPath(p2pTLSKeyStorePasswordFile) |
||||
.withTrustStoreType(p2pTLSTrustStoreType) |
||||
.withTrustStorePath(p2pTLSTrustStoreFile) |
||||
.withTrustStorePasswordSupplier( |
||||
null == p2pTLSTrustStorePasswordFile |
||||
? null |
||||
: new FileBasedPasswordProvider(p2pTLSTrustStorePasswordFile)) |
||||
.withTrustStorePasswordPath(p2pTLSTrustStorePasswordFile) |
||||
.withCrlPath(p2pCrlFile) |
||||
.withClientHelloSniEnabled(p2pTlsClientHelloSniHeaderEnabled) |
||||
.build()); |
||||
} |
||||
|
||||
/** |
||||
* Check P2P Tls options dependencies. |
||||
* |
||||
* @param logger the logger |
||||
* @param commandLine the command line |
||||
*/ |
||||
public void checkP2PTLSOptionsDependencies(final Logger logger, final CommandLine commandLine) { |
||||
CommandLineUtils.checkOptionDependencies( |
||||
logger, |
||||
commandLine, |
||||
"--Xp2p-tls-enabled", |
||||
!p2pTLSEnabled, |
||||
asList("--Xp2p-tls-keystore-type", "--Xp2p-tls-keystore-password-file")); |
||||
} |
||||
} |
@ -1,159 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty; |
||||
|
||||
import static org.hyperledger.besu.ethereum.p2p.rlpx.RlpxFrameConstants.LENGTH_FRAME_SIZE; |
||||
import static org.hyperledger.besu.ethereum.p2p.rlpx.RlpxFrameConstants.LENGTH_MAX_MESSAGE_FRAME; |
||||
|
||||
import org.hyperledger.besu.cryptoservices.NodeKey; |
||||
import org.hyperledger.besu.ethereum.p2p.config.RlpxConfiguration; |
||||
import org.hyperledger.besu.ethereum.p2p.discovery.internal.PeerTable; |
||||
import org.hyperledger.besu.ethereum.p2p.peers.LocalNode; |
||||
import org.hyperledger.besu.ethereum.p2p.peers.Peer; |
||||
import org.hyperledger.besu.ethereum.p2p.plain.PlainFramer; |
||||
import org.hyperledger.besu.ethereum.p2p.plain.PlainHandshaker; |
||||
import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnectionEventDispatcher; |
||||
import org.hyperledger.besu.ethereum.p2p.rlpx.framing.Framer; |
||||
import org.hyperledger.besu.ethereum.p2p.rlpx.handshake.HandshakeSecrets; |
||||
import org.hyperledger.besu.ethereum.p2p.rlpx.handshake.Handshaker; |
||||
import org.hyperledger.besu.plugin.data.EnodeURL; |
||||
import org.hyperledger.besu.plugin.services.MetricsSystem; |
||||
|
||||
import java.security.GeneralSecurityException; |
||||
import java.util.Optional; |
||||
import java.util.function.Supplier; |
||||
|
||||
import com.google.common.annotations.VisibleForTesting; |
||||
import com.google.common.base.Suppliers; |
||||
import io.netty.channel.Channel; |
||||
import io.netty.handler.codec.LengthFieldBasedFrameDecoder; |
||||
import io.netty.handler.codec.LengthFieldPrepender; |
||||
import io.netty.handler.codec.compression.SnappyFrameDecoder; |
||||
import io.netty.handler.codec.compression.SnappyFrameEncoder; |
||||
import io.netty.handler.ssl.SslContext; |
||||
import io.netty.handler.ssl.SslHandler; |
||||
|
||||
public class NettyTLSConnectionInitializer extends NettyConnectionInitializer { |
||||
|
||||
private final Optional<Supplier<TLSContextFactory>> tlsContextFactorySupplier; |
||||
private final Boolean clientHelloSniHeaderEnabled; |
||||
|
||||
public NettyTLSConnectionInitializer( |
||||
final NodeKey nodeKey, |
||||
final RlpxConfiguration config, |
||||
final LocalNode localNode, |
||||
final PeerConnectionEventDispatcher eventDispatcher, |
||||
final MetricsSystem metricsSystem, |
||||
final TLSConfiguration p2pTLSConfiguration, |
||||
final PeerTable peerTable) { |
||||
this( |
||||
nodeKey, |
||||
config, |
||||
localNode, |
||||
eventDispatcher, |
||||
metricsSystem, |
||||
defaultTlsContextFactorySupplier(p2pTLSConfiguration), |
||||
p2pTLSConfiguration.getClientHelloSniHeaderEnabled(), |
||||
peerTable); |
||||
} |
||||
|
||||
@VisibleForTesting |
||||
NettyTLSConnectionInitializer( |
||||
final NodeKey nodeKey, |
||||
final RlpxConfiguration config, |
||||
final LocalNode localNode, |
||||
final PeerConnectionEventDispatcher eventDispatcher, |
||||
final MetricsSystem metricsSystem, |
||||
final Supplier<TLSContextFactory> tlsContextFactorySupplier, |
||||
final Boolean clientHelloSniHeaderEnabled, |
||||
final PeerTable peerTable) { |
||||
super(nodeKey, config, localNode, eventDispatcher, metricsSystem, peerTable); |
||||
if (tlsContextFactorySupplier != null) { |
||||
this.tlsContextFactorySupplier = |
||||
Optional.of(Suppliers.memoize(tlsContextFactorySupplier::get)); |
||||
} else { |
||||
this.tlsContextFactorySupplier = Optional.empty(); |
||||
} |
||||
this.clientHelloSniHeaderEnabled = clientHelloSniHeaderEnabled; |
||||
} |
||||
|
||||
@Override |
||||
void addAdditionalOutboundHandlers(final Channel ch, final Peer peer) |
||||
throws GeneralSecurityException { |
||||
if (tlsContextFactorySupplier.isPresent()) { |
||||
final SslContext clientSslContext = |
||||
tlsContextFactorySupplier.get().get().createNettyClientSslContext(); |
||||
final EnodeURL enode = peer.getEnodeURL(); |
||||
final SslHandler sslHandler = createClientSslHandler(ch, clientSslContext, enode); |
||||
addHandlersToChannelPipeline(ch, sslHandler); |
||||
} |
||||
} |
||||
|
||||
private SslHandler createClientSslHandler( |
||||
final Channel ch, final SslContext sslContext, final EnodeURL enode) { |
||||
if (this.clientHelloSniHeaderEnabled) { |
||||
return sslContext.newHandler( |
||||
ch.alloc(), enode.getHost(), enode.getListeningPort().orElseThrow()); |
||||
} else { |
||||
return sslContext.newHandler(ch.alloc()); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
void addAdditionalInboundHandlers(final Channel ch) throws GeneralSecurityException { |
||||
if (tlsContextFactorySupplier.isPresent()) { |
||||
final SslContext serverSslContext = |
||||
tlsContextFactorySupplier.get().get().createNettyServerSslContext(); |
||||
addHandlersToChannelPipeline(ch, serverSslContext.newHandler(ch.alloc())); |
||||
} |
||||
} |
||||
|
||||
private void addHandlersToChannelPipeline(final Channel ch, final SslHandler sslHandler) { |
||||
ch.pipeline().addLast(sslHandler); |
||||
ch.pipeline().addLast(new SnappyFrameDecoder()); |
||||
ch.pipeline().addLast(new SnappyFrameEncoder()); |
||||
ch.pipeline() |
||||
.addLast( |
||||
new LengthFieldBasedFrameDecoder( |
||||
LENGTH_MAX_MESSAGE_FRAME, 0, LENGTH_FRAME_SIZE, 0, LENGTH_FRAME_SIZE)); |
||||
ch.pipeline().addLast(new LengthFieldPrepender(LENGTH_FRAME_SIZE)); |
||||
} |
||||
|
||||
@Override |
||||
public Handshaker buildInstance() { |
||||
return new PlainHandshaker(); |
||||
} |
||||
|
||||
@Override |
||||
public Framer buildFramer(final HandshakeSecrets secrets) { |
||||
return new PlainFramer(); |
||||
} |
||||
|
||||
@VisibleForTesting |
||||
static Supplier<TLSContextFactory> defaultTlsContextFactorySupplier( |
||||
final TLSConfiguration tlsConfiguration) { |
||||
if (tlsConfiguration == null) { |
||||
throw new IllegalStateException("TLSConfiguration cannot be null when using TLS"); |
||||
} |
||||
|
||||
return () -> { |
||||
try { |
||||
return TLSContextFactory.buildFrom(tlsConfiguration); |
||||
} catch (final Exception e) { |
||||
throw new IllegalStateException("Error creating TLSContextFactory", e); |
||||
} |
||||
}; |
||||
} |
||||
} |
@ -1,197 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty; |
||||
|
||||
import static java.util.Objects.requireNonNull; |
||||
|
||||
import java.nio.file.Path; |
||||
import java.util.function.Supplier; |
||||
|
||||
public class TLSConfiguration { |
||||
|
||||
private final String keyStoreType; |
||||
private final Path keyStorePath; |
||||
private final Supplier<String> keyStorePasswordSupplier; |
||||
private final Path keyStorePasswordPath; |
||||
private final String trustStoreType; |
||||
private final Path trustStorePath; |
||||
private final Supplier<String> trustStorePasswordSupplier; |
||||
private final Path trustStorePasswordPath; |
||||
private final Path crlPath; |
||||
private final String[] allowedProtocols; |
||||
private final Boolean clientHelloSniHeaderEnabled; |
||||
|
||||
private TLSConfiguration( |
||||
final String keyStoreType, |
||||
final Path keyStorePath, |
||||
final Supplier<String> keyStorePasswordSupplier, |
||||
final Path keyStorePasswordPath, |
||||
final String trustStoreType, |
||||
final Path trustStorePath, |
||||
final Supplier<String> trustStorePasswordSupplier, |
||||
final Path trustStorePasswordPath, |
||||
final Path crlPath, |
||||
final String[] allowedProtocols, |
||||
final Boolean clientHelloSniHeaderEnabled) { |
||||
this.keyStoreType = keyStoreType; |
||||
this.keyStorePath = keyStorePath; |
||||
this.keyStorePasswordSupplier = keyStorePasswordSupplier; |
||||
this.keyStorePasswordPath = keyStorePasswordPath; |
||||
this.trustStoreType = trustStoreType; |
||||
this.trustStorePath = trustStorePath; |
||||
this.trustStorePasswordSupplier = trustStorePasswordSupplier; |
||||
this.trustStorePasswordPath = trustStorePasswordPath; |
||||
this.crlPath = crlPath; |
||||
this.allowedProtocols = allowedProtocols; |
||||
this.clientHelloSniHeaderEnabled = clientHelloSniHeaderEnabled; |
||||
} |
||||
|
||||
public String getKeyStoreType() { |
||||
return keyStoreType; |
||||
} |
||||
|
||||
public Path getKeyStorePath() { |
||||
return keyStorePath; |
||||
} |
||||
|
||||
public String getKeyStorePassword() { |
||||
return null == keyStorePasswordSupplier ? null : keyStorePasswordSupplier.get(); |
||||
} |
||||
|
||||
public Path getKeyStorePasswordPath() { |
||||
return keyStorePasswordPath; |
||||
} |
||||
|
||||
public String getTrustStoreType() { |
||||
return trustStoreType; |
||||
} |
||||
|
||||
public Path getTrustStorePath() { |
||||
return trustStorePath; |
||||
} |
||||
|
||||
public String getTrustStorePassword() { |
||||
return null == trustStorePasswordSupplier ? null : trustStorePasswordSupplier.get(); |
||||
} |
||||
|
||||
public Path getTrustStorePasswordPath() { |
||||
return trustStorePasswordPath; |
||||
} |
||||
|
||||
public Path getCrlPath() { |
||||
return crlPath; |
||||
} |
||||
|
||||
public String[] getAllowedProtocols() { |
||||
return allowedProtocols; |
||||
} |
||||
|
||||
public Boolean getClientHelloSniHeaderEnabled() { |
||||
return clientHelloSniHeaderEnabled; |
||||
} |
||||
|
||||
public static final class Builder { |
||||
private String keyStoreType; |
||||
private Path keyStorePath; |
||||
private Supplier<String> keyStorePasswordSupplier; |
||||
private Path keyStorePasswordPath; |
||||
private String trustStoreType; |
||||
private Path trustStorePath; |
||||
private Supplier<String> trustStorePasswordSupplier; |
||||
private Path trustStorePasswordPath; |
||||
private Path crlPath; |
||||
private String[] allowedProtocols; |
||||
private Boolean clientHelloSniHeaderEnabled; |
||||
|
||||
private Builder() {} |
||||
|
||||
public static Builder tlsConfiguration() { |
||||
return new Builder(); |
||||
} |
||||
|
||||
public Builder withKeyStoreType(final String keyStoreType) { |
||||
this.keyStoreType = keyStoreType; |
||||
return this; |
||||
} |
||||
|
||||
public Builder withKeyStorePath(final Path keyStorePath) { |
||||
this.keyStorePath = keyStorePath; |
||||
return this; |
||||
} |
||||
|
||||
public Builder withKeyStorePasswordPath(final Path keyStorePasswordPath) { |
||||
this.keyStorePasswordPath = keyStorePasswordPath; |
||||
return this; |
||||
} |
||||
|
||||
public Builder withKeyStorePasswordSupplier(final Supplier<String> keyStorePasswordSupplier) { |
||||
this.keyStorePasswordSupplier = keyStorePasswordSupplier; |
||||
return this; |
||||
} |
||||
|
||||
public Builder withTrustStoreType(final String trustStoreType) { |
||||
this.trustStoreType = trustStoreType; |
||||
return this; |
||||
} |
||||
|
||||
public Builder withTrustStorePath(final Path trustStorePath) { |
||||
this.trustStorePath = trustStorePath; |
||||
return this; |
||||
} |
||||
|
||||
public Builder withTrustStorePasswordSupplier( |
||||
final Supplier<String> trustStorePasswordSupplier) { |
||||
this.trustStorePasswordSupplier = trustStorePasswordSupplier; |
||||
return this; |
||||
} |
||||
|
||||
public Builder withTrustStorePasswordPath(final Path trustStorePasswordPath) { |
||||
this.trustStorePasswordPath = trustStorePasswordPath; |
||||
return this; |
||||
} |
||||
|
||||
public Builder withCrlPath(final Path crlPath) { |
||||
this.crlPath = crlPath; |
||||
return this; |
||||
} |
||||
|
||||
public Builder withAllowedProtocols(final String[] allowedProtocols) { |
||||
this.allowedProtocols = allowedProtocols; |
||||
return this; |
||||
} |
||||
|
||||
public Builder withClientHelloSniEnabled(final Boolean clientHelloSniHeaderEnabled) { |
||||
this.clientHelloSniHeaderEnabled = clientHelloSniHeaderEnabled; |
||||
return this; |
||||
} |
||||
|
||||
public TLSConfiguration build() { |
||||
requireNonNull(keyStoreType, "Key Store Type must not be null"); |
||||
requireNonNull(keyStorePasswordSupplier, "Key Store password supplier must not be null"); |
||||
return new TLSConfiguration( |
||||
keyStoreType, |
||||
keyStorePath, |
||||
keyStorePasswordSupplier, |
||||
keyStorePasswordPath, |
||||
trustStoreType, |
||||
trustStorePath, |
||||
trustStorePasswordSupplier, |
||||
trustStorePasswordPath, |
||||
crlPath, |
||||
allowedProtocols, |
||||
clientHelloSniHeaderEnabled); |
||||
} |
||||
} |
||||
} |
@ -1,230 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty; |
||||
|
||||
import org.hyperledger.besu.pki.keystore.HardwareKeyStoreWrapper; |
||||
import org.hyperledger.besu.pki.keystore.KeyStoreWrapper; |
||||
import org.hyperledger.besu.pki.keystore.SoftwareKeyStoreWrapper; |
||||
|
||||
import java.io.IOException; |
||||
import java.security.GeneralSecurityException; |
||||
import java.security.KeyManagementException; |
||||
import java.security.KeyStore; |
||||
import java.security.NoSuchAlgorithmException; |
||||
import java.security.cert.CertificateException; |
||||
import java.security.cert.X509CRL; |
||||
import java.security.cert.X509Certificate; |
||||
import java.util.Arrays; |
||||
import java.util.Collection; |
||||
import java.util.Comparator; |
||||
import java.util.List; |
||||
import javax.net.ssl.KeyManagerFactory; |
||||
import javax.net.ssl.SSLContext; |
||||
import javax.net.ssl.TrustManager; |
||||
import javax.net.ssl.TrustManagerFactory; |
||||
import javax.net.ssl.X509TrustManager; |
||||
|
||||
import io.netty.handler.ssl.ClientAuth; |
||||
import io.netty.handler.ssl.IdentityCipherSuiteFilter; |
||||
import io.netty.handler.ssl.JdkSslContext; |
||||
import io.netty.handler.ssl.SslContext; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
public class TLSContextFactory { |
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TLSContextFactory.class); |
||||
|
||||
private static final String[] ALLOWED_PROTOCOLS = {"TLSv1.3"}; |
||||
private static final String KEYMANAGER_FACTORY_ALGORITHM = "PKIX"; |
||||
private static final String TRUSTMANAGER_FACTORY_ALGORITHM = "PKIX"; |
||||
|
||||
private List<String> enabledCipherSuites = null; |
||||
private KeyManagerFactory kmf; |
||||
private TrustManagerFactory tmf; |
||||
private Collection<X509CRL> crls; |
||||
private String[] allowedProtocols; |
||||
|
||||
protected TLSContextFactory() {} |
||||
|
||||
protected TLSContextFactory( |
||||
final String keystorePass, |
||||
final KeyStoreWrapper keystoreWrapper, |
||||
final List<String> configuredCipherSuites, |
||||
final String[] allowedProtocols) |
||||
throws GeneralSecurityException, IOException { |
||||
kmf = getKeyManagerFactory(keystoreWrapper.getKeyStore(), keystorePass); |
||||
tmf = getTrustManagerFactory(keystoreWrapper.getTrustStore()); |
||||
crls = keystoreWrapper.getCRLs(); |
||||
if (configuredCipherSuites != null && !configuredCipherSuites.isEmpty()) { |
||||
enabledCipherSuites = configuredCipherSuites; |
||||
} |
||||
this.allowedProtocols = null == allowedProtocols ? ALLOWED_PROTOCOLS : allowedProtocols; |
||||
} |
||||
|
||||
public static TLSContextFactory getInstance( |
||||
final String keyStorePassword, final KeyStoreWrapper wrapper, final String[] allowedProtocols) |
||||
throws GeneralSecurityException, IOException { |
||||
return new TLSContextFactory(keyStorePassword, wrapper, null, allowedProtocols); |
||||
} |
||||
|
||||
public static TLSContextFactory getInstance( |
||||
final String keyStorePassword, final KeyStoreWrapper wrapper) |
||||
throws GeneralSecurityException, IOException { |
||||
return new TLSContextFactory(keyStorePassword, wrapper, null, null); |
||||
} |
||||
|
||||
public SslContext createNettyServerSslContext() |
||||
throws NoSuchAlgorithmException, KeyManagementException { |
||||
final List<String> enabledCipherSuites = getEnabledCipherSuites(); |
||||
|
||||
return new JdkSslContext( |
||||
createJavaSslContext(), |
||||
false, |
||||
enabledCipherSuites, |
||||
IdentityCipherSuiteFilter.INSTANCE, |
||||
null, |
||||
ClientAuth.REQUIRE, |
||||
null, |
||||
false); |
||||
} |
||||
|
||||
public SslContext createNettyClientSslContext() |
||||
throws NoSuchAlgorithmException, KeyManagementException { |
||||
final List<String> enabledCipherSuites = getEnabledCipherSuites(); |
||||
|
||||
return new JdkSslContext( |
||||
createJavaSslContext(), |
||||
true, |
||||
enabledCipherSuites, |
||||
IdentityCipherSuiteFilter.INSTANCE, |
||||
null, |
||||
ClientAuth.NONE, |
||||
null, |
||||
false); |
||||
} |
||||
|
||||
public SSLContext createJavaSslContext() throws NoSuchAlgorithmException, KeyManagementException { |
||||
final SSLContext context = SSLContext.getInstance(getTlsProtocol()); |
||||
context.init( |
||||
kmf.getKeyManagers(), |
||||
null == crls || crls.isEmpty() ? tmf.getTrustManagers() : wrap(tmf.getTrustManagers()), |
||||
null); |
||||
return context; |
||||
} |
||||
|
||||
protected TrustManager[] wrap(final TrustManager[] trustMgrs) { |
||||
final TrustManager[] ret = trustMgrs.clone(); |
||||
for (int i = 0; i < ret.length; i++) { |
||||
TrustManager trustMgr = ret[i]; |
||||
if (trustMgr instanceof X509TrustManager) { |
||||
X509TrustManager x509TrustManager = (X509TrustManager) trustMgr; |
||||
ret[i] = |
||||
new X509TrustManager() { |
||||
@Override |
||||
public void checkClientTrusted( |
||||
final X509Certificate[] x509Certificates, final String s) |
||||
throws CertificateException { |
||||
checkRevoked(x509Certificates); |
||||
x509TrustManager.checkClientTrusted(x509Certificates, s); |
||||
} |
||||
|
||||
@Override |
||||
public void checkServerTrusted( |
||||
final X509Certificate[] x509Certificates, final String s) |
||||
throws CertificateException { |
||||
checkRevoked(x509Certificates); |
||||
x509TrustManager.checkServerTrusted(x509Certificates, s); |
||||
} |
||||
|
||||
private void checkRevoked(final X509Certificate[] x509Certificates) |
||||
throws CertificateException { |
||||
for (X509CRL crl : crls) { |
||||
for (X509Certificate cert : x509Certificates) { |
||||
if (crl.isRevoked(cert)) { |
||||
throw new CertificateException("Certificate revoked"); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public X509Certificate[] getAcceptedIssuers() { |
||||
return x509TrustManager.getAcceptedIssuers(); |
||||
} |
||||
}; |
||||
} |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
protected TrustManagerFactory getTrustManagerFactory(final KeyStore truststore) |
||||
throws GeneralSecurityException { |
||||
final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TRUSTMANAGER_FACTORY_ALGORITHM); |
||||
tmf.init(truststore); |
||||
return tmf; |
||||
} |
||||
|
||||
protected KeyManagerFactory getKeyManagerFactory( |
||||
final KeyStore keystore, final String keystorePassword) throws GeneralSecurityException { |
||||
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEYMANAGER_FACTORY_ALGORITHM); |
||||
kmf.init(keystore, keystorePassword.toCharArray()); |
||||
return kmf; |
||||
} |
||||
|
||||
private List<String> getEnabledCipherSuites() { |
||||
final String protocol = getTlsProtocol(); |
||||
try { |
||||
if (enabledCipherSuites == null || enabledCipherSuites.isEmpty()) { |
||||
final SSLContext sslcontext = SSLContext.getInstance(protocol); |
||||
sslcontext.init(null, null, null); |
||||
enabledCipherSuites = Arrays.asList(sslcontext.createSSLEngine().getEnabledCipherSuites()); |
||||
} |
||||
} catch (final NoSuchAlgorithmException | KeyManagementException e) { |
||||
LOG.warn( |
||||
"Could not get list of enabled (JDK) cipher suites for protocol:{}, reverting to Netty's default ones.", |
||||
protocol); |
||||
} |
||||
return enabledCipherSuites; |
||||
} |
||||
|
||||
private String getTlsProtocol() { |
||||
return Arrays.stream(allowedProtocols).max(Comparator.naturalOrder()).orElse(null); |
||||
} |
||||
|
||||
public static TLSContextFactory buildFrom(final TLSConfiguration config) |
||||
throws GeneralSecurityException, IOException { |
||||
TLSContextFactory ret = null; |
||||
if (null != config) { |
||||
LOG.info("Initializing SSL Context using {} keystore.", config.getKeyStoreType()); |
||||
KeyStoreWrapper wrapper = |
||||
KeyStoreWrapper.KEYSTORE_TYPE_PKCS11.equalsIgnoreCase(config.getKeyStoreType()) |
||||
? new HardwareKeyStoreWrapper( |
||||
config.getKeyStorePassword(), config.getKeyStorePath(), config.getCrlPath()) |
||||
: new SoftwareKeyStoreWrapper( |
||||
config.getKeyStoreType(), |
||||
config.getKeyStorePath(), |
||||
config.getKeyStorePassword(), |
||||
config.getTrustStoreType(), |
||||
config.getTrustStorePath(), |
||||
config.getTrustStorePassword(), |
||||
config.getCrlPath()); |
||||
ret = |
||||
TLSContextFactory.getInstance( |
||||
config.getKeyStorePassword(), wrapper, config.getAllowedProtocols()); |
||||
} |
||||
return ret; |
||||
} |
||||
} |
@ -1,195 +0,0 @@ |
||||
/* |
||||
* Copyright contributors to Hyperledger Besu. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty; |
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat; |
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; |
||||
import static org.mockito.ArgumentMatchers.any; |
||||
import static org.mockito.ArgumentMatchers.eq; |
||||
import static org.mockito.Mockito.mock; |
||||
import static org.mockito.Mockito.verify; |
||||
import static org.mockito.Mockito.when; |
||||
|
||||
import org.hyperledger.besu.cryptoservices.NodeKey; |
||||
import org.hyperledger.besu.ethereum.p2p.config.RlpxConfiguration; |
||||
import org.hyperledger.besu.ethereum.p2p.discovery.internal.PeerTable; |
||||
import org.hyperledger.besu.ethereum.p2p.peers.LocalNode; |
||||
import org.hyperledger.besu.ethereum.p2p.peers.Peer; |
||||
import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnectionEventDispatcher; |
||||
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; |
||||
import org.hyperledger.besu.plugin.data.EnodeURL; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Optional; |
||||
|
||||
import com.google.common.collect.ImmutableList; |
||||
import io.netty.channel.ChannelPipeline; |
||||
import io.netty.channel.embedded.EmbeddedChannel; |
||||
import io.netty.handler.codec.LengthFieldBasedFrameDecoder; |
||||
import io.netty.handler.codec.LengthFieldPrepender; |
||||
import io.netty.handler.codec.compression.SnappyFrameDecoder; |
||||
import io.netty.handler.codec.compression.SnappyFrameEncoder; |
||||
import io.netty.handler.ssl.SslContext; |
||||
import io.netty.handler.ssl.SslHandler; |
||||
import org.apache.tuweni.bytes.Bytes; |
||||
import org.junit.jupiter.api.BeforeEach; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.api.extension.ExtendWith; |
||||
import org.mockito.Mock; |
||||
import org.mockito.junit.jupiter.MockitoExtension; |
||||
import org.mockito.junit.jupiter.MockitoSettings; |
||||
import org.mockito.quality.Strictness; |
||||
|
||||
@ExtendWith(MockitoExtension.class) |
||||
@MockitoSettings(strictness = Strictness.LENIENT) |
||||
public class NettyTLSConnectionInitializerTest { |
||||
|
||||
private static final String PEER_HOST = "hyperledger.org"; |
||||
private static final int PEER_PORT = 30303; |
||||
@Mock private NodeKey nodeKey; |
||||
@Mock private RlpxConfiguration rlpxConfiguration; |
||||
@Mock private LocalNode localNode; |
||||
@Mock private PeerConnectionEventDispatcher eventDispatcher; |
||||
@Mock private TLSContextFactory tlsContextFactory; |
||||
@Mock private SslContext clientSslContext; |
||||
@Mock private SslContext serverSslContext; |
||||
@Mock private SslHandler clientSslHandler; |
||||
@Mock private SslHandler serverSslHandler; |
||||
@Mock private Peer peer; |
||||
@Mock private EnodeURL enodeURL; |
||||
|
||||
private NettyTLSConnectionInitializer nettyTLSConnectionInitializer; |
||||
|
||||
@BeforeEach |
||||
public void before() throws Exception { |
||||
nettyTLSConnectionInitializer = createNettyTLSConnectionInitializer(false); |
||||
|
||||
when(tlsContextFactory.createNettyServerSslContext()).thenReturn(serverSslContext); |
||||
when(serverSslContext.newHandler(any())).thenReturn(serverSslHandler); |
||||
|
||||
when(tlsContextFactory.createNettyClientSslContext()).thenReturn(clientSslContext); |
||||
when(clientSslContext.newHandler(any())).thenReturn(clientSslHandler); |
||||
when(peer.getEnodeURL()).thenReturn(enodeURL); |
||||
when(enodeURL.getHost()).thenReturn(PEER_HOST); |
||||
when(enodeURL.getListeningPort()).thenReturn(Optional.of(PEER_PORT)); |
||||
} |
||||
|
||||
private NettyTLSConnectionInitializer createNettyTLSConnectionInitializer( |
||||
final boolean clientHelloSniHeaderEnabled) { |
||||
return new NettyTLSConnectionInitializer( |
||||
nodeKey, |
||||
rlpxConfiguration, |
||||
localNode, |
||||
eventDispatcher, |
||||
new NoOpMetricsSystem(), |
||||
() -> tlsContextFactory, |
||||
clientHelloSniHeaderEnabled, |
||||
new PeerTable(Bytes.random(64))); |
||||
} |
||||
|
||||
@Test |
||||
public void addAdditionalOutboundHandlersIncludesAllExpectedHandlersToChannelPipeline() |
||||
throws Exception { |
||||
final EmbeddedChannel embeddedChannel = new EmbeddedChannel(); |
||||
nettyTLSConnectionInitializer.addAdditionalOutboundHandlers(embeddedChannel, peer); |
||||
|
||||
// TLS
|
||||
assertThat(embeddedChannel.pipeline().get(SslHandler.class)).isEqualTo(clientSslHandler); |
||||
|
||||
// Snappy compression
|
||||
assertThat(embeddedChannel.pipeline().get(SnappyFrameDecoder.class)).isNotNull(); |
||||
assertThat(embeddedChannel.pipeline().get(SnappyFrameEncoder.class)).isNotNull(); |
||||
|
||||
// Message Framing
|
||||
assertThat(embeddedChannel.pipeline().get(LengthFieldBasedFrameDecoder.class)).isNotNull(); |
||||
assertThat(embeddedChannel.pipeline().get(LengthFieldPrepender.class)).isNotNull(); |
||||
|
||||
assertHandlersOrderInPipeline(embeddedChannel.pipeline()); |
||||
} |
||||
|
||||
@Test |
||||
public void addAdditionalOutboundHandlersUsesSslHandlerWithSniHeaderEnabledIfConfigured() |
||||
throws Exception { |
||||
nettyTLSConnectionInitializer = createNettyTLSConnectionInitializer(true); |
||||
when(clientSslContext.newHandler(any(), eq(PEER_HOST), eq(PEER_PORT))) |
||||
.thenReturn(clientSslHandler); |
||||
|
||||
final EmbeddedChannel embeddedChannel = new EmbeddedChannel(); |
||||
nettyTLSConnectionInitializer.addAdditionalOutboundHandlers(embeddedChannel, peer); |
||||
|
||||
// Handler with SNI params was created
|
||||
verify(clientSslContext).newHandler(any(), eq(PEER_HOST), eq(PEER_PORT)); |
||||
|
||||
// Other handlers are still present as expected
|
||||
assertHandlersOrderInPipeline(embeddedChannel.pipeline()); |
||||
} |
||||
|
||||
@Test |
||||
public void addAdditionalInboundHandlersIncludesAllExpectedHandlersToChannelPipeline() |
||||
throws Exception { |
||||
final EmbeddedChannel embeddedChannel = new EmbeddedChannel(); |
||||
nettyTLSConnectionInitializer.addAdditionalInboundHandlers(embeddedChannel); |
||||
|
||||
// TLS
|
||||
assertThat(embeddedChannel.pipeline().get(SslHandler.class)).isEqualTo(serverSslHandler); |
||||
|
||||
// Snappy compression
|
||||
assertThat(embeddedChannel.pipeline().get(SnappyFrameDecoder.class)).isNotNull(); |
||||
assertThat(embeddedChannel.pipeline().get(SnappyFrameEncoder.class)).isNotNull(); |
||||
|
||||
// Message Framing
|
||||
assertThat(embeddedChannel.pipeline().get(LengthFieldBasedFrameDecoder.class)).isNotNull(); |
||||
assertThat(embeddedChannel.pipeline().get(LengthFieldPrepender.class)).isNotNull(); |
||||
|
||||
assertHandlersOrderInPipeline(embeddedChannel.pipeline()); |
||||
} |
||||
|
||||
private void assertHandlersOrderInPipeline(final ChannelPipeline pipeline) { |
||||
// Appending '#0' because Netty adds it to the handler's names
|
||||
final ArrayList<String> expectedHandlerNamesInOrder = |
||||
new ArrayList<>( |
||||
ImmutableList.of( |
||||
"SslHandler#0", |
||||
"SnappyFrameDecoder#0", |
||||
"SnappyFrameEncoder#0", |
||||
"LengthFieldBasedFrameDecoder#0", |
||||
"LengthFieldPrepender#0", |
||||
"DefaultChannelPipeline$TailContext#0")); // This final handler is Netty's default
|
||||
|
||||
final List<String> actualHandlerNamesInOrder = pipeline.names(); |
||||
assertThat(actualHandlerNamesInOrder).isEqualTo(expectedHandlerNamesInOrder); |
||||
} |
||||
|
||||
@Test |
||||
public void defaultTlsContextFactorySupplierThrowsErrorWithNullTLSConfiguration() { |
||||
assertThatThrownBy(() -> NettyTLSConnectionInitializer.defaultTlsContextFactorySupplier(null)) |
||||
.isInstanceOf(IllegalStateException.class) |
||||
.hasMessage("TLSConfiguration cannot be null when using TLS"); |
||||
} |
||||
|
||||
@Test |
||||
public void defaultTlsContextFactorySupplierCapturesInternalError() { |
||||
final TLSConfiguration tlsConfiguration = mock(TLSConfiguration.class); |
||||
when(tlsConfiguration.getKeyStoreType()).thenThrow(new RuntimeException()); |
||||
|
||||
assertThatThrownBy( |
||||
() -> |
||||
NettyTLSConnectionInitializer.defaultTlsContextFactorySupplier(tlsConfiguration) |
||||
.get()) |
||||
.isInstanceOf(IllegalStateException.class) |
||||
.hasMessage("Error creating TLSContextFactory"); |
||||
} |
||||
} |
@ -1,504 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.hyperledger.besu.pki.keystore.KeyStoreWrapper.KEYSTORE_TYPE_PKCS12; |
||||
|
||||
import org.hyperledger.besu.pki.PkiException; |
||||
import org.hyperledger.besu.pki.keystore.HardwareKeyStoreWrapper; |
||||
import org.hyperledger.besu.pki.keystore.KeyStoreWrapper; |
||||
import org.hyperledger.besu.pki.keystore.SoftwareKeyStoreWrapper; |
||||
|
||||
import java.net.InetSocketAddress; |
||||
import java.nio.file.Path; |
||||
import java.util.Arrays; |
||||
import java.util.Collection; |
||||
import java.util.Optional; |
||||
import java.util.concurrent.CountDownLatch; |
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
import io.netty.bootstrap.Bootstrap; |
||||
import io.netty.bootstrap.ServerBootstrap; |
||||
import io.netty.buffer.ByteBuf; |
||||
import io.netty.buffer.Unpooled; |
||||
import io.netty.channel.Channel; |
||||
import io.netty.channel.ChannelFuture; |
||||
import io.netty.channel.ChannelHandlerContext; |
||||
import io.netty.channel.ChannelInboundHandlerAdapter; |
||||
import io.netty.channel.ChannelInitializer; |
||||
import io.netty.channel.EventLoopGroup; |
||||
import io.netty.channel.nio.NioEventLoopGroup; |
||||
import io.netty.channel.socket.SocketChannel; |
||||
import io.netty.channel.socket.nio.NioServerSocketChannel; |
||||
import io.netty.channel.socket.nio.NioSocketChannel; |
||||
import io.netty.handler.ssl.SslContext; |
||||
import io.netty.handler.ssl.SslHandler; |
||||
import org.junit.jupiter.api.AfterEach; |
||||
import org.junit.jupiter.api.BeforeEach; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.api.condition.DisabledOnOs; |
||||
import org.junit.jupiter.api.condition.OS; |
||||
import org.junit.jupiter.params.ParameterizedTest; |
||||
import org.junit.jupiter.params.provider.MethodSource; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
class TLSContextFactoryTest { |
||||
|
||||
// see resources/keys/README.md for setup details.
|
||||
private static final String keystorePassword = "test123"; |
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TLSContextFactoryTest.class); |
||||
|
||||
private static final int MAX_NUMBER_MESSAGES = 10; |
||||
private static final String CRL_PEM = "/keys/crl/crl.pem"; |
||||
private static final String PARTNER1_CLIENT1_PKCS11 = "/keys/partner1client1/nss.cfg"; |
||||
private static final String PARTNER1_CLIENT1_KEYSTORE = "/keys/partner1client1/client1.p12"; |
||||
private static final String PARTNET1_CLIENT2_KEYSTORE = "/keys/partner1client2rvk/client2.p12"; |
||||
private static final String PARTNER2_CLIENT1_KEYSTORE = "/keys/partner2client1/client1.p12"; |
||||
private static final String PARTNER2_CLIENT2_KEYSTORE = "/keys/partner2client2rvk/client2.p12"; |
||||
private static final String INVALIDPARTNER1_CLIENT1_KEYSTORE = |
||||
"/keys/invalidpartner1client1/client1.p12"; |
||||
|
||||
private static final String PARTNER1_CLIENT1_TRUSTSTORE = "/keys/partner1client1/truststore.p12"; |
||||
private static final String PARTNET1_CLIENT2_TRUSTSTORE = |
||||
"/keys/partner1client2rvk/truststore.p12"; |
||||
private static final String PARTNER2_CLIENT1_TRUSTSTORE = "/keys/partner2client1/truststore.p12"; |
||||
private static final String PARTNER2_CLIENT2_TRUSTSTORE = |
||||
"/keys/partner2client2rvk/truststore.p12"; |
||||
private static final String INVALIDPARTNER1_CLIENT1_TRUSTSTORE = |
||||
"/keys/invalidpartner1client1/truststore.p12"; |
||||
|
||||
private Server server; |
||||
private Client client; |
||||
|
||||
static Collection<Object[]> hardwareKeysData() { |
||||
return Arrays.asList( |
||||
new Object[][] { |
||||
{ |
||||
"PKCS11 server Partner1 Client1 -> PKCS12 client Partner2 Client1 SuccessfulConnection", |
||||
true, |
||||
getHardwareKeyStoreWrapper(PARTNER1_CLIENT1_PKCS11, CRL_PEM), |
||||
getSoftwareKeyStoreWrapper( |
||||
PARTNER2_CLIENT1_KEYSTORE, PARTNER2_CLIENT1_TRUSTSTORE, CRL_PEM), |
||||
Optional.empty(), |
||||
Optional.empty() |
||||
}, |
||||
{ |
||||
"PKCS11 server Partner1 Client1 -> PKCS12 client InvalidPartner1 Client1 FailedConnection", |
||||
false, |
||||
getHardwareKeyStoreWrapper(PARTNER1_CLIENT1_PKCS11, CRL_PEM), |
||||
getSoftwareKeyStoreWrapper( |
||||
INVALIDPARTNER1_CLIENT1_KEYSTORE, INVALIDPARTNER1_CLIENT1_TRUSTSTORE, null), |
||||
Optional.empty(), |
||||
Optional.of("certificate_unknown") |
||||
}, |
||||
{ |
||||
"PKCS11 server Partner1 Client1 -> PKCS12 client Partner2 Client2 revoked FailedConnection", |
||||
false, |
||||
getHardwareKeyStoreWrapper(PARTNER1_CLIENT1_PKCS11, CRL_PEM), |
||||
getSoftwareKeyStoreWrapper( |
||||
PARTNER2_CLIENT2_KEYSTORE, PARTNER2_CLIENT2_TRUSTSTORE, null), |
||||
Optional.of("Certificate revoked"), |
||||
Optional.of("certificate_unknown") |
||||
}, |
||||
}); |
||||
} |
||||
|
||||
static Collection<Object[]> softwareKeysData() { |
||||
return Arrays.asList( |
||||
new Object[][] { |
||||
{ |
||||
"PKCS12 server Partner1 Client1 -> PKCS12 client Partner2 Client1 SuccessfulConnection", |
||||
true, |
||||
getSoftwareKeyStoreWrapper( |
||||
PARTNER1_CLIENT1_KEYSTORE, PARTNER1_CLIENT1_TRUSTSTORE, CRL_PEM), |
||||
getSoftwareKeyStoreWrapper( |
||||
PARTNER2_CLIENT1_KEYSTORE, PARTNER2_CLIENT1_TRUSTSTORE, CRL_PEM), |
||||
Optional.empty(), |
||||
Optional.empty() |
||||
}, |
||||
{ |
||||
"PKCS12 server Partner2 Client1 -> PKCS12 client Partner1 Client1 SuccessfulConnection", |
||||
true, |
||||
getSoftwareKeyStoreWrapper( |
||||
PARTNER2_CLIENT1_KEYSTORE, PARTNER2_CLIENT1_TRUSTSTORE, CRL_PEM), |
||||
getSoftwareKeyStoreWrapper( |
||||
PARTNER1_CLIENT1_KEYSTORE, PARTNER1_CLIENT1_TRUSTSTORE, CRL_PEM), |
||||
Optional.empty(), |
||||
Optional.empty() |
||||
}, |
||||
{ |
||||
"PKCS12 server Partner1 Client1 -> PKCS12 client InvalidPartner1 Client1 FailedConnection", |
||||
false, |
||||
getSoftwareKeyStoreWrapper( |
||||
PARTNER1_CLIENT1_KEYSTORE, PARTNER1_CLIENT1_TRUSTSTORE, CRL_PEM), |
||||
getSoftwareKeyStoreWrapper( |
||||
INVALIDPARTNER1_CLIENT1_KEYSTORE, INVALIDPARTNER1_CLIENT1_TRUSTSTORE, null), |
||||
Optional.empty(), |
||||
Optional.of("certificate_unknown") |
||||
}, |
||||
{ |
||||
"PKCS12 server InvalidPartner1 Client1 -> PKCS12 client Partner1 Client1 FailedConnection", |
||||
false, |
||||
getSoftwareKeyStoreWrapper( |
||||
INVALIDPARTNER1_CLIENT1_KEYSTORE, INVALIDPARTNER1_CLIENT1_TRUSTSTORE, null), |
||||
getSoftwareKeyStoreWrapper( |
||||
PARTNER1_CLIENT1_KEYSTORE, PARTNER1_CLIENT1_TRUSTSTORE, CRL_PEM), |
||||
Optional.of("certificate_unknown"), |
||||
Optional.empty() |
||||
}, |
||||
{ |
||||
"PKCS12 server Partner1 Client2 (revoked) -> PKCS12 client Partner2 Client1 FailedConnection", |
||||
false, |
||||
getSoftwareKeyStoreWrapper( |
||||
PARTNET1_CLIENT2_KEYSTORE, PARTNET1_CLIENT2_TRUSTSTORE, null), |
||||
getSoftwareKeyStoreWrapper( |
||||
PARTNER2_CLIENT1_KEYSTORE, PARTNER2_CLIENT1_TRUSTSTORE, CRL_PEM), |
||||
Optional.empty(), |
||||
Optional.of("Certificate revoked") |
||||
}, |
||||
{ |
||||
"PKCS12 server Partner2 Client1 -> PKCS12 client Partner1 Client2 (revoked) FailedConnection", |
||||
false, |
||||
getSoftwareKeyStoreWrapper( |
||||
PARTNER2_CLIENT1_KEYSTORE, PARTNER2_CLIENT1_TRUSTSTORE, CRL_PEM), |
||||
getSoftwareKeyStoreWrapper( |
||||
PARTNET1_CLIENT2_KEYSTORE, PARTNET1_CLIENT2_TRUSTSTORE, null), |
||||
Optional.of("Certificate revoked"), |
||||
Optional.of("certificate_unknown") |
||||
}, |
||||
{ |
||||
"PKCS12 server Partner2 Client2 (revoked) -> PKCS12 client Partner1 Client1 FailedConnection", |
||||
false, |
||||
getSoftwareKeyStoreWrapper( |
||||
PARTNER2_CLIENT2_KEYSTORE, PARTNER2_CLIENT2_TRUSTSTORE, null), |
||||
getSoftwareKeyStoreWrapper( |
||||
PARTNER1_CLIENT1_KEYSTORE, PARTNER1_CLIENT1_TRUSTSTORE, CRL_PEM), |
||||
Optional.empty(), |
||||
Optional.of("Certificate revoked"), |
||||
}, |
||||
{ |
||||
"PKCS12 server Partner1 Client1 -> PKCS12 client Partner2 Client2 (revoked) FailedConnection", |
||||
false, |
||||
getSoftwareKeyStoreWrapper( |
||||
PARTNER1_CLIENT1_KEYSTORE, PARTNER1_CLIENT1_TRUSTSTORE, CRL_PEM), |
||||
getSoftwareKeyStoreWrapper( |
||||
PARTNER2_CLIENT2_KEYSTORE, PARTNER2_CLIENT2_TRUSTSTORE, null), |
||||
Optional.of("Certificate revoked"), |
||||
Optional.of("certificate_unknown") |
||||
} |
||||
}); |
||||
} |
||||
|
||||
@BeforeEach |
||||
void init() {} |
||||
|
||||
@AfterEach |
||||
void tearDown() { |
||||
if (client != null) { |
||||
client.stop(); |
||||
} |
||||
if (server != null) { |
||||
server.stop(); |
||||
} |
||||
} |
||||
|
||||
private static Path toPath(final String path) throws Exception { |
||||
return null == path ? null : Path.of(TLSContextFactoryTest.class.getResource(path).toURI()); |
||||
} |
||||
|
||||
private static KeyStoreWrapper getHardwareKeyStoreWrapper( |
||||
final String config, final String crlLocation) { |
||||
try { |
||||
return new HardwareKeyStoreWrapper(keystorePassword, toPath(config), toPath(crlLocation)); |
||||
} catch (final Exception e) { |
||||
// Not a mac, probably a production build. Full failure.
|
||||
throw new PkiException("Failed to initialize hardware keystore", e); |
||||
} |
||||
} |
||||
|
||||
private static KeyStoreWrapper getSoftwareKeyStoreWrapper( |
||||
final String jksKeyStore, final String trustStore, final String crl) { |
||||
try { |
||||
return new SoftwareKeyStoreWrapper( |
||||
KEYSTORE_TYPE_PKCS12, |
||||
toPath(jksKeyStore), |
||||
keystorePassword, |
||||
KEYSTORE_TYPE_PKCS12, |
||||
toPath(trustStore), |
||||
keystorePassword, |
||||
toPath(crl)); |
||||
} catch (final Exception e) { |
||||
throw new PkiException("Failed to initialize software keystore", e); |
||||
} |
||||
} |
||||
|
||||
@ParameterizedTest(name = "{index}: {0}") |
||||
@MethodSource("softwareKeysData") |
||||
@DisabledOnOs(OS.MAC) |
||||
void testConnectionSoftwareKeys( |
||||
final String ignoredTestDescription, |
||||
final boolean testSuccess, |
||||
final KeyStoreWrapper serverKeyStoreWrapper, |
||||
final KeyStoreWrapper clientKeyStoreWrapper, |
||||
final Optional<String> serverFailureMessage, |
||||
final Optional<String> clientFailureMessage) |
||||
throws Exception { |
||||
testConnection( |
||||
testSuccess, |
||||
serverKeyStoreWrapper, |
||||
clientKeyStoreWrapper, |
||||
serverFailureMessage, |
||||
clientFailureMessage); |
||||
} |
||||
|
||||
@ParameterizedTest(name = "{index}: {0}") |
||||
@MethodSource("hardwareKeysData") |
||||
@DisabledOnOs(OS.MAC) |
||||
void testConnectionHardwareKeys( |
||||
final String ignoredTestDescription, |
||||
final boolean testSuccess, |
||||
final KeyStoreWrapper serverKeyStoreWrapper, |
||||
final KeyStoreWrapper clientKeyStoreWrapper, |
||||
final Optional<String> serverFailureMessage, |
||||
final Optional<String> clientFailureMessage) |
||||
throws Exception { |
||||
testConnection( |
||||
testSuccess, |
||||
serverKeyStoreWrapper, |
||||
clientKeyStoreWrapper, |
||||
serverFailureMessage, |
||||
clientFailureMessage); |
||||
} |
||||
|
||||
private void testConnection( |
||||
final boolean testSuccess, |
||||
final KeyStoreWrapper serverKeyStoreWrapper, |
||||
final KeyStoreWrapper clientKeyStoreWrapper, |
||||
final Optional<String> serverFailureMessage, |
||||
final Optional<String> clientFailureMessage) |
||||
throws Exception { |
||||
final CountDownLatch serverLatch = new CountDownLatch(MAX_NUMBER_MESSAGES); |
||||
final CountDownLatch clientLatch = new CountDownLatch(MAX_NUMBER_MESSAGES); |
||||
server = startServer(serverKeyStoreWrapper, serverLatch); |
||||
client = startClient(server.port, clientKeyStoreWrapper, clientLatch); |
||||
|
||||
if (testSuccess) { |
||||
client.getChannelFuture().channel().writeAndFlush(Unpooled.copyInt(0)); |
||||
final boolean allMessagesServerExchanged = serverLatch.await(10, TimeUnit.SECONDS); |
||||
final boolean allMessagesClientExchanged = clientLatch.await(10, TimeUnit.SECONDS); |
||||
assertThat(allMessagesClientExchanged && allMessagesServerExchanged).isTrue(); |
||||
} else { |
||||
try { |
||||
client.getChannelFuture().channel().writeAndFlush(Unpooled.copyInt(0)).sync(); |
||||
serverLatch.await(2, TimeUnit.SECONDS); |
||||
assertThat(client.getChannelFuture().channel().isActive()).isFalse(); |
||||
|
||||
if (serverFailureMessage.isPresent()) { |
||||
assertThat(server.getCause()).isNotEmpty(); |
||||
assertThat(server.getCause().get()).hasMessageContaining(serverFailureMessage.get()); |
||||
} else { |
||||
assertThat(server.getCause()).isEmpty(); |
||||
} |
||||
|
||||
if (clientFailureMessage.isPresent()) { |
||||
assertThat(client.getCause()).isNotEmpty(); |
||||
assertThat(client.getCause().get()).hasMessageContaining(clientFailureMessage.get()); |
||||
} else { |
||||
assertThat(client.getCause()).isEmpty(); |
||||
} |
||||
} catch (final Exception e) { |
||||
// NOOP
|
||||
} |
||||
} |
||||
} |
||||
|
||||
private Server startServer(final KeyStoreWrapper keyStoreWrapper, final CountDownLatch latch) |
||||
throws Exception { |
||||
|
||||
final Server nettyServer = new Server(keystorePassword, keyStoreWrapper, latch); |
||||
nettyServer.start(); |
||||
return nettyServer; |
||||
} |
||||
|
||||
private Client startClient( |
||||
final int port, final KeyStoreWrapper keyStoreWrapper, final CountDownLatch latch) |
||||
throws Exception { |
||||
|
||||
final Client nettyClient = new Client(port, keystorePassword, keyStoreWrapper, latch); |
||||
nettyClient.start(); |
||||
return nettyClient; |
||||
} |
||||
|
||||
static class MessageHandler extends ChannelInboundHandlerAdapter { |
||||
private final String id; |
||||
private final CountDownLatch latch; |
||||
|
||||
private Throwable cause; |
||||
|
||||
MessageHandler(final String id, final CountDownLatch latch) { |
||||
this.id = id; |
||||
this.latch = latch; |
||||
} |
||||
|
||||
@Override |
||||
public void channelRead(final ChannelHandlerContext ctx, final Object msg) |
||||
throws InterruptedException { |
||||
final int message = ((ByteBuf) msg).readInt(); |
||||
LOG.info("[" + id + "] Received message: " + message); |
||||
|
||||
if (message < 2 * MAX_NUMBER_MESSAGES) { |
||||
final int replyMessage = message + 1; |
||||
ctx.writeAndFlush(Unpooled.copyInt(replyMessage)).sync(); |
||||
LOG.info("[" + id + "] Sent message: " + replyMessage); |
||||
this.latch.countDown(); |
||||
LOG.info("Remaining {}", this.latch.getCount()); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) |
||||
throws Exception { |
||||
this.cause = cause; |
||||
} |
||||
|
||||
public Optional<Throwable> getCause() { |
||||
return Optional.ofNullable(cause); |
||||
} |
||||
} |
||||
|
||||
static class Client { |
||||
int port; |
||||
private final String keystorePassword; |
||||
private final KeyStoreWrapper keyStoreWrapper; |
||||
private final CountDownLatch latch; |
||||
|
||||
private ChannelFuture channelFuture; |
||||
private final EventLoopGroup group = new NioEventLoopGroup(); |
||||
private MessageHandler messageHandler; |
||||
|
||||
ChannelFuture getChannelFuture() { |
||||
return channelFuture; |
||||
} |
||||
|
||||
Client( |
||||
final int port, |
||||
final String keystorePassword, |
||||
final KeyStoreWrapper keyStoreWrapper, |
||||
final CountDownLatch latch) { |
||||
this.port = port; |
||||
this.keystorePassword = keystorePassword; |
||||
this.keyStoreWrapper = keyStoreWrapper; |
||||
this.latch = latch; |
||||
} |
||||
|
||||
void start() throws Exception { |
||||
final Bootstrap b = new Bootstrap(); |
||||
b.group(group); |
||||
b.channel(NioSocketChannel.class); |
||||
b.handler( |
||||
new ChannelInitializer<SocketChannel>() { |
||||
@Override |
||||
protected void initChannel(final SocketChannel socketChannel) throws Exception { |
||||
final SslContext sslContext = |
||||
TLSContextFactory.getInstance(keystorePassword, keyStoreWrapper) |
||||
.createNettyClientSslContext(); |
||||
|
||||
final SslHandler sslHandler = sslContext.newHandler(socketChannel.alloc()); |
||||
socketChannel.pipeline().addFirst("ssl", sslHandler); |
||||
messageHandler = new MessageHandler("Client", latch); |
||||
socketChannel.pipeline().addLast(messageHandler); |
||||
} |
||||
}); |
||||
|
||||
this.channelFuture = b.connect("127.0.0.1", this.port).sync(); |
||||
} |
||||
|
||||
void stop() { |
||||
group.shutdownGracefully(); |
||||
messageHandler = null; |
||||
} |
||||
|
||||
Optional<Throwable> getCause() { |
||||
return messageHandler != null ? messageHandler.getCause() : Optional.empty(); |
||||
} |
||||
} |
||||
|
||||
static class Server { |
||||
private int port; |
||||
private final String keystorePassword; |
||||
private final KeyStoreWrapper keyStoreWrapper; |
||||
private final CountDownLatch latch; |
||||
|
||||
private Channel channel; |
||||
|
||||
private final EventLoopGroup parentGroup = new NioEventLoopGroup(); |
||||
private final EventLoopGroup childGroup = new NioEventLoopGroup(); |
||||
|
||||
private MessageHandler messageHandler; |
||||
|
||||
Server( |
||||
final String keystorePassword, |
||||
final KeyStoreWrapper keyStoreWrapper, |
||||
final CountDownLatch latch) { |
||||
this.keystorePassword = keystorePassword; |
||||
this.keyStoreWrapper = keyStoreWrapper; |
||||
this.latch = latch; |
||||
} |
||||
|
||||
void start() throws Exception { |
||||
final ServerBootstrap sb = new ServerBootstrap(); |
||||
sb.group(parentGroup, childGroup) |
||||
.channel(NioServerSocketChannel.class) |
||||
.childHandler( |
||||
new ChannelInitializer<SocketChannel>() { |
||||
@Override |
||||
public void initChannel(final SocketChannel socketChannel) throws Exception { |
||||
final SslContext sslContext = |
||||
TLSContextFactory.getInstance(keystorePassword, keyStoreWrapper) |
||||
.createNettyServerSslContext(); |
||||
final SslHandler sslHandler = sslContext.newHandler(channel.alloc()); |
||||
socketChannel.pipeline().addFirst("ssl", sslHandler); |
||||
|
||||
socketChannel |
||||
.pipeline() |
||||
.addLast(messageHandler = new MessageHandler("Server", latch)); |
||||
} |
||||
}); |
||||
|
||||
final ChannelFuture cf = sb.bind(0).sync(); |
||||
this.channel = cf.channel(); |
||||
this.port = ((InetSocketAddress) channel.localAddress()).getPort(); |
||||
} |
||||
|
||||
void stop() { |
||||
childGroup.shutdownGracefully(); |
||||
parentGroup.shutdownGracefully(); |
||||
} |
||||
|
||||
Optional<Throwable> getCause() { |
||||
return messageHandler != null ? messageHandler.getCause() : Optional.empty(); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
void dryRunDetector() { |
||||
assertThat(true) |
||||
.withFailMessage("This test is here so gradle --dry-run executes this class") |
||||
.isTrue(); |
||||
} |
||||
} |
@ -1,49 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
apply plugin: 'java-library' |
||||
|
||||
jar { |
||||
archiveBaseName = 'besu-pki' |
||||
manifest { |
||||
attributes( |
||||
'Specification-Title': archiveBaseName, |
||||
'Specification-Version': project.version, |
||||
'Implementation-Title': archiveBaseName, |
||||
'Implementation-Version': calculateVersion(), |
||||
'Commit-Hash': getGitCommitDetails(40).hash |
||||
) |
||||
} |
||||
} |
||||
|
||||
dependencies { |
||||
api 'org.slf4j:slf4j-api' |
||||
|
||||
implementation 'com.google.guava:guava' |
||||
implementation 'io.tmio:tuweni-bytes' |
||||
implementation 'org.bouncycastle:bcpkix-jdk18on' |
||||
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter' |
||||
testImplementation 'org.mockito:mockito-core' |
||||
testImplementation 'org.mockito:mockito-junit-jupiter' |
||||
} |
||||
|
||||
configurations { testArtifacts } |
||||
tasks.register('testJar', Jar) { |
||||
archiveBaseName = "${project.name}-test" |
||||
from sourceSets.test.output |
||||
} |
||||
|
||||
artifacts { testArtifacts testJar } |
@ -1,54 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.pki; |
||||
|
||||
/** The Pki exception. */ |
||||
public class PkiException extends RuntimeException { |
||||
|
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
/** Instantiates a new Pki exception. */ |
||||
public PkiException() { |
||||
super(); |
||||
} |
||||
|
||||
/** |
||||
* Instantiates a new Pki exception. |
||||
* |
||||
* @param message the message |
||||
*/ |
||||
public PkiException(final String message) { |
||||
super(message); |
||||
} |
||||
|
||||
/** |
||||
* Instantiates a new Pki exception. |
||||
* |
||||
* @param message the message |
||||
* @param t the Throwable cause |
||||
*/ |
||||
public PkiException(final String message, final Throwable t) { |
||||
super(message, t); |
||||
} |
||||
|
||||
/** |
||||
* Instantiates a new Pki exception. |
||||
* |
||||
* @param t the Throwable cause |
||||
*/ |
||||
public PkiException(final Throwable t) { |
||||
super(t); |
||||
} |
||||
} |
@ -1,142 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.pki.cms; |
||||
|
||||
import org.hyperledger.besu.pki.keystore.KeyStoreWrapper; |
||||
|
||||
import java.security.PrivateKey; |
||||
import java.security.PublicKey; |
||||
import java.security.Security; |
||||
import java.security.cert.X509Certificate; |
||||
import java.security.interfaces.ECPublicKey; |
||||
import java.security.spec.EllipticCurve; |
||||
import java.util.List; |
||||
import java.util.stream.Collectors; |
||||
import java.util.stream.Stream; |
||||
|
||||
import com.google.common.annotations.VisibleForTesting; |
||||
import org.apache.tuweni.bytes.Bytes; |
||||
import org.bouncycastle.cert.jcajce.JcaCertStore; |
||||
import org.bouncycastle.cms.CMSProcessableByteArray; |
||||
import org.bouncycastle.cms.CMSSignedData; |
||||
import org.bouncycastle.cms.CMSSignedDataGenerator; |
||||
import org.bouncycastle.cms.CMSTypedData; |
||||
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; |
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider; |
||||
import org.bouncycastle.operator.ContentSigner; |
||||
import org.bouncycastle.operator.DigestCalculatorProvider; |
||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; |
||||
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; |
||||
import org.bouncycastle.util.Store; |
||||
|
||||
/** The Cms creator. */ |
||||
public class CmsCreator { |
||||
|
||||
static { |
||||
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { |
||||
Security.addProvider(new BouncyCastleProvider()); |
||||
} |
||||
} |
||||
|
||||
private final String certificateAlias; |
||||
private final KeyStoreWrapper keyStore; |
||||
|
||||
/** |
||||
* Instantiates a new Cms creator. |
||||
* |
||||
* @param keyStore the key store |
||||
* @param certificateAlias the certificate alias |
||||
*/ |
||||
public CmsCreator(final KeyStoreWrapper keyStore, final String certificateAlias) { |
||||
this.keyStore = keyStore; |
||||
this.certificateAlias = certificateAlias; |
||||
} |
||||
|
||||
/** |
||||
* Creates a CMS message with the content parameter, signed with the certificate with alias |
||||
* defined in the {@code CmsCreator} constructor. The certificate chain is also included so the |
||||
* recipient has the information needed to build a trusted certificate path when validating this |
||||
* message. |
||||
* |
||||
* @param contentToSign the content that will be signed and added to the message |
||||
* @return the CMS message bytes |
||||
*/ |
||||
@SuppressWarnings("rawtypes") |
||||
public Bytes create(final Bytes contentToSign) { |
||||
try { |
||||
// Certificates that will be sent
|
||||
final List<X509Certificate> x509Certificates = |
||||
Stream.of(keyStore.getCertificateChain(certificateAlias)) |
||||
.map(X509Certificate.class::cast) |
||||
.collect(Collectors.toList()); |
||||
final Store certs = new JcaCertStore(x509Certificates); |
||||
|
||||
// Private key of the certificate that will sign the message
|
||||
final PrivateKey privateKey = keyStore.getPrivateKey(certificateAlias); |
||||
|
||||
final ContentSigner contentSigner = |
||||
new JcaContentSignerBuilder( |
||||
getPreferredSignatureAlgorithm(keyStore.getPublicKey(certificateAlias))) |
||||
.build(privateKey); |
||||
|
||||
final CMSSignedDataGenerator cmsGenerator = new CMSSignedDataGenerator(); |
||||
|
||||
// Additional intermediate certificates for path building
|
||||
cmsGenerator.addCertificates(certs); |
||||
|
||||
final DigestCalculatorProvider digestCalculatorProvider = |
||||
new JcaDigestCalculatorProviderBuilder().setProvider("BC").build(); |
||||
// The first certificate in the list (leaf certificate is the signer)
|
||||
cmsGenerator.addSignerInfoGenerator( |
||||
new JcaSignerInfoGeneratorBuilder(digestCalculatorProvider) |
||||
.build(contentSigner, x509Certificates.get(0))); |
||||
|
||||
// Add signed content
|
||||
final CMSTypedData cmsData = new CMSProcessableByteArray(contentToSign.toArray()); |
||||
final CMSSignedData cmsSignedData = cmsGenerator.generate(cmsData, false); |
||||
|
||||
return Bytes.wrap(cmsSignedData.getEncoded()); |
||||
} catch (final Exception e) { |
||||
throw new RuntimeException("Error creating CMS data", e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Gets preferred signature algorithm for EC or RSA keys |
||||
* |
||||
* @param pub the public key |
||||
* @return the preferred signature algorithm |
||||
*/ |
||||
@VisibleForTesting |
||||
public static String getPreferredSignatureAlgorithm(final PublicKey pub) { |
||||
switch (pub.getAlgorithm()) { |
||||
case "EC" -> { |
||||
final EllipticCurve curve = ((ECPublicKey) pub).getParams().getCurve(); |
||||
return switch (curve.getField().getFieldSize()) { |
||||
case 224, 256 -> "SHA256withECDSA"; |
||||
case 384 -> "SHA384withECDSA"; |
||||
case 521 -> "SHA512withECDSA"; |
||||
default -> throw new IllegalArgumentException("Elliptic curve not supported: " + curve); |
||||
}; |
||||
} |
||||
case "RSA" -> { |
||||
return "SHA256WithRSAEncryption"; |
||||
} |
||||
default -> |
||||
throw new UnsupportedOperationException( |
||||
"Private key algorithm not supported: " + pub.getAlgorithm()); |
||||
} |
||||
} |
||||
} |
@ -1,203 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.pki.cms; |
||||
|
||||
import org.hyperledger.besu.pki.keystore.KeyStoreWrapper; |
||||
|
||||
import java.security.Security; |
||||
import java.security.cert.CertPathBuilder; |
||||
import java.security.cert.CertPathBuilderException; |
||||
import java.security.cert.CertStore; |
||||
import java.security.cert.CollectionCertStoreParameters; |
||||
import java.security.cert.PKIXBuilderParameters; |
||||
import java.security.cert.PKIXRevocationChecker; |
||||
import java.security.cert.PKIXRevocationChecker.Option; |
||||
import java.security.cert.X509CertSelector; |
||||
import java.security.cert.X509Certificate; |
||||
import java.util.Collection; |
||||
import java.util.EnumSet; |
||||
import java.util.Optional; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes; |
||||
import org.bouncycastle.cert.X509CertificateHolder; |
||||
import org.bouncycastle.cert.jcajce.JcaCertStoreBuilder; |
||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; |
||||
import org.bouncycastle.cms.CMSException; |
||||
import org.bouncycastle.cms.CMSProcessableByteArray; |
||||
import org.bouncycastle.cms.CMSSignedData; |
||||
import org.bouncycastle.cms.SignerInformation; |
||||
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; |
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider; |
||||
import org.bouncycastle.util.Store; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** The Cms validator. */ |
||||
public class CmsValidator { |
||||
|
||||
static { |
||||
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { |
||||
Security.addProvider(new BouncyCastleProvider()); |
||||
} |
||||
} |
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CmsValidator.class); |
||||
|
||||
private final KeyStoreWrapper truststore; |
||||
|
||||
/** |
||||
* Instantiates a new Cms validator. |
||||
* |
||||
* @param truststore the truststore |
||||
*/ |
||||
public CmsValidator(final KeyStoreWrapper truststore) { |
||||
this.truststore = truststore; |
||||
} |
||||
|
||||
/** |
||||
* Verifies that a CMS message signed content matched the expected content, and that the message |
||||
* signer is from a certificate that is trusted (has permission to propose a block) |
||||
* |
||||
* @param cms the CMS message bytes |
||||
* @param expectedContent the expected signed content in the CMS message |
||||
* @return true, if the signed content matched the expected content and the signer's certificate |
||||
* is trusted, otherwise returns false. |
||||
*/ |
||||
public boolean validate(final Bytes cms, final Bytes expectedContent) { |
||||
if (cms == null || cms.isEmpty()) { |
||||
return false; |
||||
} |
||||
|
||||
try { |
||||
LOGGER.trace("Validating CMS message"); |
||||
|
||||
final CMSSignedData cmsSignedData = |
||||
new CMSSignedData(new CMSProcessableByteArray(expectedContent.toArray()), cms.toArray()); |
||||
final X509Certificate signerCertificate = getSignerCertificate(cmsSignedData); |
||||
|
||||
// Validate msg signature and content
|
||||
if (!isSignatureValid(signerCertificate, cmsSignedData)) { |
||||
return false; |
||||
} |
||||
|
||||
// Validate certificate trust
|
||||
if (!isCertificateTrusted(signerCertificate, cmsSignedData)) { |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} catch (final Exception e) { |
||||
throw new RuntimeException("Error validating CMS data", e); |
||||
} |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
private X509Certificate getSignerCertificate(final CMSSignedData cmsSignedData) { |
||||
try { |
||||
final Store<X509CertificateHolder> certificateStore = cmsSignedData.getCertificates(); |
||||
|
||||
// We don't expect more than one signer on the CMS data
|
||||
if (cmsSignedData.getSignerInfos().size() != 1) { |
||||
throw new RuntimeException("Only one signer is expected on the CMS message"); |
||||
} |
||||
final SignerInformation signerInformation = |
||||
cmsSignedData.getSignerInfos().getSigners().stream().findFirst().get(); |
||||
|
||||
// Find signer's certificate from CMS data
|
||||
final Collection<X509CertificateHolder> signerCertificates = |
||||
certificateStore.getMatches(signerInformation.getSID()); |
||||
final X509CertificateHolder certificateHolder = signerCertificates.stream().findFirst().get(); |
||||
|
||||
return new JcaX509CertificateConverter().getCertificate(certificateHolder); |
||||
} catch (final Exception e) { |
||||
throw new RuntimeException("Error retrieving signer certificate from CMS data", e); |
||||
} |
||||
} |
||||
|
||||
private boolean isSignatureValid( |
||||
final X509Certificate signerCertificate, final CMSSignedData cmsSignedData) { |
||||
LOGGER.trace("Validating CMS signature"); |
||||
try { |
||||
return cmsSignedData.verifySignatures( |
||||
sid -> new JcaSimpleSignerInfoVerifierBuilder().build(signerCertificate)); |
||||
} catch (final CMSException e) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
private boolean isCertificateTrusted( |
||||
final X509Certificate signerCertificate, final CMSSignedData cmsSignedData) { |
||||
LOGGER.trace("Starting CMS certificate validation"); |
||||
|
||||
try { |
||||
final CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX"); |
||||
|
||||
// Define CMS signer certificate as the starting point of the path (leaf certificate)
|
||||
final X509CertSelector targetConstraints = new X509CertSelector(); |
||||
targetConstraints.setCertificate(signerCertificate); |
||||
|
||||
// Set parameters for the certificate path building algorithm
|
||||
final PKIXBuilderParameters params = |
||||
new PKIXBuilderParameters(truststore.getKeyStore(), targetConstraints); |
||||
|
||||
// Adding CertStore with CRLs (if present, otherwise disabling revocation check)
|
||||
createCRLCertStore(truststore) |
||||
.ifPresentOrElse( |
||||
CRLs -> { |
||||
params.addCertStore(CRLs); |
||||
PKIXRevocationChecker rc = (PKIXRevocationChecker) cpb.getRevocationChecker(); |
||||
rc.setOptions(EnumSet.of(Option.PREFER_CRLS)); |
||||
params.addCertPathChecker(rc); |
||||
}, |
||||
() -> { |
||||
LOGGER.warn("No CRL CertStore provided. CRL validation will be disabled."); |
||||
params.setRevocationEnabled(false); |
||||
}); |
||||
|
||||
// Read certificates sent on the CMS message and adding it to the path building algorithm
|
||||
final CertStore cmsCertificates = |
||||
new JcaCertStoreBuilder().addCertificates(cmsSignedData.getCertificates()).build(); |
||||
params.addCertStore(cmsCertificates); |
||||
|
||||
// Validate certificate path
|
||||
try { |
||||
cpb.build(params); |
||||
return true; |
||||
} catch (final CertPathBuilderException cpbe) { |
||||
LOGGER.warn("Untrusted certificate chain", cpbe); |
||||
LOGGER.trace("Reason for failed validation", cpbe.getCause()); |
||||
return false; |
||||
} |
||||
|
||||
} catch (final Exception e) { |
||||
LOGGER.error("Error validating certificate chain"); |
||||
throw new RuntimeException("Error validating certificate chain", e); |
||||
} |
||||
} |
||||
|
||||
private Optional<CertStore> createCRLCertStore(final KeyStoreWrapper truststore) { |
||||
if (truststore.getCRLs() != null) { |
||||
try { |
||||
return Optional.of( |
||||
CertStore.getInstance( |
||||
"Collection", new CollectionCertStoreParameters(truststore.getCRLs()))); |
||||
} catch (final Exception e) { |
||||
throw new RuntimeException("Error loading CRLs from Truststore", e); |
||||
} |
||||
} else { |
||||
return Optional.empty(); |
||||
} |
||||
} |
||||
} |
@ -1,303 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.pki.config; |
||||
|
||||
import static java.util.Objects.requireNonNull; |
||||
|
||||
import java.io.IOException; |
||||
import java.nio.file.Files; |
||||
import java.nio.file.Path; |
||||
import java.util.Optional; |
||||
import java.util.stream.Stream; |
||||
|
||||
import com.google.common.annotations.VisibleForTesting; |
||||
|
||||
/** The Pki key store configuration. */ |
||||
public class PkiKeyStoreConfiguration { |
||||
|
||||
/** The constant DEFAULT_KEYSTORE_TYPE. */ |
||||
public static String DEFAULT_KEYSTORE_TYPE = "PKCS12"; |
||||
|
||||
/** The constant DEFAULT_CERTIFICATE_ALIAS. */ |
||||
public static String DEFAULT_CERTIFICATE_ALIAS = "validator"; |
||||
|
||||
private final String keyStoreType; |
||||
private final Path keyStorePath; |
||||
private final Path keyStorePasswordPath; |
||||
private final String certificateAlias; |
||||
private final String trustStoreType; |
||||
private final Path trustStorePath; |
||||
private final Path trustStorePasswordPath; |
||||
private final Optional<Path> crlFilePath; |
||||
|
||||
/** |
||||
* Instantiates a new Pki key store configuration. |
||||
* |
||||
* @param keyStoreType the key store type |
||||
* @param keyStorePath the key store path |
||||
* @param keyStorePasswordPath the key store password path |
||||
* @param certificateAlias the certificate alias |
||||
* @param trustStoreType the trust store type |
||||
* @param trustStorePath the trust store path |
||||
* @param trustStorePasswordPath the trust store password path |
||||
* @param crlFilePath the crl file path |
||||
*/ |
||||
public PkiKeyStoreConfiguration( |
||||
final String keyStoreType, |
||||
final Path keyStorePath, |
||||
final Path keyStorePasswordPath, |
||||
final String certificateAlias, |
||||
final String trustStoreType, |
||||
final Path trustStorePath, |
||||
final Path trustStorePasswordPath, |
||||
final Optional<Path> crlFilePath) { |
||||
this.keyStoreType = keyStoreType; |
||||
this.keyStorePath = keyStorePath; |
||||
this.keyStorePasswordPath = keyStorePasswordPath; |
||||
this.certificateAlias = certificateAlias; |
||||
this.trustStoreType = trustStoreType; |
||||
this.trustStorePath = trustStorePath; |
||||
this.trustStorePasswordPath = trustStorePasswordPath; |
||||
this.crlFilePath = crlFilePath; |
||||
} |
||||
|
||||
/** |
||||
* Gets key store type. |
||||
* |
||||
* @return the key store type |
||||
*/ |
||||
public String getKeyStoreType() { |
||||
return keyStoreType; |
||||
} |
||||
|
||||
/** |
||||
* Gets key store path. |
||||
* |
||||
* @return the key store path |
||||
*/ |
||||
public Path getKeyStorePath() { |
||||
return keyStorePath; |
||||
} |
||||
|
||||
/** |
||||
* Gets key store password path. |
||||
* |
||||
* @return the key store password path |
||||
*/ |
||||
@VisibleForTesting |
||||
public Path getKeyStorePasswordPath() { |
||||
return keyStorePasswordPath; |
||||
} |
||||
|
||||
/** |
||||
* Gets key store password. |
||||
* |
||||
* @return the key store password |
||||
*/ |
||||
public String getKeyStorePassword() { |
||||
return readPasswordFromFile(keyStorePasswordPath); |
||||
} |
||||
|
||||
/** |
||||
* Gets certificate alias. |
||||
* |
||||
* @return the certificate alias |
||||
*/ |
||||
public String getCertificateAlias() { |
||||
return certificateAlias; |
||||
} |
||||
|
||||
/** |
||||
* Gets trust store type. |
||||
* |
||||
* @return the trust store type |
||||
*/ |
||||
public String getTrustStoreType() { |
||||
return trustStoreType; |
||||
} |
||||
|
||||
/** |
||||
* Gets trust store path. |
||||
* |
||||
* @return the trust store path |
||||
*/ |
||||
public Path getTrustStorePath() { |
||||
return trustStorePath; |
||||
} |
||||
|
||||
/** |
||||
* Gets trust store password path. |
||||
* |
||||
* @return the trust store password path |
||||
*/ |
||||
@VisibleForTesting |
||||
public Path getTrustStorePasswordPath() { |
||||
return trustStorePasswordPath; |
||||
} |
||||
|
||||
/** |
||||
* Gets trust store password. |
||||
* |
||||
* @return the trust store password |
||||
*/ |
||||
public String getTrustStorePassword() { |
||||
return readPasswordFromFile(trustStorePasswordPath); |
||||
} |
||||
|
||||
/** |
||||
* Gets CRL file path. |
||||
* |
||||
* @return the crl file path |
||||
*/ |
||||
public Optional<Path> getCrlFilePath() { |
||||
return crlFilePath; |
||||
} |
||||
|
||||
/** The Builder. */ |
||||
public static final class Builder { |
||||
|
||||
private String keyStoreType = DEFAULT_KEYSTORE_TYPE; |
||||
private Path keyStorePath; |
||||
private Path keyStorePasswordPath; |
||||
private String certificateAlias = DEFAULT_CERTIFICATE_ALIAS; |
||||
private String trustStoreType = DEFAULT_KEYSTORE_TYPE; |
||||
private Path trustStorePath; |
||||
private Path trustStorePasswordPath; |
||||
private Path crlFilePath; |
||||
|
||||
/** Instantiates a new Builder. */ |
||||
public Builder() {} |
||||
|
||||
/** |
||||
* With key store type. |
||||
* |
||||
* @param keyStoreType the key store type |
||||
* @return the builder |
||||
*/ |
||||
public Builder withKeyStoreType(final String keyStoreType) { |
||||
this.keyStoreType = keyStoreType; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* With key store path. |
||||
* |
||||
* @param keyStorePath the key store path |
||||
* @return the builder |
||||
*/ |
||||
public Builder withKeyStorePath(final Path keyStorePath) { |
||||
this.keyStorePath = keyStorePath; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* With key store password path. |
||||
* |
||||
* @param keyStorePasswordPath the key store password path |
||||
* @return the builder |
||||
*/ |
||||
public Builder withKeyStorePasswordPath(final Path keyStorePasswordPath) { |
||||
this.keyStorePasswordPath = keyStorePasswordPath; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* With certificate alias. |
||||
* |
||||
* @param certificateAlias the certificate alias |
||||
* @return the builder |
||||
*/ |
||||
public Builder withCertificateAlias(final String certificateAlias) { |
||||
this.certificateAlias = certificateAlias; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* With trust store type. |
||||
* |
||||
* @param trustStoreType the trust store type |
||||
* @return the builder |
||||
*/ |
||||
public Builder withTrustStoreType(final String trustStoreType) { |
||||
this.trustStoreType = trustStoreType; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* With trust store path. |
||||
* |
||||
* @param trustStorePath the trust store path |
||||
* @return the builder |
||||
*/ |
||||
public Builder withTrustStorePath(final Path trustStorePath) { |
||||
this.trustStorePath = trustStorePath; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* With trust store password path. |
||||
* |
||||
* @param trustStorePasswordPath the trust store password path |
||||
* @return the builder |
||||
*/ |
||||
public Builder withTrustStorePasswordPath(final Path trustStorePasswordPath) { |
||||
this.trustStorePasswordPath = trustStorePasswordPath; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* With crl file path. |
||||
* |
||||
* @param filePath the file path |
||||
* @return the builder |
||||
*/ |
||||
public Builder withCrlFilePath(final Path filePath) { |
||||
this.crlFilePath = filePath; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Build pki key store configuration. |
||||
* |
||||
* @return the pki key store configuration |
||||
*/ |
||||
public PkiKeyStoreConfiguration build() { |
||||
requireNonNull(keyStoreType, "Key Store Type must not be null"); |
||||
requireNonNull(keyStorePasswordPath, "Key Store password file must not be null"); |
||||
|
||||
return new PkiKeyStoreConfiguration( |
||||
keyStoreType, |
||||
keyStorePath, |
||||
keyStorePasswordPath, |
||||
certificateAlias, |
||||
trustStoreType, |
||||
trustStorePath, |
||||
trustStorePasswordPath, |
||||
Optional.ofNullable(crlFilePath)); |
||||
} |
||||
} |
||||
|
||||
private String readPasswordFromFile(final Path passwordFile) { |
||||
try (final Stream<String> fileStream = Files.lines(passwordFile)) { |
||||
return fileStream.findFirst().orElseThrow(() -> errorReadingFileException(passwordFile)); |
||||
} catch (final IOException e) { |
||||
throw errorReadingFileException(passwordFile); |
||||
} |
||||
} |
||||
|
||||
private RuntimeException errorReadingFileException(final Path path) { |
||||
return new RuntimeException(String.format("Unable to read keystore password from %s", path)); |
||||
} |
||||
} |
@ -1,53 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.pki.crl; |
||||
|
||||
import org.hyperledger.besu.pki.PkiException; |
||||
|
||||
import java.io.FileInputStream; |
||||
import java.nio.file.Paths; |
||||
import java.security.cert.CertStore; |
||||
import java.security.cert.CertificateFactory; |
||||
import java.security.cert.CollectionCertStoreParameters; |
||||
import java.security.cert.X509CRL; |
||||
import java.util.List; |
||||
import java.util.stream.Collectors; |
||||
|
||||
/** The CRL util. */ |
||||
public class CRLUtil { |
||||
/** Default constructor */ |
||||
private CRLUtil() {} |
||||
|
||||
/** |
||||
* Load CRLs cert store. |
||||
* |
||||
* @param path the path |
||||
* @return the cert store |
||||
*/ |
||||
public static CertStore loadCRLs(final String path) { |
||||
try { |
||||
final List<X509CRL> crls = |
||||
CertificateFactory.getInstance("X509") |
||||
.generateCRLs(new FileInputStream(Paths.get(path).toFile())) |
||||
.stream() |
||||
.map(X509CRL.class::cast) |
||||
.collect(Collectors.toList()); |
||||
|
||||
return CertStore.getInstance("Collection", new CollectionCertStoreParameters(crls)); |
||||
} catch (Exception e) { |
||||
throw new PkiException("Error loading CRL file " + path, e); |
||||
} |
||||
} |
||||
} |
@ -1,68 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.pki.keystore; |
||||
|
||||
import org.hyperledger.besu.pki.PkiException; |
||||
|
||||
import java.io.FileInputStream; |
||||
import java.io.InputStream; |
||||
import java.nio.file.Path; |
||||
import java.security.cert.CertificateFactory; |
||||
import java.security.cert.X509CRL; |
||||
import java.util.Collection; |
||||
import java.util.stream.Collectors; |
||||
|
||||
/** The Abstract key store wrapper. */ |
||||
public abstract class AbstractKeyStoreWrapper implements KeyStoreWrapper { |
||||
|
||||
private static final String X_509 = "X.509"; |
||||
|
||||
private final Collection<X509CRL> crls; |
||||
|
||||
/** |
||||
* Instantiates a new Abstract key store wrapper. |
||||
* |
||||
* @param crlLocation the crl location |
||||
*/ |
||||
protected AbstractKeyStoreWrapper(final Path crlLocation) { |
||||
super(); |
||||
if (null == crlLocation) { |
||||
this.crls = null; |
||||
} else { |
||||
try (InputStream stream = new FileInputStream(crlLocation.toFile())) { |
||||
this.crls = |
||||
CertificateFactory.getInstance(X_509).generateCRLs(stream).stream() |
||||
.map(X509CRL.class::cast) |
||||
.collect(Collectors.toList()); |
||||
} catch (final Exception e) { |
||||
throw new PkiException("Failed to initialize software truststore", e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Instantiates a new Abstract key store wrapper. |
||||
* |
||||
* @param crls the collection of X509CRL instances |
||||
*/ |
||||
protected AbstractKeyStoreWrapper(final Collection<X509CRL> crls) { |
||||
this.crls = crls; |
||||
} |
||||
|
||||
@Override |
||||
public Collection<X509CRL> getCRLs() { |
||||
return crls; |
||||
} |
||||
} |
@ -1,210 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.pki.keystore; |
||||
|
||||
import org.hyperledger.besu.pki.PkiException; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileInputStream; |
||||
import java.io.InputStream; |
||||
import java.nio.file.Path; |
||||
import java.security.KeyStore; |
||||
import java.security.PrivateKey; |
||||
import java.security.Provider; |
||||
import java.security.PublicKey; |
||||
import java.security.Security; |
||||
import java.security.cert.Certificate; |
||||
import java.security.cert.X509CRL; |
||||
import java.util.Collection; |
||||
import java.util.Optional; |
||||
import java.util.Properties; |
||||
import java.util.stream.Stream; |
||||
|
||||
import com.google.common.annotations.VisibleForTesting; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* Creates an instance of this class which is backed by a PKCS#11 keystore, such as a software |
||||
* (emulated) HSM or a physical/cloud HSM (see <a href= |
||||
* "https://docs.oracle.com/en/java/javase/11/security/pkcs11-reference-guide1.html">here</a> |
||||
*/ |
||||
public class HardwareKeyStoreWrapper extends AbstractKeyStoreWrapper { |
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(HardwareKeyStoreWrapper.class); |
||||
|
||||
private static final String pkcs11Provider = "SunPKCS11"; |
||||
|
||||
private final KeyStore keystore; |
||||
private final transient char[] keystorePassword; |
||||
|
||||
private final java.security.Provider provider; |
||||
|
||||
/** |
||||
* Instantiates a new Hardware key store wrapper. |
||||
* |
||||
* @param keystorePassword the keystore password |
||||
* @param provider the provider |
||||
* @param crlLocation the crl location |
||||
*/ |
||||
public HardwareKeyStoreWrapper( |
||||
final String keystorePassword, final Provider provider, final Path crlLocation) { |
||||
super(crlLocation); |
||||
try { |
||||
if (provider == null) { |
||||
throw new IllegalArgumentException("Provider is null"); |
||||
} |
||||
this.keystorePassword = keystorePassword.toCharArray(); |
||||
|
||||
this.provider = provider; |
||||
if (Security.getProvider(provider.getName()) == null) { |
||||
Security.addProvider(provider); |
||||
} |
||||
|
||||
keystore = KeyStore.getInstance(KeyStoreWrapper.KEYSTORE_TYPE_PKCS11, provider); |
||||
keystore.load(null, this.keystorePassword); |
||||
|
||||
} catch (final Exception e) { |
||||
throw new PkiException("Failed to initialize HSM keystore", e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Instantiates a new Hardware key store wrapper. |
||||
* |
||||
* @param keystorePassword the keystore password |
||||
* @param config the config |
||||
* @param crlLocation the CRL location |
||||
*/ |
||||
public HardwareKeyStoreWrapper( |
||||
final String keystorePassword, final Path config, final Path crlLocation) { |
||||
super(crlLocation); |
||||
try { |
||||
if (keystorePassword == null) { |
||||
throw new IllegalArgumentException("Keystore password is null"); |
||||
} |
||||
final Properties properties = new Properties(); |
||||
final File configFile = config.toFile(); |
||||
try (InputStream ins = new FileInputStream(configFile)) { |
||||
properties.load(ins); |
||||
} |
||||
final String name = properties.getProperty("name"); |
||||
this.keystorePassword = keystorePassword.toCharArray(); |
||||
final Optional<Provider> existingProvider = |
||||
Stream.of(Security.getProviders()) |
||||
.filter(p -> p.getName().equals(String.format("%s-%s", pkcs11Provider, name))) |
||||
.findAny(); |
||||
if (existingProvider.isPresent()) { |
||||
provider = existingProvider.get(); |
||||
} else { |
||||
provider = getPkcs11Provider(configFile.getAbsolutePath()); |
||||
Security.addProvider(provider); |
||||
} |
||||
|
||||
keystore = KeyStore.getInstance(KeyStoreWrapper.KEYSTORE_TYPE_PKCS11, provider); |
||||
keystore.load(null, this.keystorePassword); |
||||
|
||||
} catch (final Exception e) { |
||||
throw new PkiException("Failed to initialize HSM keystore", e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Instantiates a new Hardware key store wrapper. |
||||
* |
||||
* @param crls the collection of X509CRL crls |
||||
* @param keystore the keystore |
||||
* @param password the password |
||||
*/ |
||||
@VisibleForTesting |
||||
HardwareKeyStoreWrapper( |
||||
final Collection<X509CRL> crls, final KeyStore keystore, final String password) { |
||||
super(crls); |
||||
this.keystore = keystore; |
||||
this.keystorePassword = password.toCharArray(); |
||||
this.provider = null; |
||||
} |
||||
|
||||
@Override |
||||
public PrivateKey getPrivateKey(final String keyAlias) { |
||||
try { |
||||
LOG.debug("Retrieving private key for alias: {}", keyAlias); |
||||
return (PrivateKey) keystore.getKey(keyAlias, this.keystorePassword); |
||||
} catch (final Exception e) { |
||||
throw new PkiException("Failed to get key: " + keyAlias, e); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public PublicKey getPublicKey(final String keyAlias) { |
||||
try { |
||||
LOG.debug("Retrieving public key for alias: {}", keyAlias); |
||||
final Certificate certificate = keystore.getCertificate(keyAlias); |
||||
return (certificate != null) ? certificate.getPublicKey() : null; |
||||
} catch (final Exception e) { |
||||
throw new PkiException("Failed to get key: " + keyAlias, e); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Certificate getCertificate(final String certificateAlias) { |
||||
try { |
||||
LOG.debug("Retrieving certificate for alias: {}", certificateAlias); |
||||
return keystore.getCertificate(certificateAlias); |
||||
} catch (final Exception e) { |
||||
throw new PkiException("Failed to get certificate: " + certificateAlias, e); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Certificate[] getCertificateChain(final String certificateAlias) { |
||||
try { |
||||
LOG.debug("Retrieving certificate chain for alias: {}", certificateAlias); |
||||
return keystore.getCertificateChain(certificateAlias); |
||||
} catch (final Exception e) { |
||||
throw new PkiException("Failed to certificate chain for alias: " + certificateAlias, e); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public KeyStore getKeyStore() { |
||||
return keystore; |
||||
} |
||||
|
||||
@Override |
||||
public KeyStore getTrustStore() { |
||||
return keystore; |
||||
} |
||||
|
||||
private Provider getPkcs11Provider(final String config) { |
||||
final Provider provider = Security.getProvider(pkcs11Provider); |
||||
if (null == provider) { |
||||
throw new IllegalArgumentException("Unable to load PKCS11 provider configuration."); |
||||
} else { |
||||
return provider.configure(config); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Gets PKCS11 provider. |
||||
* |
||||
* @param config the config |
||||
* @return the PKCS11 provider |
||||
*/ |
||||
@VisibleForTesting |
||||
public Provider getPkcs11ProviderForConfig(final String config) { |
||||
return getPkcs11Provider(config); |
||||
} |
||||
} |
@ -1,88 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.pki.keystore; |
||||
|
||||
import java.security.KeyStore; |
||||
import java.security.PrivateKey; |
||||
import java.security.PublicKey; |
||||
import java.security.cert.Certificate; |
||||
import java.security.cert.X509CRL; |
||||
import java.util.Collection; |
||||
|
||||
/** The interface Key store wrapper. */ |
||||
public interface KeyStoreWrapper { |
||||
|
||||
/** The constant KEYSTORE_TYPE_JKS. */ |
||||
String KEYSTORE_TYPE_JKS = "JKS"; |
||||
|
||||
/** The constant KEYSTORE_TYPE_PKCS11. */ |
||||
String KEYSTORE_TYPE_PKCS11 = "PKCS11"; |
||||
|
||||
/** The constant KEYSTORE_TYPE_PKCS12. */ |
||||
String KEYSTORE_TYPE_PKCS12 = "PKCS12"; |
||||
|
||||
/** |
||||
* Gets key store. |
||||
* |
||||
* @return the key store |
||||
*/ |
||||
KeyStore getKeyStore(); |
||||
|
||||
/** |
||||
* Gets trust store. |
||||
* |
||||
* @return the trust store |
||||
*/ |
||||
KeyStore getTrustStore(); |
||||
|
||||
/** |
||||
* Gets private key. |
||||
* |
||||
* @param keyAlias the key alias |
||||
* @return the private key |
||||
*/ |
||||
PrivateKey getPrivateKey(String keyAlias); |
||||
|
||||
/** |
||||
* Gets public key. |
||||
* |
||||
* @param keyAlias the key alias |
||||
* @return the public key |
||||
*/ |
||||
PublicKey getPublicKey(String keyAlias); |
||||
|
||||
/** |
||||
* Gets certificate. |
||||
* |
||||
* @param certificateAlias the certificate alias |
||||
* @return the certificate |
||||
*/ |
||||
Certificate getCertificate(String certificateAlias); |
||||
|
||||
/** |
||||
* Get certificate chain array. |
||||
* |
||||
* @param certificateAlias the certificate alias |
||||
* @return the certificate [ ] |
||||
*/ |
||||
Certificate[] getCertificateChain(String certificateAlias); |
||||
|
||||
/** |
||||
* Gets CRLs. |
||||
* |
||||
* @return the CRLs |
||||
*/ |
||||
Collection<X509CRL> getCRLs(); |
||||
} |
@ -1,269 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.pki.keystore; |
||||
|
||||
import org.hyperledger.besu.pki.PkiException; |
||||
|
||||
import java.io.FileInputStream; |
||||
import java.io.InputStream; |
||||
import java.nio.file.Path; |
||||
import java.security.GeneralSecurityException; |
||||
import java.security.Key; |
||||
import java.security.KeyStore; |
||||
import java.security.PrivateKey; |
||||
import java.security.PublicKey; |
||||
import java.security.cert.Certificate; |
||||
import java.security.cert.X509CRL; |
||||
import java.util.Collection; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
import com.google.common.annotations.VisibleForTesting; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** The Software key store wrapper. */ |
||||
public class SoftwareKeyStoreWrapper extends AbstractKeyStoreWrapper { |
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SoftwareKeyStoreWrapper.class); |
||||
|
||||
private final KeyStore keystore; |
||||
private final transient char[] keystorePassword; |
||||
private KeyStore truststore; |
||||
private transient char[] truststorePassword; |
||||
|
||||
private final Map<String, PrivateKey> cachedPrivateKeys = new HashMap<>(); |
||||
private final Map<String, PublicKey> cachedPublicKeys = new HashMap<>(); |
||||
private final Map<String, Certificate> cachedCertificates = new HashMap<>(); |
||||
|
||||
/** |
||||
* Instantiates a new Software key store wrapper. |
||||
* |
||||
* @param keystoreType the keystore type |
||||
* @param keystoreLocation the keystore location |
||||
* @param keystorePassword the keystore password |
||||
* @param crlLocation the crl location |
||||
*/ |
||||
public SoftwareKeyStoreWrapper( |
||||
final String keystoreType, |
||||
final Path keystoreLocation, |
||||
final String keystorePassword, |
||||
final Path crlLocation) { |
||||
this(keystoreType, keystoreLocation, keystorePassword, null, null, null, crlLocation); |
||||
} |
||||
|
||||
/** |
||||
* Instantiates a new Software key store wrapper. |
||||
* |
||||
* @param keystoreType the keystore type |
||||
* @param keystoreLocation the keystore location |
||||
* @param keystorePassword the keystore password |
||||
* @param truststoreType the truststore type |
||||
* @param truststoreLocation the truststore location |
||||
* @param truststorePassword the truststore password |
||||
* @param crlLocation the crl location |
||||
*/ |
||||
public SoftwareKeyStoreWrapper( |
||||
final String keystoreType, |
||||
final Path keystoreLocation, |
||||
final String keystorePassword, |
||||
final String truststoreType, |
||||
final Path truststoreLocation, |
||||
final String truststorePassword, |
||||
final Path crlLocation) { |
||||
super(crlLocation); |
||||
|
||||
if (keystorePassword == null) { |
||||
throw new IllegalArgumentException("Keystore password is null"); |
||||
} |
||||
this.keystorePassword = keystorePassword.toCharArray(); |
||||
try (InputStream stream = new FileInputStream(keystoreLocation.toFile())) { |
||||
keystore = KeyStore.getInstance(keystoreType); |
||||
keystore.load(stream, this.keystorePassword); |
||||
|
||||
} catch (final Exception e) { |
||||
throw new PkiException("Failed to initialize software keystore: " + keystoreLocation, e); |
||||
} |
||||
|
||||
if (truststoreType != null && truststoreLocation != null) { |
||||
this.truststorePassword = |
||||
(truststorePassword != null) ? truststorePassword.toCharArray() : null; |
||||
try (InputStream stream = new FileInputStream(truststoreLocation.toFile())) { |
||||
truststore = KeyStore.getInstance(truststoreType); |
||||
truststore.load(stream, this.truststorePassword); |
||||
|
||||
} catch (final Exception e) { |
||||
throw new PkiException( |
||||
"Failed to initialize software truststore: " + truststoreLocation, e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Instantiates a new Software key store wrapper. |
||||
* |
||||
* @param keystore the keystore |
||||
* @param keystorePassword the keystore password |
||||
* @param truststore the truststore |
||||
* @param truststorePassword the truststore password |
||||
*/ |
||||
@VisibleForTesting |
||||
public SoftwareKeyStoreWrapper( |
||||
final KeyStore keystore, |
||||
final String keystorePassword, |
||||
final KeyStore truststore, |
||||
final String truststorePassword) { |
||||
super((Path) null); |
||||
this.keystore = keystore; |
||||
this.keystorePassword = keystorePassword.toCharArray(); |
||||
this.truststore = truststore; |
||||
this.truststorePassword = truststorePassword.toCharArray(); |
||||
} |
||||
|
||||
/** |
||||
* Instantiates a new Software key store wrapper. |
||||
* |
||||
* @param crls the collection of X509CRL crls |
||||
* @param keystore the keystore |
||||
* @param keystorePassword the keystore password |
||||
*/ |
||||
@VisibleForTesting |
||||
public SoftwareKeyStoreWrapper( |
||||
final Collection<X509CRL> crls, final KeyStore keystore, final String keystorePassword) { |
||||
super(crls); |
||||
this.keystore = keystore; |
||||
this.keystorePassword = keystorePassword.toCharArray(); |
||||
this.truststore = null; |
||||
this.truststorePassword = null; |
||||
} |
||||
|
||||
@Override |
||||
public PrivateKey getPrivateKey(final String keyAlias) { |
||||
LOG.debug("Retrieving private key for alias: {}", keyAlias); |
||||
return (PrivateKey) getKey(keyAlias, PrivateKey.class, cachedPrivateKeys); |
||||
} |
||||
|
||||
@Override |
||||
public PublicKey getPublicKey(final String keyAlias) { |
||||
LOG.debug("Retrieving public key for alias: {}", keyAlias); |
||||
return (PublicKey) getKey(keyAlias, PublicKey.class, cachedPublicKeys); |
||||
} |
||||
|
||||
@Override |
||||
public Certificate getCertificate(final String certificateAlias) { |
||||
try { |
||||
LOG.debug("Retrieving certificate for alias: {}", certificateAlias); |
||||
Certificate certificate = cachedCertificates.get(certificateAlias); |
||||
if (certificate == null) { |
||||
LOG.debug("Certificate alias: {} not cached", certificateAlias); |
||||
|
||||
certificate = keystore.getCertificate(certificateAlias); |
||||
if (certificate == null && truststore != null) { |
||||
certificate = truststore.getCertificate(certificateAlias); |
||||
} |
||||
if (certificate != null) { |
||||
LOG.debug("Certificate alias: {} found in keystore/truststore", certificateAlias); |
||||
cachedCertificates.put(certificateAlias, certificate); |
||||
cachedPublicKeys.put(certificateAlias, certificate.getPublicKey()); |
||||
return certificate; |
||||
} else { |
||||
LOG.warn("Certificate alias: {} not found in keystore/truststore", certificateAlias); |
||||
} |
||||
} |
||||
return certificate; |
||||
|
||||
} catch (final Exception e) { |
||||
throw new PkiException("Failed to get certificate: " + certificateAlias, e); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Certificate[] getCertificateChain(final String certificateAlias) { |
||||
try { |
||||
LOG.debug("Retrieving certificate chain for alias: {}", certificateAlias); |
||||
|
||||
Certificate[] certificateChain = keystore.getCertificateChain(certificateAlias); |
||||
if (certificateChain == null && truststore != null) { |
||||
certificateChain = truststore.getCertificateChain(certificateAlias); |
||||
} |
||||
return certificateChain; |
||||
} catch (final Exception e) { |
||||
throw new PkiException( |
||||
"Failed to retrieve certificate chain for alias: " + certificateAlias, e); |
||||
} |
||||
} |
||||
|
||||
private Key getKey( |
||||
final String keyAlias, |
||||
final Class<? extends Key> keyTypeClass, |
||||
final Map<String, ? extends Key> keyCache) { |
||||
Key cachedKey = keyCache.get(keyAlias); |
||||
if (cachedKey == null) { |
||||
LOG.debug("Key alias: {} not cached", keyAlias); |
||||
try { |
||||
cachedKey = loadAndCacheKey(this.keystore, this.keystorePassword, keyAlias, keyTypeClass); |
||||
if (cachedKey == null) { |
||||
cachedKey = |
||||
loadAndCacheKey(this.truststore, this.truststorePassword, keyAlias, keyTypeClass); |
||||
} |
||||
} catch (final Exception e) { |
||||
throw new PkiException("Failed to get key: " + keyAlias, e); |
||||
} |
||||
} |
||||
return cachedKey; |
||||
} |
||||
|
||||
@Override |
||||
public KeyStore getKeyStore() { |
||||
return keystore; |
||||
} |
||||
|
||||
@Override |
||||
public KeyStore getTrustStore() { |
||||
return truststore; |
||||
} |
||||
|
||||
private Key loadAndCacheKey( |
||||
final KeyStore keystore, |
||||
final char[] keystorePassword, |
||||
final String keyAlias, |
||||
final Class<? extends Key> keyTypeClass) |
||||
throws GeneralSecurityException { |
||||
if (keystore != null && keystore.containsAlias(keyAlias)) { |
||||
|
||||
final Key key = keystore.getKey(keyAlias, keystorePassword); |
||||
if (key != null) { |
||||
LOG.debug("Key alias: {} found in keystore/truststore", keyAlias); |
||||
if (key instanceof PrivateKey && PrivateKey.class.isAssignableFrom(keyTypeClass)) { |
||||
cachedPrivateKeys.put(keyAlias, (PrivateKey) key); |
||||
return key; |
||||
} else if (key instanceof PublicKey && PublicKey.class.isAssignableFrom(keyTypeClass)) { |
||||
cachedPublicKeys.put(keyAlias, (PublicKey) key); |
||||
return key; |
||||
} |
||||
} |
||||
|
||||
if (PublicKey.class.isAssignableFrom(keyTypeClass)) { |
||||
final Certificate certificate = getCertificate(keyAlias); |
||||
if (certificate != null) { |
||||
return certificate.getPublicKey(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
LOG.warn("Key alias: {} not found in keystore/truststore", keyAlias); |
||||
return null; |
||||
} |
||||
} |
@ -1,217 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.pki.util; |
||||
|
||||
import org.hyperledger.besu.pki.cms.CmsCreator; |
||||
|
||||
import java.io.IOException; |
||||
import java.math.BigInteger; |
||||
import java.security.InvalidAlgorithmParameterException; |
||||
import java.security.KeyPair; |
||||
import java.security.KeyPairGenerator; |
||||
import java.security.NoSuchAlgorithmException; |
||||
import java.security.Security; |
||||
import java.security.cert.CRLException; |
||||
import java.security.cert.CRLReason; |
||||
import java.security.cert.CertificateEncodingException; |
||||
import java.security.cert.X509CRL; |
||||
import java.security.cert.X509Certificate; |
||||
import java.security.spec.ECGenParameterSpec; |
||||
import java.sql.Date; |
||||
import java.time.Instant; |
||||
import java.time.temporal.ChronoUnit; |
||||
import java.util.Collection; |
||||
import java.util.Random; |
||||
|
||||
import org.bouncycastle.asn1.x500.X500Name; |
||||
import org.bouncycastle.asn1.x509.BasicConstraints; |
||||
import org.bouncycastle.asn1.x509.Extension; |
||||
import org.bouncycastle.cert.X509CRLHolder; |
||||
import org.bouncycastle.cert.X509CertificateHolder; |
||||
import org.bouncycastle.cert.X509v2CRLBuilder; |
||||
import org.bouncycastle.cert.X509v3CertificateBuilder; |
||||
import org.bouncycastle.cert.jcajce.JcaX509CRLConverter; |
||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; |
||||
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils; |
||||
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; |
||||
import org.bouncycastle.jce.X509KeyUsage; |
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider; |
||||
import org.bouncycastle.operator.ContentSigner; |
||||
import org.bouncycastle.operator.OperatorCreationException; |
||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; |
||||
|
||||
/* |
||||
This class provides utility method for creating certificates used on tests. |
||||
|
||||
Based on https://stackoverflow.com/a/18648284/5021783
|
||||
*/ |
||||
public class TestCertificateUtils { |
||||
|
||||
static { |
||||
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { |
||||
Security.addProvider(new BouncyCastleProvider()); |
||||
} |
||||
} |
||||
|
||||
public enum Algorithm { |
||||
RSA, |
||||
EC |
||||
} |
||||
|
||||
public static KeyPair createKeyPair(final Algorithm algorithm) { |
||||
try { |
||||
@SuppressWarnings("InsecureCryptoUsage") |
||||
final KeyPairGenerator kpg = KeyPairGenerator.getInstance(algorithm.name()); |
||||
if (algorithm == Algorithm.EC) { |
||||
kpg.initialize(new ECGenParameterSpec("secp256r1")); |
||||
} |
||||
return kpg.generateKeyPair(); |
||||
} catch (NoSuchAlgorithmException e) { |
||||
throw new RuntimeException("Error creating KeyPair", e); |
||||
} catch (InvalidAlgorithmParameterException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
} |
||||
|
||||
public static X509Certificate createSelfSignedCertificate( |
||||
final String name, final Instant notBefore, final Instant notAfter, final KeyPair keyPair) { |
||||
try { |
||||
final String signatureAlgorithm = |
||||
CmsCreator.getPreferredSignatureAlgorithm(keyPair.getPublic()); |
||||
final ContentSigner signer = |
||||
new JcaContentSignerBuilder(signatureAlgorithm).build(keyPair.getPrivate()); |
||||
|
||||
final X509v3CertificateBuilder certificateBuilder = |
||||
new JcaX509v3CertificateBuilder( |
||||
new X500Name("CN=" + name), |
||||
new BigInteger(32, new Random()), |
||||
Date.from(notBefore), |
||||
Date.from(notAfter), |
||||
new X500Name("CN=" + name), |
||||
keyPair.getPublic()) |
||||
.addExtension( |
||||
Extension.authorityKeyIdentifier, |
||||
false, |
||||
new JcaX509ExtensionUtils().createAuthorityKeyIdentifier(keyPair.getPublic())) |
||||
.addExtension( |
||||
Extension.subjectKeyIdentifier, |
||||
false, |
||||
new JcaX509ExtensionUtils().createSubjectKeyIdentifier(keyPair.getPublic())) |
||||
.addExtension( |
||||
Extension.basicConstraints, |
||||
false, |
||||
new BasicConstraints(true)) // true if it is allowed to sign other certs
|
||||
.addExtension( |
||||
Extension.keyUsage, |
||||
true, |
||||
new X509KeyUsage(X509KeyUsage.keyCertSign | X509KeyUsage.cRLSign)); |
||||
|
||||
final X509CertificateHolder certHolder = certificateBuilder.build(signer); |
||||
|
||||
return new JcaX509CertificateConverter() |
||||
.setProvider(BouncyCastleProvider.PROVIDER_NAME) |
||||
.getCertificate(certHolder); |
||||
|
||||
} catch (final Exception e) { |
||||
throw new RuntimeException("Error creating CA certificate", e); |
||||
} |
||||
} |
||||
|
||||
public static X509Certificate issueCertificate( |
||||
final X509Certificate issuer, |
||||
final KeyPair issuerKeyPair, |
||||
final String subject, |
||||
final Instant notBefore, |
||||
final Instant notAfter, |
||||
final KeyPair keyPair, |
||||
final boolean isCa) { |
||||
|
||||
try { |
||||
final String signatureAlgorithm = |
||||
CmsCreator.getPreferredSignatureAlgorithm(keyPair.getPublic()); |
||||
final ContentSigner signer = |
||||
new JcaContentSignerBuilder(signatureAlgorithm).build(issuerKeyPair.getPrivate()); |
||||
|
||||
final X509v3CertificateBuilder certificateBuilder = |
||||
new JcaX509v3CertificateBuilder( |
||||
issuer, |
||||
new BigInteger(32, new Random()), |
||||
Date.from(notBefore), |
||||
Date.from(notAfter), |
||||
new X500Name("CN=" + subject), |
||||
keyPair.getPublic()) |
||||
.addExtension( |
||||
Extension.authorityKeyIdentifier, |
||||
false, |
||||
new JcaX509ExtensionUtils() |
||||
.createAuthorityKeyIdentifier(issuerKeyPair.getPublic())) |
||||
.addExtension( |
||||
Extension.basicConstraints, |
||||
false, |
||||
new BasicConstraints(isCa)) // true if it is allowed to sign other certs
|
||||
.addExtension( |
||||
Extension.keyUsage, |
||||
true, |
||||
new X509KeyUsage( |
||||
X509KeyUsage.digitalSignature |
||||
| X509KeyUsage.nonRepudiation |
||||
| X509KeyUsage.keyEncipherment |
||||
| X509KeyUsage.dataEncipherment |
||||
| X509KeyUsage.cRLSign |
||||
| X509KeyUsage.keyCertSign)); |
||||
|
||||
final X509CertificateHolder certHolder = certificateBuilder.build(signer); |
||||
|
||||
return new JcaX509CertificateConverter() |
||||
.setProvider(BouncyCastleProvider.PROVIDER_NAME) |
||||
.getCertificate(certHolder); |
||||
} catch (final Exception e) { |
||||
throw new RuntimeException("Error creating certificate", e); |
||||
} |
||||
} |
||||
|
||||
public static X509CRL createCRL( |
||||
final X509Certificate issuer, |
||||
final KeyPair issuerKeyPair, |
||||
final Collection<X509Certificate> revokedCertificates) { |
||||
try { |
||||
final X509CertificateHolder x509CertificateHolder = |
||||
new X509CertificateHolder(issuer.getEncoded()); |
||||
|
||||
final X509v2CRLBuilder crlBuilder = |
||||
new X509v2CRLBuilder(x509CertificateHolder.getSubject(), Date.from(Instant.now())); |
||||
|
||||
revokedCertificates.forEach( |
||||
c -> |
||||
crlBuilder.addCRLEntry( |
||||
c.getSerialNumber(), Date.from(Instant.now()), CRLReason.UNSPECIFIED.ordinal())); |
||||
|
||||
crlBuilder.setNextUpdate(Date.from(Instant.now().plus(1, ChronoUnit.DAYS))); |
||||
final String signatureAlgorithm = |
||||
CmsCreator.getPreferredSignatureAlgorithm(issuerKeyPair.getPublic()); |
||||
final ContentSigner signer = |
||||
new JcaContentSignerBuilder(signatureAlgorithm).build(issuerKeyPair.getPrivate()); |
||||
final X509CRLHolder crlHolder = crlBuilder.build(signer); |
||||
return new JcaX509CRLConverter() |
||||
.setProvider(BouncyCastleProvider.PROVIDER_NAME) |
||||
.getCRL(crlHolder); |
||||
} catch (OperatorCreationException |
||||
| CRLException |
||||
| CertificateEncodingException |
||||
| IOException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
} |
||||
} |
@ -1,27 +0,0 @@ |
||||
-----BEGIN X509 CRL----- |
||||
MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCVVMxCzAJBgNV |
||||
BAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJBgNVBAoMAk1DMQ0wCwYDVQQLDARyb290 |
||||
MRMwEQYDVQQDDApwYXJ0bmVyMWNhMSYwJAYJKoZIhvcNAQkBFhdwYXJ0bmVyMWNh |
||||
QHBhcnRuZXIxLmNvbRcNMjEwNjA3MTcwNjAwWhcNMjIwNjA3MTcwNjAwWjAnMCUC |
||||
FGltgEkvXupxY562dERH8+uKOf89Fw0yMTA2MDcxNzA2MDBaoA4wDDAKBgNVHRQE |
||||
AwIBADANBgkqhkiG9w0BAQsFAAOCAQEABF/7Kq+byYi/bRoftL8xqgSGcaLVuCOF |
||||
BZVZXDKjyYfISwBqbvPSqtIvnFO1ewicgD7dNIZwWcQ9Kx7OOz4BA6Pe8YPtiBfp |
||||
HZMabT8BS2eLePvViGumY7PTo3oIk3yXylOtzMDo59WQhCH/0vp5xjzJC+VFex/W |
||||
p/an5ii1y3Q1FpEZNer6jpU0xJEJ2mCaGT/zuj6Mg1awWqmmYce3BahZeCNj8Wyx |
||||
GIy8bGUjOdJyp99rAF9euCZ45pAjI12sg9lhPIVkp3Wnoy3La4Yj219Elc3MbJvF |
||||
8GEFEmZ0Lm5Ze/EG5VyLB+wRpggeSJTc20i/eGWdaWg8AEukCgMdCg== |
||||
-----END X509 CRL----- |
||||
-----BEGIN X509 CRL----- |
||||
MIICLDCCARQCAQEwDQYJKoZIhvcNAQELBQAwgYExCzAJBgNVBAYTAlVTMQswCQYD |
||||
VQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9v |
||||
dDETMBEGA1UEAwwKcGFydG5lcjJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcjJj |
||||
YUBwYXJ0bmVyMi5jb20XDTIxMDYwNzE3MDYwMFoXDTIyMDYwNzE3MDYwMFowTjAl |
||||
AhRpbYBJL17qcWOetnRER/Prijn/PRcNMjEwNjA3MTcwNjAwWjAlAhR+2Aa1zeVQ |
||||
jbXFGnXFu53h4vZEahcNMjEwNjA3MTcwNjAwWqAOMAwwCgYDVR0UBAMCAQEwDQYJ |
||||
KoZIhvcNAQELBQADggEBAFXQOMk+6FDP8bm9TGK079IHojhooipo+9x3I1y/kUhH |
||||
XY7xuyTXOvzv14//xenDuryIjSAC8pyqbls+DcUXkmGZ/nIWugtMykGLNgqqo/Oe |
||||
pfoUSXRJP7CtvfHa4ejfr3q1t5MXfM3nqBQumu65slWjDFtE6mZF4ANcsIlsNQ10 |
||||
GTkDIdDHgUWxmZlBzTkoofvYspixuUptpJfl5eei9SDA+T1uADKnjARkxVv8xeYi |
||||
QwTp6jVYq6YKc9z0l1UMadnFQz8osk7QNypWnsrD0+iBB1if8ikJwy+8BWayTkgQ |
||||
tWLFT4n/c1m/wYzSclvZUUOxkkkE4Q9fZ3ReCADC+bQ= |
||||
-----END X509 CRL----- |
Binary file not shown.
Binary file not shown.
@ -1,6 +0,0 @@ |
||||
|
||||
name = NSScrypto-invalidpartner1client1 |
||||
nssSecmodDirectory = ./src/test/resources/keystore/invalidpartner1client1/nssdb |
||||
nssDbMode = readOnly |
||||
nssModule = keystore |
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@ |
||||
test123 |
@ -1,72 +0,0 @@ |
||||
-----BEGIN CERTIFICATE----- |
||||
MIIEFDCCAvygAwIBAgIUaZCzBtI9osbhHtrNGSQLldSCSHkwDQYJKoZIhvcNAQEL |
||||
BQAwgYYxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw |
||||
CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEXMBUGA1UEAwwOaW52YWxpZGludGVy |
||||
Y2ExJzAlBgkqhkiG9w0BCQEWGGludmFsaWRpbnRlcmNhQGFkbWluLmNvbTAgFw0y |
||||
MTA2MDcxNzA1NTJaGA8yMTIxMDUxNDE3MDU1MlowgZYxCzAJBgNVBAYTAlVTMQsw |
||||
CQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwE |
||||
cm9vdDEaMBgGA1UEAwwRaW52YWxpZHBhcnRuZXIxY2ExNDAyBgkqhkiG9w0BCQEW |
||||
JWludmFsaWRwYXJ0bmVyMWNhQGludmFsaWRwYXJ0bmVyMS5jb20wggEiMA0GCSqG |
||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDEMKBBPhzkvg+icZoRsN8CW2tlB4RZXo3C |
||||
apaQu2oJdEIqyKMRx86Uk7mRsW4rNWSbOjQwfCVsvhkUdriqBD+DfkzE03KKmhmL |
||||
hs2aC+ICb31aGyEvfWYFmKckY4zO8ptObaddWUZt27aie5vOzutB9n+oBmZMezd1 |
||||
xc4dwOO+MzC92Ay3DIxw52SzGiywPGn3gfNWZ5NGvWM1poV4SwTi/eJXF/lwU9aY |
||||
Hl/+XOQ5/PJrIiQKGbBaywoOwYUU3FReosgCFVwDadnsj4ma++TKi/U7GQTcA01B |
||||
1F42sZx1vmLJC68jAyDJylAEtUZxiGs8LQ/S8B1zXBvdfiYW7RQfAgMBAAGjZjBk |
||||
MB0GA1UdDgQWBBQswNKqcoGkBJOL6/iCkqmNYsyypzAfBgNVHSMEGDAWgBRZVeo2 |
||||
o+J44Ie43gS6L4tG3S0CaTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQE |
||||
AwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAUu60om2Fcx7h5C+bVmmBUhMDbnkWO9pa |
||||
lmEhmeuRrrmvSj/Ny6vmAmy9XOpox2PWMO5AndCIChLX697M4HskxIXCYhZzhjHE |
||||
x85WtmRjZAxdBA7vhgA6KIz58BJ6PmmJ3nYwc9dpyMthuMH74FcjfgsBL/1UalLI |
||||
26WtNMqEr+qK/drrlKpGHb1TjB3eWC1OPAwusgkw4uQBzKGHUZKxsVlaQ8jNkLdq |
||||
t31kMk770wXPh57N1tMn+gF21kACbkk0L4os+5AknYXWUS1A546I1TiEKmbKktPa |
||||
SdZIUT2AdIpZl4XMR5DZXBhMw8i/XyNfU6mW4b7TRt+QHU8l8ao47Q== |
||||
-----END CERTIFICATE----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIIECDCCAvCgAwIBAgIUK5+/p9u9ZYQuD9obuRHeJx0msBgwDQYJKoZIhvcNAQEL |
||||
BQAwgYoxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw |
||||
CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEcMBoGA1UEAwwTcm9vdGludmFsaWRj |
||||
YS5hZG1pbjEmMCQGCSqGSIb3DQEJARYXcm9vdGludmFsaWRjYUBhZG1pbi5jb20w |
||||
IBcNMjEwNjA3MTcwNTUyWhgPMjEyMTA1MTQxNzA1NTJaMIGGMQswCQYDVQQGEwJV |
||||
UzELMAkGA1UECAwCQ0ExDDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMxDTALBgNV |
||||
BAsMBHJvb3QxFzAVBgNVBAMMDmludmFsaWRpbnRlcmNhMScwJQYJKoZIhvcNAQkB |
||||
FhhpbnZhbGlkaW50ZXJjYUBhZG1pbi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB |
||||
DwAwggEKAoIBAQDNNU2p6MImjkrboq5MG7x422jISEYA9Zi/AMruUlQIXYwNUClc |
||||
yhalIPaToNRDBZ1mxj1uhdS/bxbAGxfO7EDQAcTGzIMhlkC+i/zLTSXTsoHjmgrt |
||||
5ZNQsc2Ok/a4aMpDUxZIx480Gm1GWEn5wrZpKJPdPnwwOg8tcjT4FCxI3CsMYQqb |
||||
UOR3iJn9IRyqTc1M/LCt5rYsd3slXVMnEOU5iu4UHJaNzKLlfsnB2LsdVqGqKA2e |
||||
nc6xdui+iJh81dqX/0RVUmyz4lDvhw8qfE58WAo4iIcpjBDcS8GPwt7WBF5KR120 |
||||
HWF3HErVOsra/eVPK3iZU5vvWuU+zQ8pAm5DAgMBAAGjZjBkMB0GA1UdDgQWBBRZ |
||||
Veo2o+J44Ie43gS6L4tG3S0CaTAfBgNVHSMEGDAWgBS5ftf0c7cpwPnkG0MaBaV5 |
||||
jXxrdzASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG |
||||
9w0BAQsFAAOCAQEAjnY1t9Pt8DxhExpqnLBLkhGeg+upWQutTsvW+JMowPw+rX3H |
||||
m7mRKDkGl98Ol9m/6Iwx4kjgNz/bFx9flgJTYKvLE+yK/Jg4cizMjE4s9CzBA9ic |
||||
R20L0MrRS3w8ae6IXXDZaaZvwmUqxYOCChr1mXslP59EXPPeTbQa2asTAz5sYAFV |
||||
btPAjNa0T3KGcSbKyfZj3kAmNBFXrpyS0FcEQCt/u3USx1zGF1YuPGte0VBxtYw1 |
||||
S/6DAeff+3rA9FAXXoG4qu+ZKu2kYydyJJPborTtJ3A/ATJmcJL2KW6ADHRK7rn1 |
||||
NLj25w6mQoSRhoOLWHe+oWNF5nMO1SmMzfwlEQ== |
||||
-----END CERTIFICATE----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIID+TCCAuGgAwIBAgIUMcRYNxIDRzqdAgyjxeKuyrSVsscwDQYJKoZIhvcNAQEL |
||||
BQAwgYoxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw |
||||
CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEcMBoGA1UEAwwTcm9vdGludmFsaWRj |
||||
YS5hZG1pbjEmMCQGCSqGSIb3DQEJARYXcm9vdGludmFsaWRjYUBhZG1pbi5jb20w |
||||
IBcNMjEwNjA3MTcwNTUyWhgPMjEyMTA1MTQxNzA1NTJaMIGKMQswCQYDVQQGEwJV |
||||
UzELMAkGA1UECAwCQ0ExDDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMxDTALBgNV |
||||
BAsMBHJvb3QxHDAaBgNVBAMME3Jvb3RpbnZhbGlkY2EuYWRtaW4xJjAkBgkqhkiG |
||||
9w0BCQEWF3Jvb3RpbnZhbGlkY2FAYWRtaW4uY29tMIIBIjANBgkqhkiG9w0BAQEF |
||||
AAOCAQ8AMIIBCgKCAQEAzmtt2EEdHNucUr8lZt8owINf9dSmCcpt663rnj833TO1 |
||||
mCdKdmZvQYzgvdfVCLqonj5CaHts4GCyh3PeHxU+zqjEWxPbZCSkITKOtn3AblTJ |
||||
n4yFGpV6eIuGRFSL6TAaSPOyt59ZIFfSn5HDpVtET2/1hKRjjEnWhKy1pIG2J/mp |
||||
BaXO7QJtJyTbYdXm2AXorQChbX8T5J965wl4k/xLGrHtRcvaDeZsy9TdtYLseC78 |
||||
bLFVwi7gAu3S9R6u9AuoVEn3rSZXaF+wSkH0GTX8rP049wQ9pQCS/zwjcQtcg+uT |
||||
2gbgRtMo+se1FV1YFylx0xIUWCh91uX1EAPhmw0IBQIDAQABo1MwUTAdBgNVHQ4E |
||||
FgQUuX7X9HO3KcD55BtDGgWleY18a3cwHwYDVR0jBBgwFoAUuX7X9HO3KcD55BtD |
||||
GgWleY18a3cwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAj/rZ |
||||
ga+ClC89q4a89U/OhX7hR8xOTPfpDLBGI8TpU2iXR57SZd4LvSNW1MTOJh/aTC/z |
||||
wA+MvhP3RK03kzW2pE3aauglT0bwx+mZ24oaQFGR1GLPhgq5BMina6Fr9C3NJggf |
||||
WtAoKNe+JoYUZkoLeBEnOcYEBZ1JYq7WBmctEY7sJgz456Coa0Ja+yXrPUPDbkKO |
||||
oTCeIwt9Fusk9T8y78+Ugx9eQuQGbwKF7evwQg0ZsuOWPvn0Y1qG0obph95tPp0s |
||||
HfNIDbTyjVga/gy3Et81E+AMrl7lKl5XZW0DZHSi41Y0KC5GhBBohrTIBoruIIkI |
||||
+hYCoquh8+xoYv32jg== |
||||
-----END CERTIFICATE----- |
@ -1,129 +0,0 @@ |
||||
-----BEGIN PRIVATE KEY----- |
||||
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCfr4vk1jKqglCu |
||||
6yGwIkqNFY/khpYA4UzHMueQ3ChFNTuQo+NhKz6B4akmL7fAFvYyeXdAAceNsBJ+ |
||||
eTDDB/DdLUqMPwYI1DUvG/8aDds7j+bRTX1ozLKML96qdL+JfGMAuT8jz37L66iW |
||||
DXYAS7dDHXOaNJ7HzUddngLMutjJ2NKi4jGhRHOeGxi22PLEL+yguZha3wyGMIks |
||||
2Gqz2rMqkuqLqAyEPX8GHWmNVXy0e/ruhp6VRa4vNyzWiMjs5Z6LR1/JQVzjlT5R |
||||
1MB1QYSp5u8tv6N+ySaH1kK/DiNi/TIAWnGGjaVkfW9iWANYodEuH/9yAzbFLT7e |
||||
vt92CRHVAgMBAAECggEBAJUZS/23IkeitcMdOK9E1Wc2Isy1/YmE1DOKjDzt04wL |
||||
UDqVS9GGly6ejVliZKeuyOIIGBhjkPfy1tHQRn9UAsoBaAHbNr83pRD/iwnAtlq+ |
||||
2j3DpL0do/jRGY7+w3iT87zROuss6q9sslSo7O0JxWudLDtntnnIakI3L1YJgDG2 |
||||
D92AVgwrDj+cePdns8CEOVjhW9qURxFz7dpC8AWS9mBmhcjCz2lAORjlpcR0TGEQ |
||||
+FN6KNVrsAi4ixURaetW1Jnj+N5v/rrmfDwGQq3rr5LL26rBao9ScteWJRUTlDqX |
||||
AkexjIrFeDKvlH6+rvwAq17dbTVvPmUjrmNd70AxgAECgYEA0hesj1BpELmxqowY |
||||
IIGKuIxVYAqBuZoU+rgiXPIjBvGX6iwvovUeGuDgeXPcb9bkmVvAfQM40JJyRVBm |
||||
Ww5tVX0+omrSrksOxf/+1g11Dybpnv4ZSa2cE30qQMxiyStADJHD+EyTZoRg3BUc |
||||
E7m77ml2/8EtrQ5lIG8aBDvrfdUCgYEAwpQtnshmzj9vQF2webxFCnUA5judEwpi |
||||
T8bwlJlPAB0l0K70lFkju3W8H52qHIoy+FR6kyoC76q5G4s8gVx5sPilOf7Gph29 |
||||
w3IfSKsk3BC2xKl8saKZvMBmve02EtZVCf5JAoeD9KzfVOPculPljcKmEetI68qn |
||||
PPaaozVtRAECgYEAqzkoJdT/C+aLadergjKRgD6/BfsKJt3w4zVWrDGbYnlbujow |
||||
yLrEwlssF0/aBDw7KtGgW0JY94OjJeKUyPlFGjts5Kny8qGxdKViZ8mn8aVhGXc1 |
||||
3NplLW0BFrZ8fD+Hf7b85ExkhVS2LCf4LgtdorzJgz9JnpTwzjI+Hd1H29ECgYEA |
||||
p3UDNg3efE4XntuCz6H6AR/lID/Z1NMw/NuHnTu7w6tSKiEIGMwGdoTC3KrCBkHh |
||||
z9pUi2aylDTnjg7siaBekrHK8PiVWc1qzVPgHJg95q7zvJjo2a/Ig6tKQNZvnRKc |
||||
qTcQ+n5KUD6fDd30zt75RmFory9A2LzV5R+OwjtuyAECgYBZrqUVGu61Rod3zFvz |
||||
y/SAirOMEgNDNfxGKSyuUwllrX/9H9jmmcM198Sx/bGXPX80H6f8Ov0Od46MhpXR |
||||
rnhHDQ6N/8OPzeZ5C7ri/ku1RS11Q7Z+a9kn5VS3gjFZpHCu2GIa6Tzn3Ag+czV1 |
||||
3QpC2/6ydTgrrDAhNBwcZ5xY/g== |
||||
-----END PRIVATE KEY----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIIFAzCCA+ugAwIBAgIUBxLi0l/lss+0yOGpKQjfW+GTHI4wDQYJKoZIhvcNAQEL |
||||
BQAwgZYxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw |
||||
CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEaMBgGA1UEAwwRaW52YWxpZHBhcnRu |
||||
ZXIxY2ExNDAyBgkqhkiG9w0BCQEWJWludmFsaWRwYXJ0bmVyMWNhQGludmFsaWRw |
||||
YXJ0bmVyMS5jb20wIBcNMjEwNjA3MTcwNTUyWhgPMjEyMTA1MTQxNzA1NTJaMIGg |
||||
MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExDDAKBgNVBAcMA1NGTzELMAkGA1UE |
||||
CgwCTUMxDTALBgNVBAsMBHJvb3QxHzAdBgNVBAMMFmludmFsaWRwYXJ0bmVyMWNs |
||||
aWVudDExOTA3BgkqhkiG9w0BCQEWKmludmFsaWRwYXJ0bmVyMWNsaWVudDFAaW52 |
||||
YWxpZHBhcnRuZXIxLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB |
||||
AJ+vi+TWMqqCUK7rIbAiSo0Vj+SGlgDhTMcy55DcKEU1O5Cj42ErPoHhqSYvt8AW |
||||
9jJ5d0ABx42wEn55MMMH8N0tSow/BgjUNS8b/xoN2zuP5tFNfWjMsowv3qp0v4l8 |
||||
YwC5PyPPfsvrqJYNdgBLt0Mdc5o0nsfNR12eAsy62MnY0qLiMaFEc54bGLbY8sQv |
||||
7KC5mFrfDIYwiSzYarPasyqS6ouoDIQ9fwYdaY1VfLR7+u6GnpVFri83LNaIyOzl |
||||
notHX8lBXOOVPlHUwHVBhKnm7y2/o37JJofWQr8OI2L9MgBacYaNpWR9b2JYA1ih |
||||
0S4f/3IDNsUtPt6+33YJEdUCAwEAAaOCATkwggE1MBEGCWCGSAGG+EIBAQQEAwIG |
||||
wDAdBgNVHQ4EFgQUEUDbVrBFiwidyWrMY6rUqIi06bIwCQYDVR0TBAIwADAOBgNV |
||||
HQ8BAf8EBAMCBeAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMIHGBgNV |
||||
HSMEgb4wgbuAFCzA0qpygaQEk4vr+IKSqY1izLKnoYGMpIGJMIGGMQswCQYDVQQG |
||||
EwJVUzELMAkGA1UECAwCQ0ExDDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMxDTAL |
||||
BgNVBAsMBHJvb3QxFzAVBgNVBAMMDmludmFsaWRpbnRlcmNhMScwJQYJKoZIhvcN |
||||
AQkBFhhpbnZhbGlkaW50ZXJjYUBhZG1pbi5jb22CFGmQswbSPaLG4R7azRkkC5XU |
||||
gkh5MA0GCSqGSIb3DQEBCwUAA4IBAQB5fiodcOYjxuCLjI+1AAsQP+mApMO5DJn3 |
||||
tJh8ARt7TK1TzWBTaOQNe+MP4vUHKYu2pXDv07csgBM9F5WEXPbADTHOVd16h+5Q |
||||
OVK8JsfXaq26mg/+zp6UiK2JVHE+MCyVOfDhbpbu2WPXdzeOiPuQsBwzsolPWoMI |
||||
/dvIhKuHtUZ9wGSIurulCYPSqvUDOoHkFnIdsDMq3ISP5y6kCLCDDAqpwYb6PrfF |
||||
R0lJvbORWZ67LcHAvJgdmN1u93FG3yTh9xCl4fhCfNtsbVsQpXaYyTKhdBLaS9in |
||||
pyrOIxZJ9yiWk4iMv4/Ehm5BgR6CAJPHo3dvx46veSkVsztYQQDe |
||||
-----END CERTIFICATE----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIIEFDCCAvygAwIBAgIUaZCzBtI9osbhHtrNGSQLldSCSHkwDQYJKoZIhvcNAQEL |
||||
BQAwgYYxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw |
||||
CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEXMBUGA1UEAwwOaW52YWxpZGludGVy |
||||
Y2ExJzAlBgkqhkiG9w0BCQEWGGludmFsaWRpbnRlcmNhQGFkbWluLmNvbTAgFw0y |
||||
MTA2MDcxNzA1NTJaGA8yMTIxMDUxNDE3MDU1MlowgZYxCzAJBgNVBAYTAlVTMQsw |
||||
CQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwE |
||||
cm9vdDEaMBgGA1UEAwwRaW52YWxpZHBhcnRuZXIxY2ExNDAyBgkqhkiG9w0BCQEW |
||||
JWludmFsaWRwYXJ0bmVyMWNhQGludmFsaWRwYXJ0bmVyMS5jb20wggEiMA0GCSqG |
||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDEMKBBPhzkvg+icZoRsN8CW2tlB4RZXo3C |
||||
apaQu2oJdEIqyKMRx86Uk7mRsW4rNWSbOjQwfCVsvhkUdriqBD+DfkzE03KKmhmL |
||||
hs2aC+ICb31aGyEvfWYFmKckY4zO8ptObaddWUZt27aie5vOzutB9n+oBmZMezd1 |
||||
xc4dwOO+MzC92Ay3DIxw52SzGiywPGn3gfNWZ5NGvWM1poV4SwTi/eJXF/lwU9aY |
||||
Hl/+XOQ5/PJrIiQKGbBaywoOwYUU3FReosgCFVwDadnsj4ma++TKi/U7GQTcA01B |
||||
1F42sZx1vmLJC68jAyDJylAEtUZxiGs8LQ/S8B1zXBvdfiYW7RQfAgMBAAGjZjBk |
||||
MB0GA1UdDgQWBBQswNKqcoGkBJOL6/iCkqmNYsyypzAfBgNVHSMEGDAWgBRZVeo2 |
||||
o+J44Ie43gS6L4tG3S0CaTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQE |
||||
AwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAUu60om2Fcx7h5C+bVmmBUhMDbnkWO9pa |
||||
lmEhmeuRrrmvSj/Ny6vmAmy9XOpox2PWMO5AndCIChLX697M4HskxIXCYhZzhjHE |
||||
x85WtmRjZAxdBA7vhgA6KIz58BJ6PmmJ3nYwc9dpyMthuMH74FcjfgsBL/1UalLI |
||||
26WtNMqEr+qK/drrlKpGHb1TjB3eWC1OPAwusgkw4uQBzKGHUZKxsVlaQ8jNkLdq |
||||
t31kMk770wXPh57N1tMn+gF21kACbkk0L4os+5AknYXWUS1A546I1TiEKmbKktPa |
||||
SdZIUT2AdIpZl4XMR5DZXBhMw8i/XyNfU6mW4b7TRt+QHU8l8ao47Q== |
||||
-----END CERTIFICATE----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIIECDCCAvCgAwIBAgIUK5+/p9u9ZYQuD9obuRHeJx0msBgwDQYJKoZIhvcNAQEL |
||||
BQAwgYoxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw |
||||
CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEcMBoGA1UEAwwTcm9vdGludmFsaWRj |
||||
YS5hZG1pbjEmMCQGCSqGSIb3DQEJARYXcm9vdGludmFsaWRjYUBhZG1pbi5jb20w |
||||
IBcNMjEwNjA3MTcwNTUyWhgPMjEyMTA1MTQxNzA1NTJaMIGGMQswCQYDVQQGEwJV |
||||
UzELMAkGA1UECAwCQ0ExDDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMxDTALBgNV |
||||
BAsMBHJvb3QxFzAVBgNVBAMMDmludmFsaWRpbnRlcmNhMScwJQYJKoZIhvcNAQkB |
||||
FhhpbnZhbGlkaW50ZXJjYUBhZG1pbi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB |
||||
DwAwggEKAoIBAQDNNU2p6MImjkrboq5MG7x422jISEYA9Zi/AMruUlQIXYwNUClc |
||||
yhalIPaToNRDBZ1mxj1uhdS/bxbAGxfO7EDQAcTGzIMhlkC+i/zLTSXTsoHjmgrt |
||||
5ZNQsc2Ok/a4aMpDUxZIx480Gm1GWEn5wrZpKJPdPnwwOg8tcjT4FCxI3CsMYQqb |
||||
UOR3iJn9IRyqTc1M/LCt5rYsd3slXVMnEOU5iu4UHJaNzKLlfsnB2LsdVqGqKA2e |
||||
nc6xdui+iJh81dqX/0RVUmyz4lDvhw8qfE58WAo4iIcpjBDcS8GPwt7WBF5KR120 |
||||
HWF3HErVOsra/eVPK3iZU5vvWuU+zQ8pAm5DAgMBAAGjZjBkMB0GA1UdDgQWBBRZ |
||||
Veo2o+J44Ie43gS6L4tG3S0CaTAfBgNVHSMEGDAWgBS5ftf0c7cpwPnkG0MaBaV5 |
||||
jXxrdzASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG |
||||
9w0BAQsFAAOCAQEAjnY1t9Pt8DxhExpqnLBLkhGeg+upWQutTsvW+JMowPw+rX3H |
||||
m7mRKDkGl98Ol9m/6Iwx4kjgNz/bFx9flgJTYKvLE+yK/Jg4cizMjE4s9CzBA9ic |
||||
R20L0MrRS3w8ae6IXXDZaaZvwmUqxYOCChr1mXslP59EXPPeTbQa2asTAz5sYAFV |
||||
btPAjNa0T3KGcSbKyfZj3kAmNBFXrpyS0FcEQCt/u3USx1zGF1YuPGte0VBxtYw1 |
||||
S/6DAeff+3rA9FAXXoG4qu+ZKu2kYydyJJPborTtJ3A/ATJmcJL2KW6ADHRK7rn1 |
||||
NLj25w6mQoSRhoOLWHe+oWNF5nMO1SmMzfwlEQ== |
||||
-----END CERTIFICATE----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIID+TCCAuGgAwIBAgIUMcRYNxIDRzqdAgyjxeKuyrSVsscwDQYJKoZIhvcNAQEL |
||||
BQAwgYoxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw |
||||
CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEcMBoGA1UEAwwTcm9vdGludmFsaWRj |
||||
YS5hZG1pbjEmMCQGCSqGSIb3DQEJARYXcm9vdGludmFsaWRjYUBhZG1pbi5jb20w |
||||
IBcNMjEwNjA3MTcwNTUyWhgPMjEyMTA1MTQxNzA1NTJaMIGKMQswCQYDVQQGEwJV |
||||
UzELMAkGA1UECAwCQ0ExDDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMxDTALBgNV |
||||
BAsMBHJvb3QxHDAaBgNVBAMME3Jvb3RpbnZhbGlkY2EuYWRtaW4xJjAkBgkqhkiG |
||||
9w0BCQEWF3Jvb3RpbnZhbGlkY2FAYWRtaW4uY29tMIIBIjANBgkqhkiG9w0BAQEF |
||||
AAOCAQ8AMIIBCgKCAQEAzmtt2EEdHNucUr8lZt8owINf9dSmCcpt663rnj833TO1 |
||||
mCdKdmZvQYzgvdfVCLqonj5CaHts4GCyh3PeHxU+zqjEWxPbZCSkITKOtn3AblTJ |
||||
n4yFGpV6eIuGRFSL6TAaSPOyt59ZIFfSn5HDpVtET2/1hKRjjEnWhKy1pIG2J/mp |
||||
BaXO7QJtJyTbYdXm2AXorQChbX8T5J965wl4k/xLGrHtRcvaDeZsy9TdtYLseC78 |
||||
bLFVwi7gAu3S9R6u9AuoVEn3rSZXaF+wSkH0GTX8rP049wQ9pQCS/zwjcQtcg+uT |
||||
2gbgRtMo+se1FV1YFylx0xIUWCh91uX1EAPhmw0IBQIDAQABo1MwUTAdBgNVHQ4E |
||||
FgQUuX7X9HO3KcD55BtDGgWleY18a3cwHwYDVR0jBBgwFoAUuX7X9HO3KcD55BtD |
||||
GgWleY18a3cwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAj/rZ |
||||
ga+ClC89q4a89U/OhX7hR8xOTPfpDLBGI8TpU2iXR57SZd4LvSNW1MTOJh/aTC/z |
||||
wA+MvhP3RK03kzW2pE3aauglT0bwx+mZ24oaQFGR1GLPhgq5BMina6Fr9C3NJggf |
||||
WtAoKNe+JoYUZkoLeBEnOcYEBZ1JYq7WBmctEY7sJgz456Coa0Ja+yXrPUPDbkKO |
||||
oTCeIwt9Fusk9T8y78+Ugx9eQuQGbwKF7evwQg0ZsuOWPvn0Y1qG0obph95tPp0s |
||||
HfNIDbTyjVga/gy3Et81E+AMrl7lKl5XZW0DZHSi41Y0KC5GhBBohrTIBoruIIkI |
||||
+hYCoquh8+xoYv32jg== |
||||
-----END CERTIFICATE----- |
Binary file not shown.
Binary file not shown.
@ -1,27 +0,0 @@ |
||||
-----BEGIN X509 CRL----- |
||||
MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCVVMxCzAJBgNV |
||||
BAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJBgNVBAoMAk1DMQ0wCwYDVQQLDARyb290 |
||||
MRMwEQYDVQQDDApwYXJ0bmVyMWNhMSYwJAYJKoZIhvcNAQkBFhdwYXJ0bmVyMWNh |
||||
QHBhcnRuZXIxLmNvbRcNMjEwNjA3MTcwNjAwWhcNMjIwNjA3MTcwNjAwWjAnMCUC |
||||
FGltgEkvXupxY562dERH8+uKOf89Fw0yMTA2MDcxNzA2MDBaoA4wDDAKBgNVHRQE |
||||
AwIBADANBgkqhkiG9w0BAQsFAAOCAQEABF/7Kq+byYi/bRoftL8xqgSGcaLVuCOF |
||||
BZVZXDKjyYfISwBqbvPSqtIvnFO1ewicgD7dNIZwWcQ9Kx7OOz4BA6Pe8YPtiBfp |
||||
HZMabT8BS2eLePvViGumY7PTo3oIk3yXylOtzMDo59WQhCH/0vp5xjzJC+VFex/W |
||||
p/an5ii1y3Q1FpEZNer6jpU0xJEJ2mCaGT/zuj6Mg1awWqmmYce3BahZeCNj8Wyx |
||||
GIy8bGUjOdJyp99rAF9euCZ45pAjI12sg9lhPIVkp3Wnoy3La4Yj219Elc3MbJvF |
||||
8GEFEmZ0Lm5Ze/EG5VyLB+wRpggeSJTc20i/eGWdaWg8AEukCgMdCg== |
||||
-----END X509 CRL----- |
||||
-----BEGIN X509 CRL----- |
||||
MIICLDCCARQCAQEwDQYJKoZIhvcNAQELBQAwgYExCzAJBgNVBAYTAlVTMQswCQYD |
||||
VQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9v |
||||
dDETMBEGA1UEAwwKcGFydG5lcjJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcjJj |
||||
YUBwYXJ0bmVyMi5jb20XDTIxMDYwNzE3MDYwMFoXDTIyMDYwNzE3MDYwMFowTjAl |
||||
AhRpbYBJL17qcWOetnRER/Prijn/PRcNMjEwNjA3MTcwNjAwWjAlAhR+2Aa1zeVQ |
||||
jbXFGnXFu53h4vZEahcNMjEwNjA3MTcwNjAwWqAOMAwwCgYDVR0UBAMCAQEwDQYJ |
||||
KoZIhvcNAQELBQADggEBAFXQOMk+6FDP8bm9TGK079IHojhooipo+9x3I1y/kUhH |
||||
XY7xuyTXOvzv14//xenDuryIjSAC8pyqbls+DcUXkmGZ/nIWugtMykGLNgqqo/Oe |
||||
pfoUSXRJP7CtvfHa4ejfr3q1t5MXfM3nqBQumu65slWjDFtE6mZF4ANcsIlsNQ10 |
||||
GTkDIdDHgUWxmZlBzTkoofvYspixuUptpJfl5eei9SDA+T1uADKnjARkxVv8xeYi |
||||
QwTp6jVYq6YKc9z0l1UMadnFQz8osk7QNypWnsrD0+iBB1if8ikJwy+8BWayTkgQ |
||||
tWLFT4n/c1m/wYzSclvZUUOxkkkE4Q9fZ3ReCADC+bQ= |
||||
-----END X509 CRL----- |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@ |
||||
test123 |
@ -1,70 +0,0 @@ |
||||
-----BEGIN CERTIFICATE----- |
||||
MIID8DCCAtigAwIBAgIUNniG6StciHezbAqX+uNMciPW7jowDQYJKoZIhvcNAQEL |
||||
BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ |
||||
BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ |
||||
KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA2MDcxNzA1NDdaGA8y |
||||
MTIxMDUxNDE3MDU0N1owgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG |
||||
A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK |
||||
cGFydG5lcjFjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcjFjYUBwYXJ0bmVyMS5j |
||||
b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDR8KbDV1MbtC1Siuo2 |
||||
pbOU6eMRaNyDdlhcz48FY+mKGsUEAePceFJTvh1w9gXwt/A26CO02BVdTPYowudf |
||||
Qkl9v+qSRIKXgKz1fkNUW4xYKl7KsgABi/zpgY/bM3CarBcBan9VKWapgx680Aj2 |
||||
bv99ODNqZTH9Iwdq2IrHNBplLp2TmFao7oKz+LeMV6ZrdfY1THf1AuprD86Ccxfa |
||||
9YAyuMI4t7BKqmIqMuDKSSykXuEDY/CCDWw8o/0rg6baoM4bKzipv/4oqaegM3MB |
||||
8vt979rx4PGH69+/JSMt7wL3SQbkQtMNODZyGM/HW+TsPAFYfHPsURVRezFpOB7G |
||||
OoTdAgMBAAGjZjBkMB0GA1UdDgQWBBSB8CJNxPXuu/mEDmD1+rPhI/qN5DAfBgNV |
||||
HSMEGDAWgBT8BlnPk8BS8+JHlIEoCp3sO8jDDjASBgNVHRMBAf8ECDAGAQH/AgEA |
||||
MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAKb5S3NTSxSJrI5Mk |
||||
EKoULvy7vKh+W/o5wDKm8ILwJHn76HFyq3Nl0zYdoshROnLG8gL69rMWZgTg+Fsl |
||||
teX8pNvLEQV7Asx5Yvn2oFBQqRevwGsg2z48et5SIq5pDYeThwUMbdrGuhkEkizW |
||||
ecBUN8j7auRLSpx5ornl9zFx5bvsVb4Dy/rIMVnPiw3VniOAOplGIJOm/TiPxTR0 |
||||
qyzdHljsRbM0uyw81QkeskuJWCpmKTFZxfV1Jww3ScKApNY8WFW+iuarWBvRTq7l |
||||
3AxXcE11ms92rnZw3vFvrIfM6WlE7Idb0rlRK69e73j40eBtJN5i6L7IPJ7Uht+N |
||||
mLfQvw== |
||||
-----END CERTIFICATE----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIID6jCCAtKgAwIBAgIUTwPfI+2FxYq0V6uukemLf67qANowDQYJKoZIhvcNAQEL |
||||
BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ |
||||
BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x |
||||
HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNjA3MTcwNTQ3 |
||||
WhgPMjEyMTA1MTQxNzA1NDdaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM |
||||
MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE |
||||
AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi |
||||
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxuUWq2F6MFQLeFVBB800pjiJv |
||||
pqrpMb8lv5aEOX87slRRkIVe0M/6mSlNvJSSclGindIhsWxaYD4Kend+o+ODhMqT |
||||
Jl7zvVTTluGg8SK22kyJ8DTWHnhnFhpoKVLc5qjgvglOf0h7S9F/tL5AkpGoBq7t |
||||
PkbOJPxKR7bvn34Iux3HgS1uzwZqHSYBcNHuYB6PSgyQJiNLIrA/019YqqUI5R+W |
||||
V/Nb/kkrnsUS+hU6ntAtewus0irO+4fJzBlpN+bvbEBdVHeVmIYhF6ILxtCGWX5l |
||||
lOlDrYNXiff0ksKtEvyUV/NFOASixEBMQ88Un7NGHR8y1NW3fCGiVkOhvaprAgMB |
||||
AAGjZjBkMB0GA1UdDgQWBBT8BlnPk8BS8+JHlIEoCp3sO8jDDjAfBgNVHSMEGDAW |
||||
gBTj0UDC6u67VvpJ2NmXE7vz77nHHTASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud |
||||
DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAZYQg0VUOQ1DGoU0y0TsTzAZ4 |
||||
IEy5xavV7Nma9AJI0ZVFpqGEBjTXjxi7r/co1EREN3bi7QnZfJhU4SGVZ0T7wq+p |
||||
/S3x16DEPEufa3JmP+brBPOOP/5EJX5+2BXMUWuDcY7MAokaAIAudjmVk32FoZgy |
||||
54FkZ+YRillU++7k0ie8EEYE8pN2ABIqNCdHxGEhwEc0wVwB6bBONmcEssYmipUh |
||||
DQH6+sfKBcd+sUMGG3qd79sE7BF9w8bAHhKcBm5eTdEks9jh6H1o0PgBvFP8fFzF |
||||
q89KGuLw7T0n/Khkmrv5cifwmTpg42Ivorv8qk02aeiOAGiMyFFJ38BQtH64LQ== |
||||
-----END CERTIFICATE----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIID2zCCAsOgAwIBAgIURc832yfuirkVrhWhC4O1uBfTZXAwDQYJKoZIhvcNAQEL |
||||
BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ |
||||
BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x |
||||
HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNjA3MTcwNTQ3 |
||||
WhgPMjEyMTA1MTQxNzA1NDdaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM |
||||
MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE |
||||
AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t |
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzKd0JrZR3N0A3C7Gp7sT |
||||
zLurt0pVjAIBh3N+5NsyY7eAHJWA7wRR+JpG4q6MxmYVWsk4MjsnWB0ViCCm+fTY |
||||
a9tFms6lmsjM4fJgIs8/DP+zBEOien7sD3kfddmI4ClODynNv3ODbJKyhzKQEOZ8 |
||||
sdf61yWYuFzayEfNoon6BlqroPv9B0eAsgOFDndPo6vbqAFlrYAyVXx+7hmH7Hv6 |
||||
8RWDaSr0uI62uhvAQeK4a+p9aTSwLcHRh1/7NezW9rzI0/7yzP3w/RS7tevDuacU |
||||
XMr3sH5xEUahGF72qYUVejUlP48fPLrdGK76QZk0M8K2EOyvuNq66P+UMialx+83 |
||||
NwIDAQABo1MwUTAdBgNVHQ4EFgQU49FAwuruu1b6SdjZlxO78++5xx0wHwYDVR0j |
||||
BBgwFoAU49FAwuruu1b6SdjZlxO78++5xx0wDwYDVR0TAQH/BAUwAwEB/zANBgkq |
||||
hkiG9w0BAQsFAAOCAQEADfrsmYBaeV4/MTRVazsey/o0ZhBoLJ+3RFYC6+M2lYB1 |
||||
yT92tbAT3787aHTw/SdFvA11oT+lMDEmBWowzZ1bp/J7tqlqMcmwL4QyhZjp0gmK |
||||
eqDXy2Jui/fOTRzWQ1ka7mR6OTWxxVoIjKVvJ/AysqGCTFMXZXrMthtCuQDG+b85 |
||||
B3ALz6/j0ZFqgKzftCIuY0UnBtDEuKkAa0QkDMHLvcMAw7V/etpQPypCXqmwnc2e |
||||
vvL6cSvakEVE7rErhIeeL+1m2TBSWNrPVIvggLMv655meqkhGQn9uYyiGw6i/2V/ |
||||
ngBAs4gYDvk20Cyg0kxQONmzreAdFzArud+k7FofZw== |
||||
-----END CERTIFICATE----- |
@ -1,126 +0,0 @@ |
||||
-----BEGIN PRIVATE KEY----- |
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC8YRSLAPea6rIG |
||||
tgDxF+q4KVlm5zV5VWyvKf6KjECZC6fHekQkP1sFYhG6+wq+nDT8hf+Em8JYa/oV |
||||
WMi4QDHZkzryJC2rEyukq1Pi9ELBhGfbLw356zP4zCK+/RtiR06B/UOPkQ8/Itz+ |
||||
fTbuU7LrgIA6AT8rDG5kTOuKBvcNWDx02QEeAguZVXSVOG1A6Un8NsL/pFi9tsUU |
||||
qW9jgTA389wHunggAKa+KDPg5HXsqZfG/sioJv3iZw42zvmBaSaQJ+ZtQeVx2zu+ |
||||
OUMWhke5nmr+6ohLqG0R8GwKhW6AxlErKvFZXEKhLTobUAWOExL6ImtqgvYUc8wT |
||||
gvN92pfPAgMBAAECggEBAJ0HN76fcccbOIdLlAFk9G3LWhDjTrnzsYNaOCp5uydY |
||||
heVMUBz/Cvqzwx/gQBaf07NkZ5i81gYrC+5bcgXUzTkW95389mySsGC1yFl5T2RM |
||||
4N3enYHkxA/y6kvWZMtJsXG+EmFMhC8W+qzQ58dG0fBpz3mKrINP+310eSs3nxzp |
||||
MGnAHaawB8KVTIfqsFbVbT+DMShU8KkZSe8HAwEZF0vsD0Epq/IftH3H+gucH8Ny |
||||
5O3/hfvU4CBn0RxJyH239YDyPaf+TeZfJwI361k5se/aDwicj2azFo60uObsV8FT |
||||
DhYxPFB39LT0kKgeo14SrW6USyhv6PEZs/x6dTKyw8ECgYEA3drXVsEwOuVrg8DD |
||||
H8/pfsKS6EXB9Enxs5jzeS2nWR6qjjEo9+Ks4dZTRstlkCe+WSMgeeX9snDCJodJ |
||||
cG/5XDpg5GlrcapRz79zJ7SKcaiaH/EKs7pmcUR+3BanGYB2AWYjwil9yLTv7FB9 |
||||
o08Xx6dEbm/doQlOoTNrmZUcKH8CgYEA2V9JnkJmqVZAyYISRniESZNxHElVd98B |
||||
jR546VeGS41faEyiXZd6vrjubbMkxylsNBxri774g04ki+T3fNSXNDBr1TcOf4do |
||||
XoVhrVk03p2xTt/4tDV5XfefIam11POEVs/H9R5cUeF5aylOP5Wi3tNveSDeqhwW |
||||
RSKfOHuRaLECgYAc46Bi5ak4IiPL9k/yVoqbPQ8QO/UzsGVO873Qq8c87adb+L7S |
||||
+Kt2hQg3EclZ6jL5PH/AH9jXYaOGjNtdTtdz0Q5I8AlTtdANc2q1YuccQc5AFo1E |
||||
NiOc4ER8uF5uDbJQIFLLt8dvWVBcv2Z825HHJ9rbXqnHjIS2rRF34FjYVQKBgGUz |
||||
p+K2p3VPYvpuRHPqyCw5KQAyZEha2y4IceKxjSS/vRuiEjXgwJTrJJaOQSE4d9gL |
||||
I0b8slbvmrRG9bJ4h60Unh+2clmNgVoAX2mFjsfWQyalv/SmsMq+7qeNi8qJVaPV |
||||
ORM1/2VfxFfP805HLHzxk4SheQlZ6kRlyhtR7HEBAoGAMPaMPm0PaPesN6dpwgKD |
||||
HHm4BgniKafmikjkieuVQgtu/Rl/1Eq+haGHIDMQtRn9fD88y1lETEw4o2vXUDjI |
||||
vBFkGE+Mf/Vjg6V1THAGd9XseLgAK2PCvfEDsCYAiyEEVY0hPfmgQwNZxxCt94fE |
||||
fjI21dc+cX9CHXTHyzORnWE= |
||||
-----END PRIVATE KEY----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIIEyDCCA7CgAwIBAgIUaW2ASS9e6nFjnrZ0REfz64o5/zwwDQYJKoZIhvcNAQEL |
||||
BQAwgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw |
||||
CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwKcGFydG5lcjFjYTEm |
||||
MCQGCSqGSIb3DQEJARYXcGFydG5lcjFjYUBwYXJ0bmVyMS5jb20wIBcNMjEwNjA3 |
||||
MTcwNTQ3WhgPMjEyMTA1MTQxNzA1NDdaMIGLMQswCQYDVQQGEwJVUzELMAkGA1UE |
||||
CAwCQ0ExDDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMxDTALBgNVBAsMBHJvb3Qx |
||||
GDAWBgNVBAMMD3BhcnRuZXIxY2xpZW50MTErMCkGCSqGSIb3DQEJARYccGFydG5l |
||||
cjFjbGllbnQxQHBhcnRuZXIxLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC |
||||
AQoCggEBALxhFIsA95rqsga2APEX6rgpWWbnNXlVbK8p/oqMQJkLp8d6RCQ/WwVi |
||||
Ebr7Cr6cNPyF/4Sbwlhr+hVYyLhAMdmTOvIkLasTK6SrU+L0QsGEZ9svDfnrM/jM |
||||
Ir79G2JHToH9Q4+RDz8i3P59Nu5TsuuAgDoBPysMbmRM64oG9w1YPHTZAR4CC5lV |
||||
dJU4bUDpSfw2wv+kWL22xRSpb2OBMDfz3Ae6eCAApr4oM+Dkdeypl8b+yKgm/eJn |
||||
DjbO+YFpJpAn5m1B5XHbO745QxaGR7meav7qiEuobRHwbAqFboDGUSsq8VlcQqEt |
||||
OhtQBY4TEvoia2qC9hRzzBOC833al88CAwEAAaOCASgwggEkMBEGCWCGSAGG+EIB |
||||
AQQEAwIGwDAdBgNVHQ4EFgQUteJ5GVlEpzaoonh4YXoc+1103lowCQYDVR0TBAIw |
||||
ADAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC |
||||
MIG1BgNVHSMEga0wgaqAFIHwIk3E9e67+YQOYPX6s+Ej+o3koXykejB4MQswCQYD |
||||
VQQGEwJVUzELMAkGA1UECAwCQ0ExDDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMx |
||||
DTALBgNVBAsMBHJvb3QxEDAOBgNVBAMMB2ludGVyY2ExIDAeBgkqhkiG9w0BCQEW |
||||
EWludGVyY2FAYWRtaW4uY29tghQ2eIbpK1yId7NsCpf640xyI9buOjANBgkqhkiG |
||||
9w0BAQsFAAOCAQEABiqi7zOT55MIm5rbCGwe00LvAghbkfUitDEEotRjvF8E/fvA |
||||
rwnbqgBDbetYtI+88ml3NhdU2B3qZA8Z/KXnjJA+vmNmpdRVYGnl8BdKjqTUl+QV |
||||
d1vm0IbOID33gOKhaxba+Tbq7WYnzCMltqOzqtjgCUmJamacGR5sDYvz057vWEM/ |
||||
19Gw1agAAY+sb1Vx7BwM6A81iKP7rf1z0jKZTVMc8bW1IOZJxqDsMosnuSAyQwMK |
||||
4Bwt6CEbWjknRZ/jTioM0C2HFpWXz51SyNwP583s60OVqf7/NYb1LC3lWrpWL7yf |
||||
rsHBob8jsrkCRHbRHIjXjio3l29ObL5AfQm3Ig== |
||||
-----END CERTIFICATE----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIID8DCCAtigAwIBAgIUNniG6StciHezbAqX+uNMciPW7jowDQYJKoZIhvcNAQEL |
||||
BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ |
||||
BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ |
||||
KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA2MDcxNzA1NDdaGA8y |
||||
MTIxMDUxNDE3MDU0N1owgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG |
||||
A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK |
||||
cGFydG5lcjFjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcjFjYUBwYXJ0bmVyMS5j |
||||
b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDR8KbDV1MbtC1Siuo2 |
||||
pbOU6eMRaNyDdlhcz48FY+mKGsUEAePceFJTvh1w9gXwt/A26CO02BVdTPYowudf |
||||
Qkl9v+qSRIKXgKz1fkNUW4xYKl7KsgABi/zpgY/bM3CarBcBan9VKWapgx680Aj2 |
||||
bv99ODNqZTH9Iwdq2IrHNBplLp2TmFao7oKz+LeMV6ZrdfY1THf1AuprD86Ccxfa |
||||
9YAyuMI4t7BKqmIqMuDKSSykXuEDY/CCDWw8o/0rg6baoM4bKzipv/4oqaegM3MB |
||||
8vt979rx4PGH69+/JSMt7wL3SQbkQtMNODZyGM/HW+TsPAFYfHPsURVRezFpOB7G |
||||
OoTdAgMBAAGjZjBkMB0GA1UdDgQWBBSB8CJNxPXuu/mEDmD1+rPhI/qN5DAfBgNV |
||||
HSMEGDAWgBT8BlnPk8BS8+JHlIEoCp3sO8jDDjASBgNVHRMBAf8ECDAGAQH/AgEA |
||||
MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAKb5S3NTSxSJrI5Mk |
||||
EKoULvy7vKh+W/o5wDKm8ILwJHn76HFyq3Nl0zYdoshROnLG8gL69rMWZgTg+Fsl |
||||
teX8pNvLEQV7Asx5Yvn2oFBQqRevwGsg2z48et5SIq5pDYeThwUMbdrGuhkEkizW |
||||
ecBUN8j7auRLSpx5ornl9zFx5bvsVb4Dy/rIMVnPiw3VniOAOplGIJOm/TiPxTR0 |
||||
qyzdHljsRbM0uyw81QkeskuJWCpmKTFZxfV1Jww3ScKApNY8WFW+iuarWBvRTq7l |
||||
3AxXcE11ms92rnZw3vFvrIfM6WlE7Idb0rlRK69e73j40eBtJN5i6L7IPJ7Uht+N |
||||
mLfQvw== |
||||
-----END CERTIFICATE----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIID6jCCAtKgAwIBAgIUTwPfI+2FxYq0V6uukemLf67qANowDQYJKoZIhvcNAQEL |
||||
BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ |
||||
BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x |
||||
HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNjA3MTcwNTQ3 |
||||
WhgPMjEyMTA1MTQxNzA1NDdaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM |
||||
MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE |
||||
AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi |
||||
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxuUWq2F6MFQLeFVBB800pjiJv |
||||
pqrpMb8lv5aEOX87slRRkIVe0M/6mSlNvJSSclGindIhsWxaYD4Kend+o+ODhMqT |
||||
Jl7zvVTTluGg8SK22kyJ8DTWHnhnFhpoKVLc5qjgvglOf0h7S9F/tL5AkpGoBq7t |
||||
PkbOJPxKR7bvn34Iux3HgS1uzwZqHSYBcNHuYB6PSgyQJiNLIrA/019YqqUI5R+W |
||||
V/Nb/kkrnsUS+hU6ntAtewus0irO+4fJzBlpN+bvbEBdVHeVmIYhF6ILxtCGWX5l |
||||
lOlDrYNXiff0ksKtEvyUV/NFOASixEBMQ88Un7NGHR8y1NW3fCGiVkOhvaprAgMB |
||||
AAGjZjBkMB0GA1UdDgQWBBT8BlnPk8BS8+JHlIEoCp3sO8jDDjAfBgNVHSMEGDAW |
||||
gBTj0UDC6u67VvpJ2NmXE7vz77nHHTASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud |
||||
DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAZYQg0VUOQ1DGoU0y0TsTzAZ4 |
||||
IEy5xavV7Nma9AJI0ZVFpqGEBjTXjxi7r/co1EREN3bi7QnZfJhU4SGVZ0T7wq+p |
||||
/S3x16DEPEufa3JmP+brBPOOP/5EJX5+2BXMUWuDcY7MAokaAIAudjmVk32FoZgy |
||||
54FkZ+YRillU++7k0ie8EEYE8pN2ABIqNCdHxGEhwEc0wVwB6bBONmcEssYmipUh |
||||
DQH6+sfKBcd+sUMGG3qd79sE7BF9w8bAHhKcBm5eTdEks9jh6H1o0PgBvFP8fFzF |
||||
q89KGuLw7T0n/Khkmrv5cifwmTpg42Ivorv8qk02aeiOAGiMyFFJ38BQtH64LQ== |
||||
-----END CERTIFICATE----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIID2zCCAsOgAwIBAgIURc832yfuirkVrhWhC4O1uBfTZXAwDQYJKoZIhvcNAQEL |
||||
BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ |
||||
BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x |
||||
HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNjA3MTcwNTQ3 |
||||
WhgPMjEyMTA1MTQxNzA1NDdaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM |
||||
MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE |
||||
AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t |
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzKd0JrZR3N0A3C7Gp7sT |
||||
zLurt0pVjAIBh3N+5NsyY7eAHJWA7wRR+JpG4q6MxmYVWsk4MjsnWB0ViCCm+fTY |
||||
a9tFms6lmsjM4fJgIs8/DP+zBEOien7sD3kfddmI4ClODynNv3ODbJKyhzKQEOZ8 |
||||
sdf61yWYuFzayEfNoon6BlqroPv9B0eAsgOFDndPo6vbqAFlrYAyVXx+7hmH7Hv6 |
||||
8RWDaSr0uI62uhvAQeK4a+p9aTSwLcHRh1/7NezW9rzI0/7yzP3w/RS7tevDuacU |
||||
XMr3sH5xEUahGF72qYUVejUlP48fPLrdGK76QZk0M8K2EOyvuNq66P+UMialx+83 |
||||
NwIDAQABo1MwUTAdBgNVHQ4EFgQU49FAwuruu1b6SdjZlxO78++5xx0wHwYDVR0j |
||||
BBgwFoAU49FAwuruu1b6SdjZlxO78++5xx0wDwYDVR0TAQH/BAUwAwEB/zANBgkq |
||||
hkiG9w0BAQsFAAOCAQEADfrsmYBaeV4/MTRVazsey/o0ZhBoLJ+3RFYC6+M2lYB1 |
||||
yT92tbAT3787aHTw/SdFvA11oT+lMDEmBWowzZ1bp/J7tqlqMcmwL4QyhZjp0gmK |
||||
eqDXy2Jui/fOTRzWQ1ka7mR6OTWxxVoIjKVvJ/AysqGCTFMXZXrMthtCuQDG+b85 |
||||
B3ALz6/j0ZFqgKzftCIuY0UnBtDEuKkAa0QkDMHLvcMAw7V/etpQPypCXqmwnc2e |
||||
vvL6cSvakEVE7rErhIeeL+1m2TBSWNrPVIvggLMv655meqkhGQn9uYyiGw6i/2V/ |
||||
ngBAs4gYDvk20Cyg0kxQONmzreAdFzArud+k7FofZw== |
||||
-----END CERTIFICATE----- |
@ -1,27 +0,0 @@ |
||||
-----BEGIN X509 CRL----- |
||||
MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCVVMxCzAJBgNV |
||||
BAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJBgNVBAoMAk1DMQ0wCwYDVQQLDARyb290 |
||||
MRMwEQYDVQQDDApwYXJ0bmVyMWNhMSYwJAYJKoZIhvcNAQkBFhdwYXJ0bmVyMWNh |
||||
QHBhcnRuZXIxLmNvbRcNMjEwNjA3MTcwNjAwWhcNMjIwNjA3MTcwNjAwWjAnMCUC |
||||
FGltgEkvXupxY562dERH8+uKOf89Fw0yMTA2MDcxNzA2MDBaoA4wDDAKBgNVHRQE |
||||
AwIBADANBgkqhkiG9w0BAQsFAAOCAQEABF/7Kq+byYi/bRoftL8xqgSGcaLVuCOF |
||||
BZVZXDKjyYfISwBqbvPSqtIvnFO1ewicgD7dNIZwWcQ9Kx7OOz4BA6Pe8YPtiBfp |
||||
HZMabT8BS2eLePvViGumY7PTo3oIk3yXylOtzMDo59WQhCH/0vp5xjzJC+VFex/W |
||||
p/an5ii1y3Q1FpEZNer6jpU0xJEJ2mCaGT/zuj6Mg1awWqmmYce3BahZeCNj8Wyx |
||||
GIy8bGUjOdJyp99rAF9euCZ45pAjI12sg9lhPIVkp3Wnoy3La4Yj219Elc3MbJvF |
||||
8GEFEmZ0Lm5Ze/EG5VyLB+wRpggeSJTc20i/eGWdaWg8AEukCgMdCg== |
||||
-----END X509 CRL----- |
||||
-----BEGIN X509 CRL----- |
||||
MIICLDCCARQCAQEwDQYJKoZIhvcNAQELBQAwgYExCzAJBgNVBAYTAlVTMQswCQYD |
||||
VQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9v |
||||
dDETMBEGA1UEAwwKcGFydG5lcjJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcjJj |
||||
YUBwYXJ0bmVyMi5jb20XDTIxMDYwNzE3MDYwMFoXDTIyMDYwNzE3MDYwMFowTjAl |
||||
AhRpbYBJL17qcWOetnRER/Prijn/PRcNMjEwNjA3MTcwNjAwWjAlAhR+2Aa1zeVQ |
||||
jbXFGnXFu53h4vZEahcNMjEwNjA3MTcwNjAwWqAOMAwwCgYDVR0UBAMCAQEwDQYJ |
||||
KoZIhvcNAQELBQADggEBAFXQOMk+6FDP8bm9TGK079IHojhooipo+9x3I1y/kUhH |
||||
XY7xuyTXOvzv14//xenDuryIjSAC8pyqbls+DcUXkmGZ/nIWugtMykGLNgqqo/Oe |
||||
pfoUSXRJP7CtvfHa4ejfr3q1t5MXfM3nqBQumu65slWjDFtE6mZF4ANcsIlsNQ10 |
||||
GTkDIdDHgUWxmZlBzTkoofvYspixuUptpJfl5eei9SDA+T1uADKnjARkxVv8xeYi |
||||
QwTp6jVYq6YKc9z0l1UMadnFQz8osk7QNypWnsrD0+iBB1if8ikJwy+8BWayTkgQ |
||||
tWLFT4n/c1m/wYzSclvZUUOxkkkE4Q9fZ3ReCADC+bQ= |
||||
-----END X509 CRL----- |
Binary file not shown.
Binary file not shown.
@ -1,6 +0,0 @@ |
||||
|
||||
name = NSScrypto-partner2client1 |
||||
nssSecmodDirectory = ./src/test/resources/keystore/partner2client1/nssdb |
||||
nssDbMode = readOnly |
||||
nssModule = keystore |
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@ |
||||
test123 |
@ -1,70 +0,0 @@ |
||||
-----BEGIN CERTIFICATE----- |
||||
MIID8DCCAtigAwIBAgIUNniG6StciHezbAqX+uNMciPW7jswDQYJKoZIhvcNAQEL |
||||
BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ |
||||
BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ |
||||
KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA2MDcxNzA1NDlaGA8y |
||||
MTIxMDUxNDE3MDU0OVowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG |
||||
A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK |
||||
cGFydG5lcjJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcjJjYUBwYXJ0bmVyMi5j |
||||
b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLvHvIuFFYmNYEA6P2 |
||||
/RB3LBDpxbnjl7SU4KCWcfBxQ1guw3aG/HzjenKt3m6UmmESFSh0k4/a/s9m4z/M |
||||
ubVqrm0ll2HvyodetFL40jLgSCIbP3taCIhLptaOCB2P6keYEfjGdb5YTNMgCqYk |
||||
NYA+dgXtw1VMJvI7aRpmVOIPtQx/nqncigYzxykGlTbeusSPAGp7CAmxTZSJUFLI |
||||
ig0ReaKSopiQE2j/ljJXFK26sMlkq3Lw41E4fPju+PBeubeb6eT8fzhn0IaCgTeO |
||||
cZgKzVUv3MsrrKfDHXUhGAspKBGDkqkrogZ6UYcvyCLfnRM0vVGc1L7oaFnMMZ1m |
||||
NYRpAgMBAAGjZjBkMB0GA1UdDgQWBBSsXIVGVfgo124o7djQsYtrkYPWYzAfBgNV |
||||
HSMEGDAWgBT8BlnPk8BS8+JHlIEoCp3sO8jDDjASBgNVHRMBAf8ECDAGAQH/AgEA |
||||
MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEABSHI1SgQ1FBWmPRZ |
||||
nXDspyvbvPsjk/p6erUVGGuDyy/F2rJldz7musNCL5ijAmlQfYPNMNoLU1BR+fAl |
||||
WSYfdjL1mMygXtj/KlaNqM5hQMUfyYa4Yk1ODaScl+wfIsSmzTSl/j4fMf58GYpr |
||||
9rssVveQrFAipeWhxgGqQNJooAbqmZKE4tePhKzrsH+B2hDEUnFptkasnQEkQQEZ |
||||
rSzJlU72U8p3Gwq9t9rKYoBLSr0yoBbh4fdFcPsuN/mZS6TNEu1Uc4ui9eWheGTM |
||||
RCNGehiXAczfIhf9WfMfyNhp5/pZc2nTeV/LsSjuCFXUdoL5rAESPcHBc56vXtcV |
||||
1ywC0A== |
||||
-----END CERTIFICATE----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIID6jCCAtKgAwIBAgIUTwPfI+2FxYq0V6uukemLf67qANowDQYJKoZIhvcNAQEL |
||||
BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ |
||||
BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x |
||||
HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNjA3MTcwNTQ3 |
||||
WhgPMjEyMTA1MTQxNzA1NDdaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM |
||||
MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE |
||||
AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi |
||||
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxuUWq2F6MFQLeFVBB800pjiJv |
||||
pqrpMb8lv5aEOX87slRRkIVe0M/6mSlNvJSSclGindIhsWxaYD4Kend+o+ODhMqT |
||||
Jl7zvVTTluGg8SK22kyJ8DTWHnhnFhpoKVLc5qjgvglOf0h7S9F/tL5AkpGoBq7t |
||||
PkbOJPxKR7bvn34Iux3HgS1uzwZqHSYBcNHuYB6PSgyQJiNLIrA/019YqqUI5R+W |
||||
V/Nb/kkrnsUS+hU6ntAtewus0irO+4fJzBlpN+bvbEBdVHeVmIYhF6ILxtCGWX5l |
||||
lOlDrYNXiff0ksKtEvyUV/NFOASixEBMQ88Un7NGHR8y1NW3fCGiVkOhvaprAgMB |
||||
AAGjZjBkMB0GA1UdDgQWBBT8BlnPk8BS8+JHlIEoCp3sO8jDDjAfBgNVHSMEGDAW |
||||
gBTj0UDC6u67VvpJ2NmXE7vz77nHHTASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud |
||||
DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAZYQg0VUOQ1DGoU0y0TsTzAZ4 |
||||
IEy5xavV7Nma9AJI0ZVFpqGEBjTXjxi7r/co1EREN3bi7QnZfJhU4SGVZ0T7wq+p |
||||
/S3x16DEPEufa3JmP+brBPOOP/5EJX5+2BXMUWuDcY7MAokaAIAudjmVk32FoZgy |
||||
54FkZ+YRillU++7k0ie8EEYE8pN2ABIqNCdHxGEhwEc0wVwB6bBONmcEssYmipUh |
||||
DQH6+sfKBcd+sUMGG3qd79sE7BF9w8bAHhKcBm5eTdEks9jh6H1o0PgBvFP8fFzF |
||||
q89KGuLw7T0n/Khkmrv5cifwmTpg42Ivorv8qk02aeiOAGiMyFFJ38BQtH64LQ== |
||||
-----END CERTIFICATE----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIID2zCCAsOgAwIBAgIURc832yfuirkVrhWhC4O1uBfTZXAwDQYJKoZIhvcNAQEL |
||||
BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ |
||||
BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x |
||||
HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNjA3MTcwNTQ3 |
||||
WhgPMjEyMTA1MTQxNzA1NDdaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM |
||||
MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE |
||||
AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t |
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzKd0JrZR3N0A3C7Gp7sT |
||||
zLurt0pVjAIBh3N+5NsyY7eAHJWA7wRR+JpG4q6MxmYVWsk4MjsnWB0ViCCm+fTY |
||||
a9tFms6lmsjM4fJgIs8/DP+zBEOien7sD3kfddmI4ClODynNv3ODbJKyhzKQEOZ8 |
||||
sdf61yWYuFzayEfNoon6BlqroPv9B0eAsgOFDndPo6vbqAFlrYAyVXx+7hmH7Hv6 |
||||
8RWDaSr0uI62uhvAQeK4a+p9aTSwLcHRh1/7NezW9rzI0/7yzP3w/RS7tevDuacU |
||||
XMr3sH5xEUahGF72qYUVejUlP48fPLrdGK76QZk0M8K2EOyvuNq66P+UMialx+83 |
||||
NwIDAQABo1MwUTAdBgNVHQ4EFgQU49FAwuruu1b6SdjZlxO78++5xx0wHwYDVR0j |
||||
BBgwFoAU49FAwuruu1b6SdjZlxO78++5xx0wDwYDVR0TAQH/BAUwAwEB/zANBgkq |
||||
hkiG9w0BAQsFAAOCAQEADfrsmYBaeV4/MTRVazsey/o0ZhBoLJ+3RFYC6+M2lYB1 |
||||
yT92tbAT3787aHTw/SdFvA11oT+lMDEmBWowzZ1bp/J7tqlqMcmwL4QyhZjp0gmK |
||||
eqDXy2Jui/fOTRzWQ1ka7mR6OTWxxVoIjKVvJ/AysqGCTFMXZXrMthtCuQDG+b85 |
||||
B3ALz6/j0ZFqgKzftCIuY0UnBtDEuKkAa0QkDMHLvcMAw7V/etpQPypCXqmwnc2e |
||||
vvL6cSvakEVE7rErhIeeL+1m2TBSWNrPVIvggLMv655meqkhGQn9uYyiGw6i/2V/ |
||||
ngBAs4gYDvk20Cyg0kxQONmzreAdFzArud+k7FofZw== |
||||
-----END CERTIFICATE----- |
@ -1,126 +0,0 @@ |
||||
-----BEGIN PRIVATE KEY----- |
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDGcHX9nWsO3oQy |
||||
9HlcTQAA9RxCpVqi5MmBG2HuTipppBdXphGyhQggpD1rL5I26vdq1FIuPBlFI1pg |
||||
Hd/hw7FOr5HuQ12GZpmmPW5KIbEzeY0MVJNXOw+iUuoaQNHLQSKtV5ZOmIJURIWE |
||||
0tjicDOewW/yR9MMStOQladn7WICwwfpgLQeX9EkZqko4iOK9K6ZKUeyRf9kI/86 |
||||
2M7/DAi0pxvaBGcW0F9XmBlqQu7Ma6q0fyR1qf2q3OZL3mSWuNV8S4hYyPqgKAce |
||||
s5w7zzRSNaeGX644RWU1XY8ze6Zik61aRLI2clHrI8wta8HDCdV1GvHvPj1Y7kqB |
||||
xDg0yBqpAgMBAAECggEBAJ2ipshSLcKBFylXNbUR4efgzpNOwaJW9o+eDfx9kYmb |
||||
9YMGBFb5AMzVS4kDIDaKDwOJKMNbsINQozFpafjxOL+WDunkD759cJ8ze5JeE2Md |
||||
suNRqD4KR9Ad56P1S/MXihGDW36R/i4sxJgP2oR+tzLs3R3s2oWQR2I6z+JqG4qu |
||||
tf4gDP6UIrJOirkn7TQD1VQi+8HMWx1BSER6yR86tKKTnwIlgVh0mowWXKXsB5aS |
||||
Y38Kfu+OG8FWAkCaVjFZdvg6xQcjI8MEmRqumPPf3OETrE/D6u4+qvpy1D7b8nsf |
||||
utYgv1mKYqkU0wvdDt6WTrPn/0fteLw6yMaoPmhim1ECgYEA9eFj889HojPzF7fx |
||||
67yWICah9vqd9OPYIPOtQ5rrgnTkiSxk1QyAG6i2Jl15sr8lGuVcVhTyXk/M75Ct |
||||
4gWanwbUI6khDKOM3kVN1nx/kvYFrzSuWkswB55OBEbDY/qhGu73ERNaIJdJVrY+ |
||||
p5wn1sbT5I1fqAuKwpj2A5B++x0CgYEAzps6ZujBOq896QoiR4MmLEI6rzqprIsL |
||||
LHCWnGtwn4SJhPwSUD3yDbyjA5rpodjWatLtX/MV7hWlWARj/ERSOLZlU2rCPNwO |
||||
gRgGnpGcSZYhVs7WSa675OEhjmhdUmqcl88pO+14+WLN9Bj8ECqkxyD+srUe5zxo |
||||
IisJYBK/e/0CgYADI+bH5VzP2IQBSIshbJ4qOPQWmGrOBt7qxNHwrBjX6LBGhDeh |
||||
dPBp6gSxhr4YJ1LM/iLowom55KEEaj+eRF4OK+MntXBDng8dg5sT4zEp6lR2QWD8 |
||||
rDsnzcDHUzQJodjO5EBpimq7QdNg9SDluRvVJWLtZ1TSa5tREu0JbJ4CjQKBgADK |
||||
kWexfoP2BdutoUH625uRyV3AcMPraGiMKdeBhdXmkQxEVuGdyx6IWWt7HWf0R6Xz |
||||
FtumN7BIvvBeW++sZ1A2Sp8OKp5HDXsrF2NmFV4myAvoEOQJWkjfH9zGw4y8QctH |
||||
DNZg63SxDy7fJZ/+OdFVbARNM0gZcCCpX4jRqZAVAoGBALz0ELUMj1s42+G6UAZ3 |
||||
toBHOBI7o/4R7hRoim21dmpmyz1XJrL17wIZO4vvftNxYI4n/0U0QMFopaakMrCi |
||||
E0/I9sU9R/4MyOK0VCPtkeuxznp3xkX8zoNeewK+9EGiEZFcOpsbyRSmwjLCyTKU |
||||
G8HIMfRI71A7qj+5Me3q62K2 |
||||
-----END PRIVATE KEY----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIIEyDCCA7CgAwIBAgIUftgGtc3lUI21xRp1xbud4eL2RGkwDQYJKoZIhvcNAQEL |
||||
BQAwgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDU0ZPMQsw |
||||
CQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwKcGFydG5lcjJjYTEm |
||||
MCQGCSqGSIb3DQEJARYXcGFydG5lcjJjYUBwYXJ0bmVyMi5jb20wIBcNMjEwNjA3 |
||||
MTcwNTQ5WhgPMjEyMTA1MTQxNzA1NDlaMIGLMQswCQYDVQQGEwJVUzELMAkGA1UE |
||||
CAwCQ0ExDDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMxDTALBgNVBAsMBHJvb3Qx |
||||
GDAWBgNVBAMMD3BhcnRuZXIyY2xpZW50MTErMCkGCSqGSIb3DQEJARYccGFydG5l |
||||
cjJjbGllbnQxQHBhcnRuZXIyLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC |
||||
AQoCggEBAMZwdf2daw7ehDL0eVxNAAD1HEKlWqLkyYEbYe5OKmmkF1emEbKFCCCk |
||||
PWsvkjbq92rUUi48GUUjWmAd3+HDsU6vke5DXYZmmaY9bkohsTN5jQxUk1c7D6JS |
||||
6hpA0ctBIq1Xlk6YglREhYTS2OJwM57Bb/JH0wxK05CVp2ftYgLDB+mAtB5f0SRm |
||||
qSjiI4r0rpkpR7JF/2Qj/zrYzv8MCLSnG9oEZxbQX1eYGWpC7sxrqrR/JHWp/arc |
||||
5kveZJa41XxLiFjI+qAoBx6znDvPNFI1p4ZfrjhFZTVdjzN7pmKTrVpEsjZyUesj |
||||
zC1rwcMJ1XUa8e8+PVjuSoHEODTIGqkCAwEAAaOCASgwggEkMBEGCWCGSAGG+EIB |
||||
AQQEAwIGwDAdBgNVHQ4EFgQUojh+oPjTK6xgPMtbz+XEy4tl7iwwCQYDVR0TBAIw |
||||
ADAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC |
||||
MIG1BgNVHSMEga0wgaqAFKxchUZV+CjXbijt2NCxi2uRg9ZjoXykejB4MQswCQYD |
||||
VQQGEwJVUzELMAkGA1UECAwCQ0ExDDAKBgNVBAcMA1NGTzELMAkGA1UECgwCTUMx |
||||
DTALBgNVBAsMBHJvb3QxEDAOBgNVBAMMB2ludGVyY2ExIDAeBgkqhkiG9w0BCQEW |
||||
EWludGVyY2FAYWRtaW4uY29tghQ2eIbpK1yId7NsCpf640xyI9buOzANBgkqhkiG |
||||
9w0BAQsFAAOCAQEAbhEisOmfG5/Ks7MHu9cl17R9ISIFbMVv4wBiztLt2tWv5o5P |
||||
ul9DG2s9tBuOzs3xB4v2aZg7H2kPnUPDaTe7z5Ulc5+IyHDGSdsBzBqONH3sElue |
||||
HyZo1cOXU6nBIineYGYc0Bs9QnLRA0dmaYWZyjqB5S5GCs9Z5mk/JWzA1d110uio |
||||
RzStTpbSFlYvBpLTPShLREfFp56SMHDEaHBIoVERzfULvQwZLDsIAyqE/W+WE0FF |
||||
Lxhz3jxvztoOE6Sr5cmOp7nuwo3ALlWOjFCHOZRs/1qDDnIgXFnPKsZohtvVK2TG |
||||
a+/zW8wRyAAo4FgBTfqICXpOtK+Yg479Aj2GbQ== |
||||
-----END CERTIFICATE----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIID8DCCAtigAwIBAgIUNniG6StciHezbAqX+uNMciPW7jswDQYJKoZIhvcNAQEL |
||||
BQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ |
||||
BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRAwDgYDVQQDDAdpbnRlcmNhMSAwHgYJ |
||||
KoZIhvcNAQkBFhFpbnRlcmNhQGFkbWluLmNvbTAgFw0yMTA2MDcxNzA1NDlaGA8y |
||||
MTIxMDUxNDE3MDU0OVowgYExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoG |
||||
A1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDETMBEGA1UEAwwK |
||||
cGFydG5lcjJjYTEmMCQGCSqGSIb3DQEJARYXcGFydG5lcjJjYUBwYXJ0bmVyMi5j |
||||
b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDLvHvIuFFYmNYEA6P2 |
||||
/RB3LBDpxbnjl7SU4KCWcfBxQ1guw3aG/HzjenKt3m6UmmESFSh0k4/a/s9m4z/M |
||||
ubVqrm0ll2HvyodetFL40jLgSCIbP3taCIhLptaOCB2P6keYEfjGdb5YTNMgCqYk |
||||
NYA+dgXtw1VMJvI7aRpmVOIPtQx/nqncigYzxykGlTbeusSPAGp7CAmxTZSJUFLI |
||||
ig0ReaKSopiQE2j/ljJXFK26sMlkq3Lw41E4fPju+PBeubeb6eT8fzhn0IaCgTeO |
||||
cZgKzVUv3MsrrKfDHXUhGAspKBGDkqkrogZ6UYcvyCLfnRM0vVGc1L7oaFnMMZ1m |
||||
NYRpAgMBAAGjZjBkMB0GA1UdDgQWBBSsXIVGVfgo124o7djQsYtrkYPWYzAfBgNV |
||||
HSMEGDAWgBT8BlnPk8BS8+JHlIEoCp3sO8jDDjASBgNVHRMBAf8ECDAGAQH/AgEA |
||||
MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEABSHI1SgQ1FBWmPRZ |
||||
nXDspyvbvPsjk/p6erUVGGuDyy/F2rJldz7musNCL5ijAmlQfYPNMNoLU1BR+fAl |
||||
WSYfdjL1mMygXtj/KlaNqM5hQMUfyYa4Yk1ODaScl+wfIsSmzTSl/j4fMf58GYpr |
||||
9rssVveQrFAipeWhxgGqQNJooAbqmZKE4tePhKzrsH+B2hDEUnFptkasnQEkQQEZ |
||||
rSzJlU72U8p3Gwq9t9rKYoBLSr0yoBbh4fdFcPsuN/mZS6TNEu1Uc4ui9eWheGTM |
||||
RCNGehiXAczfIhf9WfMfyNhp5/pZc2nTeV/LsSjuCFXUdoL5rAESPcHBc56vXtcV |
||||
1ywC0A== |
||||
-----END CERTIFICATE----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIID6jCCAtKgAwIBAgIUTwPfI+2FxYq0V6uukemLf67qANowDQYJKoZIhvcNAQEL |
||||
BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ |
||||
BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x |
||||
HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNjA3MTcwNTQ3 |
||||
WhgPMjEyMTA1MTQxNzA1NDdaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM |
||||
MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEQMA4GA1UE |
||||
AwwHaW50ZXJjYTEgMB4GCSqGSIb3DQEJARYRaW50ZXJjYUBhZG1pbi5jb20wggEi |
||||
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxuUWq2F6MFQLeFVBB800pjiJv |
||||
pqrpMb8lv5aEOX87slRRkIVe0M/6mSlNvJSSclGindIhsWxaYD4Kend+o+ODhMqT |
||||
Jl7zvVTTluGg8SK22kyJ8DTWHnhnFhpoKVLc5qjgvglOf0h7S9F/tL5AkpGoBq7t |
||||
PkbOJPxKR7bvn34Iux3HgS1uzwZqHSYBcNHuYB6PSgyQJiNLIrA/019YqqUI5R+W |
||||
V/Nb/kkrnsUS+hU6ntAtewus0irO+4fJzBlpN+bvbEBdVHeVmIYhF6ILxtCGWX5l |
||||
lOlDrYNXiff0ksKtEvyUV/NFOASixEBMQ88Un7NGHR8y1NW3fCGiVkOhvaprAgMB |
||||
AAGjZjBkMB0GA1UdDgQWBBT8BlnPk8BS8+JHlIEoCp3sO8jDDjAfBgNVHSMEGDAW |
||||
gBTj0UDC6u67VvpJ2NmXE7vz77nHHTASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1Ud |
||||
DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAZYQg0VUOQ1DGoU0y0TsTzAZ4 |
||||
IEy5xavV7Nma9AJI0ZVFpqGEBjTXjxi7r/co1EREN3bi7QnZfJhU4SGVZ0T7wq+p |
||||
/S3x16DEPEufa3JmP+brBPOOP/5EJX5+2BXMUWuDcY7MAokaAIAudjmVk32FoZgy |
||||
54FkZ+YRillU++7k0ie8EEYE8pN2ABIqNCdHxGEhwEc0wVwB6bBONmcEssYmipUh |
||||
DQH6+sfKBcd+sUMGG3qd79sE7BF9w8bAHhKcBm5eTdEks9jh6H1o0PgBvFP8fFzF |
||||
q89KGuLw7T0n/Khkmrv5cifwmTpg42Ivorv8qk02aeiOAGiMyFFJ38BQtH64LQ== |
||||
-----END CERTIFICATE----- |
||||
-----BEGIN CERTIFICATE----- |
||||
MIID2zCCAsOgAwIBAgIURc832yfuirkVrhWhC4O1uBfTZXAwDQYJKoZIhvcNAQEL |
||||
BQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANTRk8xCzAJ |
||||
BgNVBAoMAk1DMQ0wCwYDVQQLDARyb290MRUwEwYDVQQDDAxyb290Y2EuYWRtaW4x |
||||
HzAdBgkqhkiG9w0BCQEWEHJvb3RjYUBhZG1pbi5jb20wIBcNMjEwNjA3MTcwNTQ3 |
||||
WhgPMjEyMTA1MTQxNzA1NDdaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEM |
||||
MAoGA1UEBwwDU0ZPMQswCQYDVQQKDAJNQzENMAsGA1UECwwEcm9vdDEVMBMGA1UE |
||||
AwwMcm9vdGNhLmFkbWluMR8wHQYJKoZIhvcNAQkBFhByb290Y2FAYWRtaW4uY29t |
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzKd0JrZR3N0A3C7Gp7sT |
||||
zLurt0pVjAIBh3N+5NsyY7eAHJWA7wRR+JpG4q6MxmYVWsk4MjsnWB0ViCCm+fTY |
||||
a9tFms6lmsjM4fJgIs8/DP+zBEOien7sD3kfddmI4ClODynNv3ODbJKyhzKQEOZ8 |
||||
sdf61yWYuFzayEfNoon6BlqroPv9B0eAsgOFDndPo6vbqAFlrYAyVXx+7hmH7Hv6 |
||||
8RWDaSr0uI62uhvAQeK4a+p9aTSwLcHRh1/7NezW9rzI0/7yzP3w/RS7tevDuacU |
||||
XMr3sH5xEUahGF72qYUVejUlP48fPLrdGK76QZk0M8K2EOyvuNq66P+UMialx+83 |
||||
NwIDAQABo1MwUTAdBgNVHQ4EFgQU49FAwuruu1b6SdjZlxO78++5xx0wHwYDVR0j |
||||
BBgwFoAU49FAwuruu1b6SdjZlxO78++5xx0wDwYDVR0TAQH/BAUwAwEB/zANBgkq |
||||
hkiG9w0BAQsFAAOCAQEADfrsmYBaeV4/MTRVazsey/o0ZhBoLJ+3RFYC6+M2lYB1 |
||||
yT92tbAT3787aHTw/SdFvA11oT+lMDEmBWowzZ1bp/J7tqlqMcmwL4QyhZjp0gmK |
||||
eqDXy2Jui/fOTRzWQ1ka7mR6OTWxxVoIjKVvJ/AysqGCTFMXZXrMthtCuQDG+b85 |
||||
B3ALz6/j0ZFqgKzftCIuY0UnBtDEuKkAa0QkDMHLvcMAw7V/etpQPypCXqmwnc2e |
||||
vvL6cSvakEVE7rErhIeeL+1m2TBSWNrPVIvggLMv655meqkhGQn9uYyiGw6i/2V/ |
||||
ngBAs4gYDvk20Cyg0kxQONmzreAdFzArud+k7FofZw== |
||||
-----END CERTIFICATE----- |
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@ |
||||
mock-maker-inline |
Loading…
Reference in new issue