Support encrypted PKCS8 private keys in SSL bundles
Properties `ssl.bundle.pem.mybundle.keystore.private-key-password` and `ssl.bundle.pem.mybundle.truststore.private-key-password` have been added for configuring the password required to decrypt an encrypted private key. Only PKCS8 private keys with encryption are supported. PKCS1 and EC private keys with encryption are much more complex to decrypt, and are not supported. Fixes gh-35652
This commit is contained in:
parent
7fcfcadfc3
commit
767ec4e22e
|
|
@ -66,6 +66,11 @@ public class PemSslBundleProperties extends SslBundleProperties {
|
|||
*/
|
||||
String privateKey;
|
||||
|
||||
/**
|
||||
* Password used to decrypt an encrypted private key.
|
||||
*/
|
||||
String privateKeyPassword;
|
||||
|
||||
public String getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
|
@ -90,6 +95,14 @@ public class PemSslBundleProperties extends SslBundleProperties {
|
|||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
public String getPrivateKeyPassword() {
|
||||
return this.privateKeyPassword;
|
||||
}
|
||||
|
||||
public void setPrivateKeyPassword(String privateKeyPassword) {
|
||||
this.privateKeyPassword = privateKeyPassword;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,7 +113,8 @@ public final class PropertiesSslBundle implements SslBundle {
|
|||
}
|
||||
|
||||
private static PemSslStoreDetails asStoreDetails(PemSslBundleProperties.Store properties) {
|
||||
return new PemSslStoreDetails(properties.getType(), properties.getCertificate(), properties.getPrivateKey());
|
||||
return new PemSslStoreDetails(properties.getType(), properties.getCertificate(), properties.getPrivateKey(),
|
||||
properties.getPrivateKeyPassword());
|
||||
}
|
||||
|
||||
private static SslStoreBundle asSslStoreBundle(JksSslBundleProperties properties) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.ssl;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.ssl.SslBundle;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link PropertiesSslBundle}.
|
||||
*
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
class PropertiesSslBundleTests {
|
||||
|
||||
@Test
|
||||
void pemPropertiesAreMappedToSslBundle() {
|
||||
PemSslBundleProperties properties = new PemSslBundleProperties();
|
||||
properties.getKey().setAlias("alias");
|
||||
properties.getKey().setPassword("secret");
|
||||
properties.getOptions().setCiphers(Set.of("cipher1", "cipher2", "cipher3"));
|
||||
properties.getOptions().setEnabledProtocols(Set.of("protocol1", "protocol2"));
|
||||
properties.getKeystore().setCertificate("cert1.pem");
|
||||
properties.getKeystore().setPrivateKey("key1.pem");
|
||||
properties.getKeystore().setPrivateKeyPassword("keysecret1");
|
||||
properties.getKeystore().setType("PKCS12");
|
||||
properties.getTruststore().setCertificate("cert2.pem");
|
||||
properties.getTruststore().setPrivateKey("key2.pem");
|
||||
properties.getTruststore().setPrivateKeyPassword("keysecret2");
|
||||
properties.getTruststore().setType("JKS");
|
||||
SslBundle sslBundle = PropertiesSslBundle.get(properties);
|
||||
assertThat(sslBundle.getKey().getAlias()).isEqualTo("alias");
|
||||
assertThat(sslBundle.getKey().getPassword()).isEqualTo("secret");
|
||||
assertThat(sslBundle.getOptions().getCiphers()).containsExactlyInAnyOrder("cipher1", "cipher2", "cipher3");
|
||||
assertThat(sslBundle.getOptions().getEnabledProtocols()).containsExactlyInAnyOrder("protocol1", "protocol2");
|
||||
assertThat(sslBundle.getStores()).isNotNull();
|
||||
assertThat(sslBundle.getStores()).extracting("keyStoreDetails")
|
||||
.extracting("certificate", "privateKey", "privateKeyPassword", "type")
|
||||
.containsExactly("cert1.pem", "key1.pem", "keysecret1", "PKCS12");
|
||||
assertThat(sslBundle.getStores()).extracting("trustStoreDetails")
|
||||
.extracting("certificate", "privateKey", "privateKeyPassword", "type")
|
||||
.containsExactly("cert2.pem", "key2.pem", "keysecret2", "JKS");
|
||||
}
|
||||
|
||||
@Test
|
||||
void jksPropertiesAreMappedToSslBundle() {
|
||||
JksSslBundleProperties properties = new JksSslBundleProperties();
|
||||
properties.getKey().setAlias("alias");
|
||||
properties.getKey().setPassword("secret");
|
||||
properties.getOptions().setCiphers(Set.of("cipher1", "cipher2", "cipher3"));
|
||||
properties.getOptions().setEnabledProtocols(Set.of("protocol1", "protocol2"));
|
||||
properties.getKeystore().setLocation("cert1.p12");
|
||||
properties.getKeystore().setPassword("secret1");
|
||||
properties.getKeystore().setProvider("provider1");
|
||||
properties.getKeystore().setType("JKS");
|
||||
properties.getTruststore().setLocation("cert2.jks");
|
||||
properties.getTruststore().setPassword("secret2");
|
||||
properties.getTruststore().setProvider("provider2");
|
||||
properties.getTruststore().setType("PKCS12");
|
||||
SslBundle sslBundle = PropertiesSslBundle.get(properties);
|
||||
assertThat(sslBundle.getKey().getAlias()).isEqualTo("alias");
|
||||
assertThat(sslBundle.getKey().getPassword()).isEqualTo("secret");
|
||||
assertThat(sslBundle.getOptions().getCiphers()).containsExactlyInAnyOrder("cipher1", "cipher2", "cipher3");
|
||||
assertThat(sslBundle.getOptions().getEnabledProtocols()).containsExactlyInAnyOrder("protocol1", "protocol2");
|
||||
assertThat(sslBundle.getStores()).isNotNull();
|
||||
assertThat(sslBundle.getStores()).extracting("keyStoreDetails")
|
||||
.extracting("location", "password", "provider", "type")
|
||||
.containsExactly("cert1.p12", "secret1", "provider1", "JKS");
|
||||
assertThat(sslBundle.getStores()).extracting("trustStoreDetails")
|
||||
.extracting("location", "password", "provider", "type")
|
||||
.containsExactly("cert2.jks", "secret2", "provider2", "PKCS12");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ package org.springframework.boot.ssl.pem;
|
|||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.AlgorithmParameters;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PrivateKey;
|
||||
|
|
@ -27,10 +28,18 @@ import java.util.ArrayList;
|
|||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.EncryptedPrivateKeyInfo;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Parser for PKCS private key files in PEM format.
|
||||
*
|
||||
|
|
@ -48,18 +57,27 @@ final class PemPrivateKeyParser {
|
|||
|
||||
private static final String PKCS8_FOOTER = "-+END\\s+PRIVATE\\s+KEY[^-]*-+";
|
||||
|
||||
private static final String PKCS8_ENCRYPTED_HEADER = "-+BEGIN\\s+ENCRYPTED\\s+PRIVATE\\s+KEY[^-]*-+(?:\\s|\\r|\\n)+";
|
||||
|
||||
private static final String PKCS8_ENCRYPTED_FOOTER = "-+END\\s+ENCRYPTED\\s+PRIVATE\\s+KEY[^-]*-+";
|
||||
|
||||
private static final String EC_HEADER = "-+BEGIN\\s+EC\\s+PRIVATE\\s+KEY[^-]*-+(?:\\s|\\r|\\n)+";
|
||||
|
||||
private static final String EC_FOOTER = "-+END\\s+EC\\s+PRIVATE\\s+KEY[^-]*-+";
|
||||
|
||||
private static final String BASE64_TEXT = "([a-z0-9+/=\\r\\n]+)";
|
||||
|
||||
public static final int BASE64_TEXT_GROUP = 1;
|
||||
|
||||
private static final List<PemParser> PEM_PARSERS;
|
||||
static {
|
||||
List<PemParser> parsers = new ArrayList<>();
|
||||
parsers.add(new PemParser(PKCS1_HEADER, PKCS1_FOOTER, PemPrivateKeyParser::createKeySpecForPkcs1, "RSA"));
|
||||
parsers.add(new PemParser(EC_HEADER, EC_FOOTER, PemPrivateKeyParser::createKeySpecForEc, "EC"));
|
||||
parsers.add(new PemParser(PKCS8_HEADER, PKCS8_FOOTER, PKCS8EncodedKeySpec::new, "RSA", "EC", "DSA", "Ed25519"));
|
||||
parsers.add(new PemParser(PKCS8_HEADER, PKCS8_FOOTER, PemPrivateKeyParser::createKeySpecForPkcs8, "RSA", "EC",
|
||||
"DSA", "Ed25519"));
|
||||
parsers.add(new PemParser(PKCS8_ENCRYPTED_HEADER, PKCS8_ENCRYPTED_FOOTER,
|
||||
PemPrivateKeyParser::createKeySpecForPkcs8Encrypted, "RSA", "EC", "DSA", "Ed25519"));
|
||||
PEM_PARSERS = Collections.unmodifiableList(parsers);
|
||||
}
|
||||
|
||||
|
|
@ -81,11 +99,11 @@ final class PemPrivateKeyParser {
|
|||
private PemPrivateKeyParser() {
|
||||
}
|
||||
|
||||
private static PKCS8EncodedKeySpec createKeySpecForPkcs1(byte[] bytes) {
|
||||
private static PKCS8EncodedKeySpec createKeySpecForPkcs1(byte[] bytes, String password) {
|
||||
return createKeySpecForAlgorithm(bytes, RSA_ALGORITHM, null);
|
||||
}
|
||||
|
||||
private static PKCS8EncodedKeySpec createKeySpecForEc(byte[] bytes) {
|
||||
private static PKCS8EncodedKeySpec createKeySpecForEc(byte[] bytes, String password) {
|
||||
return createKeySpecForAlgorithm(bytes, EC_ALGORITHM, EC_PARAMETERS);
|
||||
}
|
||||
|
||||
|
|
@ -106,18 +124,37 @@ final class PemPrivateKeyParser {
|
|||
}
|
||||
}
|
||||
|
||||
private static PKCS8EncodedKeySpec createKeySpecForPkcs8(byte[] bytes, String password) {
|
||||
return new PKCS8EncodedKeySpec(bytes);
|
||||
}
|
||||
|
||||
private static PKCS8EncodedKeySpec createKeySpecForPkcs8Encrypted(byte[] bytes, String password) {
|
||||
return Pkcs8PrivateKeyDecryptor.decrypt(bytes, password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a private key from the specified string.
|
||||
* @param key the private key to parse
|
||||
* @return the parsed private key
|
||||
*/
|
||||
static PrivateKey parse(String key) {
|
||||
return parse(key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a private key from the specified string, using the provided password for
|
||||
* decryption if necessary.
|
||||
* @param key the private key to parse
|
||||
* @param password the password used to decrypt an encrypted private key
|
||||
* @return the parsed private key
|
||||
*/
|
||||
static PrivateKey parse(String key, String password) {
|
||||
if (key == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
for (PemParser pemParser : PEM_PARSERS) {
|
||||
PrivateKey privateKey = pemParser.parse(key);
|
||||
PrivateKey privateKey = pemParser.parse(key, password);
|
||||
if (privateKey != null) {
|
||||
return privateKey;
|
||||
}
|
||||
|
|
@ -136,20 +173,20 @@ final class PemPrivateKeyParser {
|
|||
|
||||
private final Pattern pattern;
|
||||
|
||||
private final Function<byte[], PKCS8EncodedKeySpec> keySpecFactory;
|
||||
private final BiFunction<byte[], String, PKCS8EncodedKeySpec> keySpecFactory;
|
||||
|
||||
private final String[] algorithms;
|
||||
|
||||
PemParser(String header, String footer, Function<byte[], PKCS8EncodedKeySpec> keySpecFactory,
|
||||
PemParser(String header, String footer, BiFunction<byte[], String, PKCS8EncodedKeySpec> keySpecFactory,
|
||||
String... algorithms) {
|
||||
this.pattern = Pattern.compile(header + BASE64_TEXT + footer, Pattern.CASE_INSENSITIVE);
|
||||
this.algorithms = algorithms;
|
||||
this.keySpecFactory = keySpecFactory;
|
||||
this.algorithms = algorithms;
|
||||
}
|
||||
|
||||
PrivateKey parse(String text) {
|
||||
PrivateKey parse(String text, String password) {
|
||||
Matcher matcher = this.pattern.matcher(text);
|
||||
return (!matcher.find()) ? null : parse(decodeBase64(matcher.group(1)));
|
||||
return (!matcher.find()) ? null : parse(decodeBase64(matcher.group(BASE64_TEXT_GROUP)), password);
|
||||
}
|
||||
|
||||
private static byte[] decodeBase64(String content) {
|
||||
|
|
@ -157,9 +194,9 @@ final class PemPrivateKeyParser {
|
|||
return Base64.getDecoder().decode(contentBytes);
|
||||
}
|
||||
|
||||
private PrivateKey parse(byte[] bytes) {
|
||||
private PrivateKey parse(byte[] bytes, String password) {
|
||||
try {
|
||||
PKCS8EncodedKeySpec keySpec = this.keySpecFactory.apply(bytes);
|
||||
PKCS8EncodedKeySpec keySpec = this.keySpecFactory.apply(bytes, password);
|
||||
for (String algorithm : this.algorithms) {
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
|
||||
try {
|
||||
|
|
@ -251,4 +288,34 @@ final class PemPrivateKeyParser {
|
|||
|
||||
}
|
||||
|
||||
static class Pkcs8PrivateKeyDecryptor {
|
||||
|
||||
public static final String PBES2_ALGORITHM = "PBES2";
|
||||
|
||||
static PKCS8EncodedKeySpec decrypt(byte[] bytes, String password) {
|
||||
Assert.notNull(password, "Password is required for an encrypted private key");
|
||||
try {
|
||||
EncryptedPrivateKeyInfo keyInfo = new EncryptedPrivateKeyInfo(bytes);
|
||||
AlgorithmParameters algorithmParameters = keyInfo.getAlgParameters();
|
||||
String encryptionAlgorithm = getEncryptionAlgorithm(algorithmParameters, keyInfo.getAlgName());
|
||||
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(encryptionAlgorithm);
|
||||
SecretKey key = keyFactory.generateSecret(new PBEKeySpec(password.toCharArray()));
|
||||
Cipher cipher = Cipher.getInstance(encryptionAlgorithm);
|
||||
cipher.init(Cipher.DECRYPT_MODE, key, algorithmParameters);
|
||||
return keyInfo.getKeySpec(cipher);
|
||||
}
|
||||
catch (IOException | GeneralSecurityException ex) {
|
||||
throw new IllegalArgumentException("Error decrypting private key", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getEncryptionAlgorithm(AlgorithmParameters algParameters, String algName) {
|
||||
if (algParameters != null && PBES2_ALGORITHM.equals(algName)) {
|
||||
return algParameters.toString();
|
||||
}
|
||||
return algName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,14 +84,14 @@ public class PemSslStoreBundle implements SslStoreBundle {
|
|||
return null;
|
||||
}
|
||||
try {
|
||||
Assert.notNull(details.certificate(), "CertificateContent must not be null");
|
||||
Assert.notNull(details.certificate(), "Certificate content must not be null");
|
||||
String type = (!StringUtils.hasText(details.type())) ? KeyStore.getDefaultType() : details.type();
|
||||
KeyStore store = KeyStore.getInstance(type);
|
||||
store.load(null);
|
||||
String certificateContent = PemContent.load(details.certificate());
|
||||
String privateKeyContent = PemContent.load(details.privateKey());
|
||||
X509Certificate[] certificates = PemCertificateParser.parse(certificateContent);
|
||||
PrivateKey privateKey = PemPrivateKeyParser.parse(privateKeyContent);
|
||||
PrivateKey privateKey = PemPrivateKeyParser.parse(privateKeyContent, details.privateKeyPassword());
|
||||
addCertificates(store, certificates, privateKey);
|
||||
return store;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,11 +30,16 @@ import org.springframework.util.StringUtils;
|
|||
* that can be loaded by {@link ResourceUtils#getURL})
|
||||
* @param privateKey the private key content (either the PEM content itself or something
|
||||
* that can be loaded by {@link ResourceUtils#getURL})
|
||||
* @param privateKeyPassword a password used to decrypt an encrypted private key
|
||||
* @author Scott Frederick
|
||||
* @author Phillip Webb
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public record PemSslStoreDetails(String type, String certificate, String privateKey) {
|
||||
public record PemSslStoreDetails(String type, String certificate, String privateKey, String privateKeyPassword) {
|
||||
|
||||
public PemSslStoreDetails(String type, String certificate, String privateKey) {
|
||||
this(type, certificate, privateKey, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new {@link PemSslStoreDetails} instance with a new private key.
|
||||
|
|
@ -42,7 +47,16 @@ public record PemSslStoreDetails(String type, String certificate, String private
|
|||
* @return a new {@link PemSslStoreDetails} instance
|
||||
*/
|
||||
public PemSslStoreDetails withPrivateKey(String privateKey) {
|
||||
return new PemSslStoreDetails(this.type, this.certificate, privateKey);
|
||||
return new PemSslStoreDetails(this.type, this.certificate, privateKey, this.privateKeyPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new {@link PemSslStoreDetails} instance with a new private key password.
|
||||
* @param password the new private key password
|
||||
* @return a new {@link PemSslStoreDetails} instance
|
||||
*/
|
||||
public PemSslStoreDetails withPrivateKeyPassword(String password) {
|
||||
return new PemSslStoreDetails(this.type, this.certificate, this.privateKey, password);
|
||||
}
|
||||
|
||||
boolean isEmpty() {
|
||||
|
|
|
|||
|
|
@ -84,6 +84,47 @@ class PemPrivateKeyParserTests {
|
|||
assertThatIllegalStateException().isThrownBy(() -> PemPrivateKeyParser.parse(read("test-banner.txt")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parsePkcs8EncryptedRsaKeyFile() throws Exception {
|
||||
// created with:
|
||||
// openssl genpkey -aes-256-cbc -algorithm RSA \
|
||||
// -pkeyopt rsa_keygen_bits:4096 -out key-rsa-encrypted.key
|
||||
PrivateKey privateKey = PemPrivateKeyParser.parse(read("ssl/pkcs8/key-rsa-encrypted.pem"), "test");
|
||||
assertThat(privateKey).isNotNull();
|
||||
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
||||
assertThat(privateKey.getAlgorithm()).isEqualTo("RSA");
|
||||
}
|
||||
|
||||
@Test
|
||||
void parsePkcs8EncryptedEcKeyFile() throws Exception {
|
||||
// created with:
|
||||
// openssl genpkey -aes-256-cbc -algorithm EC \
|
||||
// -pkeyopt ec_paramgen_curve:prime256v1 -out key-ec-encrypted.key
|
||||
PrivateKey privateKey = PemPrivateKeyParser.parse(read("ssl/pkcs8/key-ec-encrypted.pem"), "test");
|
||||
assertThat(privateKey).isNotNull();
|
||||
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
||||
assertThat(privateKey.getAlgorithm()).isEqualTo("EC");
|
||||
}
|
||||
|
||||
@Test
|
||||
void failParsingPkcs1EncryptedKeyFile() throws Exception {
|
||||
// created with:
|
||||
// openssl genrsa -aes-256-cbc -out key-rsa-encrypted.pem
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> PemPrivateKeyParser.parse(read("ssl/pkcs1/key-rsa-encrypted.pem"), "test"))
|
||||
.withMessageContaining("Unrecognized private key format");
|
||||
}
|
||||
|
||||
@Test
|
||||
void failParsingEcEncryptedKeyFile() throws Exception {
|
||||
// created with:
|
||||
// openssl ecparam -genkey -name prime256v1 | openssl ec -aes-128-cbc -out
|
||||
// key-ec-prime256v1-encrypted.pem
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> PemPrivateKeyParser.parse(read("ssl/ec/key-ec-prime256v1-encrypted.pem"), "test"))
|
||||
.withMessageContaining("Unrecognized private key format");
|
||||
}
|
||||
|
||||
private String read(String path) throws IOException {
|
||||
return new ClassPathResource(path).getContentAsString(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,17 @@ class PemSslStoreBundleTests {
|
|||
assertThat(bundle.getTrustStore()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenHasKeyStoreDetailsCertAndEncryptedKey() {
|
||||
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
||||
.withPrivateKey("classpath:ssl/pkcs8/key-rsa-encrypted.pem")
|
||||
.withPrivateKeyPassword("test");
|
||||
PemSslStoreDetails trustStoreDetails = null;
|
||||
PemSslStoreBundle bundle = new PemSslStoreBundle(keyStoreDetails, trustStoreDetails);
|
||||
assertThat(bundle.getKeyStore()).satisfies(storeContainingCertAndKey("ssl"));
|
||||
assertThat(bundle.getTrustStore()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenHasKeyStoreDetailsAndTrustStoreDetailsWithoutKey() {
|
||||
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
-----BEGIN EC PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-128-CBC,3F26BBC4C7A6F3B5B3A5C03C7CC59B33
|
||||
|
||||
rp4qC+n+qIG+WKJp4BHQHk5z0oraaaLZvoVK5glESGx5IcR3mCsN7tdg2aZ7yEk+
|
||||
HnT4nQuM3R5pv248cmK0xDUje8N7FLe8lixVnEyQx3JdZfGdauowt9yaxL3AJypX
|
||||
idWxNrxz1xff5RSMI6+PFv2SQpG0l794EpOjZxOUABM=
|
||||
-----END EC PRIVATE KEY-----
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-256-CBC,2036BA8802B364C6BE415A48E1AC9966
|
||||
|
||||
0euP/daGIbl798XGc2Tc6u6NmnCl8C6hE0a2grO+wbvFEa13IT4hNVNTzqahfLb8
|
||||
STF9LXdvPbz9HybyWnG8KNm5sqsSY1omsHQI38khhwuhpHuWfjb62TqWobwrAmAU
|
||||
qh2+kjc7upzW48axJLRQ69vfE4zKczZ4Sqv8qImPz9SiXPeaXinHf/wKfgXZZOvr
|
||||
6A8nCykLglVrFbrZWydqKrTM9w/LTXsn0gNpDmrfZERDgWnabKnjYidHkXdgAoFy
|
||||
ulsBjKvj2hJFtnJHTkCPXj6XAj18cwUWsN7inFJR5wqjIWXuLqfv/fNbK9lPzjAk
|
||||
vMTEVWwynekvXFsSvnHAyEJfmRCNF6DOE+5VwjEROCFq8xceK4fz4T3BHC7XSgis
|
||||
2ofBZwjCAJ0pP6SdRpbbZ0wlXH09wqDDTZ2vWD6bEG7hO9VuP/aO76MIWydLa78z
|
||||
bDb2R6MnYKmYEInPzwfU4H66Z3/cz8orfYLlnF55DRd4rO+fJm6Y/XY14ac3x0S+
|
||||
P67s5e0WbdImagUsOxGNBjgOr84lwmtk/LoVd5nKho8JyQw3V7tiyrsKsM1lAXdS
|
||||
TaJXKRnN6LbgC8d+Tgfjc/qMUdVqLlN8zATIa6E4sc861DDiJsneXuFm43pHc/ja
|
||||
0sxSifBKgLGenj8xY5ANEfrYnXKrzaQemUnMzd+zan6OS02I+e8WTQevESt1j0D8
|
||||
7mgLJ9W2SfNNfiEd5OKar21lLNOc3POaFn7M73zL/gyhTROipPR3fpV+08k27UKl
|
||||
nzGhFtRwQieXl34QjM0JrHokKKfv8FsAJsbrGnz2/wcm6jJGmrj5VVsogMKc90v4
|
||||
ZTM44NAKymM0UTuIp/rKb/UUVYDpl9VWDegWh2+XKX8io31ENrDMcvQTJ/mzNCuZ
|
||||
SINrAeMbVD6W5L0i7THEt32YsDmbFsBaEJBlNXlUNBa/NCK0pjwAn5AYOFUvEqBC
|
||||
oZUEleUMU6Q3TKI287o37euw3No6jo5VdPULlrwHsZAjmq9EUvRCgMoIEPdxv5XG
|
||||
a4PljE7DQLlk6G9d+gjRzClLFfkadSTbtH9o2011RtWUKP4dcRuSOcBm64xVIO6J
|
||||
rhe38sE3yzHvLUM/mvLsEM8B0AHl85nrEstlbBzftXMo2CAJ2Gs9c61PYfft+xiT
|
||||
pRdHx4HB1P+kfHa96ayvAytOexHih2iVKVG5CchOr5tbWmkhXVE5cZAKzvczDYFd
|
||||
YvniHNiqt6LO8EbJOzz+Yxessmd0zBXj/rjxTMdGwaRjiFI0BIguYpvmGoMS8+bp
|
||||
spRj2DMtqjNZz68BEEfgKQwDHPCTblYSR+3Uw4sja608sflqQ8rTmOwbfta3SNS8
|
||||
Kq/zzWfYzarQ8hAk5n/H1Jm6AQdvcptyMjuF8FAiMnvt8xDCBRMD3xY2BHb/tcs9
|
||||
dBWBxhb76CKIrV3pzm9gGhhZ32Ndq9KmmE+bWCYyvrLxvPJxODfM7X5XamPmG5SH
|
||||
wEKSbp0wPF0b6vyxt5M72OYnU8UnxYWu6PlbVvczfWEu9fIw/oIN/kDT/QUojTyt
|
||||
wBgzVSTSNFaDtVXJw10IWQgsgWdNY5XueHKH060P5g+14woxU8i3TboNd+tC3hRl
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||
MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAjZ2eXtLFXLdgICCAAw
|
||||
DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEIlOTfeoLwq9Bs9TFtw7VSMEgZAU
|
||||
RO9W+K3vvzRG4sACrcFaB7PMhv3+HUOcPFf09QHa7aSJMWsb8EXGFBK4xlFhkK0/
|
||||
N0C8sRtH2N1JdYj9hiwS7I8WyybaR2W0ZALNR57iLz3WsOGQ7nVECFprElboqnSW
|
||||
BtjkKTD9pz3xX/6cMkDV/2WqbS6Y/dzWJTH8yTTqjzTjbs4vguEK1Io6dlIRVqA=
|
||||
-----END ENCRYPTED PRIVATE KEY-----
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||
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
|
||||
-----END ENCRYPTED PRIVATE KEY-----
|
||||
Loading…
Reference in New Issue