Merge branch '3.1.x'
This commit is contained in:
@@ -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-----
|
||||
Reference in New Issue
Block a user