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