diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/PemSslBundleProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/PemSslBundleProperties.java index d296ffdec3..89f51bf27d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/PemSslBundleProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/PemSslBundleProperties.java @@ -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; + } + } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/PropertiesSslBundle.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/PropertiesSslBundle.java index abb9ab6cc6..b25b88ad14 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/PropertiesSslBundle.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/PropertiesSslBundle.java @@ -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) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ssl/PropertiesSslBundleTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ssl/PropertiesSslBundleTests.java new file mode 100644 index 0000000000..43c00ac56b --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ssl/PropertiesSslBundleTests.java @@ -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"); + } + +} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemPrivateKeyParser.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemPrivateKeyParser.java index e7216d03c6..7f3e6c3304 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemPrivateKeyParser.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemPrivateKeyParser.java @@ -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 PEM_PARSERS; static { List 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 keySpecFactory; + private final BiFunction keySpecFactory; private final String[] algorithms; - PemParser(String header, String footer, Function keySpecFactory, + PemParser(String header, String footer, BiFunction 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; + } + + } + } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemSslStoreBundle.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemSslStoreBundle.java index dc857bf66f..dee4651852 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemSslStoreBundle.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemSslStoreBundle.java @@ -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; } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemSslStoreDetails.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemSslStoreDetails.java index 978d14a1b4..81d68eb695 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemSslStoreDetails.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemSslStoreDetails.java @@ -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() { diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ssl/pem/PemPrivateKeyParserTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ssl/pem/PemPrivateKeyParserTests.java index 79bd3a11ee..82203b75dc 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ssl/pem/PemPrivateKeyParserTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ssl/pem/PemPrivateKeyParserTests.java @@ -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); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ssl/pem/PemSslStoreBundleTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ssl/pem/PemSslStoreBundleTests.java index fd092261b1..61f5c4983b 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ssl/pem/PemSslStoreBundleTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ssl/pem/PemSslStoreBundleTests.java @@ -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") diff --git a/spring-boot-project/spring-boot/src/test/resources/ssl/ec/key-ec-prime256v1-encrypted.pem b/spring-boot-project/spring-boot/src/test/resources/ssl/ec/key-ec-prime256v1-encrypted.pem new file mode 100644 index 0000000000..ccecc24707 --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/resources/ssl/ec/key-ec-prime256v1-encrypted.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----- diff --git a/spring-boot-project/spring-boot/src/test/resources/ssl/pkcs1/key-rsa-encrypted.pem b/spring-boot-project/spring-boot/src/test/resources/ssl/pkcs1/key-rsa-encrypted.pem new file mode 100644 index 0000000000..4053ed5f6e --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/resources/ssl/pkcs1/key-rsa-encrypted.pem @@ -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----- diff --git a/spring-boot-project/spring-boot/src/test/resources/ssl/pkcs8/key-ec-encrypted.pem b/spring-boot-project/spring-boot/src/test/resources/ssl/pkcs8/key-ec-encrypted.pem new file mode 100644 index 0000000000..ec36422309 --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/resources/ssl/pkcs8/key-ec-encrypted.pem @@ -0,0 +1,7 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAjZ2eXtLFXLdgICCAAw +DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEIlOTfeoLwq9Bs9TFtw7VSMEgZAU +RO9W+K3vvzRG4sACrcFaB7PMhv3+HUOcPFf09QHa7aSJMWsb8EXGFBK4xlFhkK0/ +N0C8sRtH2N1JdYj9hiwS7I8WyybaR2W0ZALNR57iLz3WsOGQ7nVECFprElboqnSW +BtjkKTD9pz3xX/6cMkDV/2WqbS6Y/dzWJTH8yTTqjzTjbs4vguEK1Io6dlIRVqA= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/spring-boot-project/spring-boot/src/test/resources/ssl/pkcs8/key-rsa-encrypted.pem b/spring-boot-project/spring-boot/src/test/resources/ssl/pkcs8/key-rsa-encrypted.pem new file mode 100644 index 0000000000..638f6fd3fd --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/resources/ssl/pkcs8/key-rsa-encrypted.pem @@ -0,0 +1,54 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +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 +-----END ENCRYPTED PRIVATE KEY-----