From 7cc9edbf1bb9430355d798b8195307d30bc32a22 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Mon, 18 Oct 2021 21:24:23 +1100 Subject: [PATCH] Fix parsing of PBES2 encrypted PKCS#8 keys (#78904) This commit adds support for decrypting PKCS#8 encoded private keys that have been encrypted using a PBES2 based scheme (AES only). Unfortunately `java.crypto.EncryptedPrivateKeyInfo` doesn't make this easy as the underlying encryption algorithm is hidden within the `AlgorithmParameters`, and can only be extracted by calling `toString()` on the parameters object. See: https://datatracker.ietf.org/doc/html/rfc8018#appendix-A.4 See: AlgorithmParameters#toString() See: com.sun.crypto.provider.PBES2Parameters#toString() Resolves: #78901, #32021 --- .../elasticsearch/common/ssl/DerParser.java | 73 ++++++----- .../elasticsearch/common/ssl/PemUtils.java | 115 +++++++++++++++++- .../common/ssl/PemUtilsTests.java | 52 ++++++-- .../resources/certs/pem-utils/README.asciidoc | 26 +++- .../certs/pem-utils/key_pkcs8_encrypted.pem | 29 ----- .../key_pkcs8_encrypted_pbes1_des.pem | 29 +++++ .../key_pkcs8_encrypted_pbes2_aes.pem | 30 +++++ .../key_pkcs8_encrypted_pbes2_des.pem | 29 +++++ 8 files changed, 313 insertions(+), 70 deletions(-) delete mode 100644 libs/ssl-config/src/test/resources/certs/pem-utils/key_pkcs8_encrypted.pem create mode 100644 libs/ssl-config/src/test/resources/certs/pem-utils/key_pkcs8_encrypted_pbes1_des.pem create mode 100644 libs/ssl-config/src/test/resources/certs/pem-utils/key_pkcs8_encrypted_pbes2_aes.pem create mode 100644 libs/ssl-config/src/test/resources/certs/pem-utils/key_pkcs8_encrypted_pbes2_des.pem diff --git a/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/DerParser.java b/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/DerParser.java index a188636b1c9fa..7b6f8aa5480bc 100644 --- a/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/DerParser.java +++ b/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/DerParser.java @@ -36,21 +36,22 @@ public final class DerParser { private static final int CONSTRUCTED = 0x20; // Tag and data types - private static final int INTEGER = 0x02; - private static final int OCTET_STRING = 0x04; - private static final int OBJECT_OID = 0x06; - private static final int NUMERIC_STRING = 0x12; - private static final int PRINTABLE_STRING = 0x13; - private static final int VIDEOTEX_STRING = 0x15; - private static final int IA5_STRING = 0x16; - private static final int GRAPHIC_STRING = 0x19; - private static final int ISO646_STRING = 0x1A; - private static final int GENERAL_STRING = 0x1B; - - private static final int UTF8_STRING = 0x0C; - private static final int UNIVERSAL_STRING = 0x1C; - private static final int BMP_STRING = 0x1E; - + static final class Type { + static final int INTEGER = 0x02; + static final int OCTET_STRING = 0x04; + static final int OBJECT_OID = 0x06; + static final int SEQUENCE = 0x10; + static final int NUMERIC_STRING = 0x12; + static final int PRINTABLE_STRING = 0x13; + static final int VIDEOTEX_STRING = 0x15; + static final int IA5_STRING = 0x16; + static final int GRAPHIC_STRING = 0x19; + static final int ISO646_STRING = 0x1A; + static final int GENERAL_STRING = 0x1B; + static final int UTF8_STRING = 0x0C; + static final int UNIVERSAL_STRING = 0x1C; + static final int BMP_STRING = 0x1E; + } private InputStream derInputStream; private int maxAsnObjectLength; @@ -60,6 +61,22 @@ public DerParser(byte[] bytes) { this.maxAsnObjectLength = bytes.length; } + /** + * Read an object and verify its type + * @param requiredType The expected type code + * @throws IOException if data can not be parsed + * @throws IllegalStateException if the parsed object is of the wrong type + */ + public Asn1Object readAsn1Object(int requiredType) throws IOException { + final Asn1Object obj = readAsn1Object(); + if (obj.type != requiredType) { + throw new IllegalStateException( + "Expected ASN.1 object of type 0x" + Integer.toHexString(requiredType) + " but was 0x" + Integer.toHexString(obj.type) + ); + } + return obj; + } + public Asn1Object readAsn1Object() throws IOException { int tag = derInputStream.read(); if (tag == -1) { @@ -207,7 +224,7 @@ public DerParser getParser() throws IOException { * @return BigInteger */ public BigInteger getInteger() throws IOException { - if (type != DerParser.INTEGER) + if (type != Type.INTEGER) throw new IOException("Invalid DER: object is not integer"); //$NON-NLS-1$ return new BigInteger(value); @@ -218,28 +235,28 @@ public String getString() throws IOException { String encoding; switch (type) { - case DerParser.OCTET_STRING: + case Type.OCTET_STRING: // octet string is basically a byte array return toHexString(value); - case DerParser.NUMERIC_STRING: - case DerParser.PRINTABLE_STRING: - case DerParser.VIDEOTEX_STRING: - case DerParser.IA5_STRING: - case DerParser.GRAPHIC_STRING: - case DerParser.ISO646_STRING: - case DerParser.GENERAL_STRING: + case Type.NUMERIC_STRING: + case Type.PRINTABLE_STRING: + case Type.VIDEOTEX_STRING: + case Type.IA5_STRING: + case Type.GRAPHIC_STRING: + case Type.ISO646_STRING: + case Type.GENERAL_STRING: encoding = "ISO-8859-1"; //$NON-NLS-1$ break; - case DerParser.BMP_STRING: + case Type.BMP_STRING: encoding = "UTF-16BE"; //$NON-NLS-1$ break; - case DerParser.UTF8_STRING: + case Type.UTF8_STRING: encoding = "UTF-8"; //$NON-NLS-1$ break; - case DerParser.UNIVERSAL_STRING: + case Type.UNIVERSAL_STRING: throw new IOException("Invalid DER: can't handle UCS-4 string"); //$NON-NLS-1$ default: @@ -251,7 +268,7 @@ public String getString() throws IOException { public String getOid() throws IOException { - if (type != DerParser.OBJECT_OID) { + if (type != Type.OBJECT_OID) { throw new IOException("Ivalid DER: object is not object OID"); } StringBuilder sb = new StringBuilder(64); diff --git a/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/PemUtils.java b/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/PemUtils.java index d56459746b9cf..151bb6331cf9a 100644 --- a/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/PemUtils.java +++ b/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/PemUtils.java @@ -25,6 +25,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.security.AccessControlException; +import java.security.AlgorithmParameters; import java.security.GeneralSecurityException; import java.security.KeyFactory; import java.security.KeyPairGenerator; @@ -68,6 +69,9 @@ public final class PemUtils { private static final String OPENSSL_EC_PARAMS_FOOTER = "-----END EC PARAMETERS-----"; private static final String HEADER = "-----BEGIN"; + private static final String PBES2_OID = "1.2.840.113549.1.5.13"; + private static final String AES_OID = "2.16.840.1.101.3.4.1"; + private PemUtils() { throw new IllegalStateException("Utility class should not be instantiated"); } @@ -365,10 +369,14 @@ private static PrivateKey parsePKCS8Encrypted(BufferedReader bReader, char[] key } byte[] keyBytes = Base64.getDecoder().decode(sb.toString()); - EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(keyBytes); - SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(encryptedPrivateKeyInfo.getAlgName()); + final EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = getEncryptedPrivateKeyInfo(keyBytes); + String algorithm = encryptedPrivateKeyInfo.getAlgName(); + if (algorithm.equals("PBES2") || algorithm.equals("1.2.840.113549.1.5.13")) { + algorithm = getPBES2Algorithm(encryptedPrivateKeyInfo); + } + SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(algorithm); SecretKey secretKey = secretKeyFactory.generateSecret(new PBEKeySpec(keyPassword)); - Cipher cipher = Cipher.getInstance(encryptedPrivateKeyInfo.getAlgName()); + Cipher cipher = Cipher.getInstance(algorithm); cipher.init(Cipher.DECRYPT_MODE, secretKey, encryptedPrivateKeyInfo.getAlgParameters()); PKCS8EncodedKeySpec keySpec = encryptedPrivateKeyInfo.getKeySpec(cipher); String keyAlgo = getKeyAlgorithmIdentifier(keySpec.getEncoded()); @@ -376,6 +384,55 @@ private static PrivateKey parsePKCS8Encrypted(BufferedReader bReader, char[] key return keyFactory.generatePrivate(keySpec); } + private static EncryptedPrivateKeyInfo getEncryptedPrivateKeyInfo(byte[] keyBytes) throws IOException, GeneralSecurityException { + try { + return new EncryptedPrivateKeyInfo(keyBytes); + } catch (IOException e) { + // The Sun JCE provider can't handle non-AES PBES2 data (but it can handle PBES1 DES data - go figure) + // It's not worth our effort to try and decrypt it ourselves, but we can detect it and give a good error message + DerParser parser = new DerParser(keyBytes); + final DerParser.Asn1Object rootSeq = parser.readAsn1Object(DerParser.Type.SEQUENCE); + parser = rootSeq.getParser(); + final DerParser.Asn1Object algSeq = parser.readAsn1Object(DerParser.Type.SEQUENCE); + parser = algSeq.getParser(); + final String algId = parser.readAsn1Object(DerParser.Type.OBJECT_OID).getOid(); + if (PBES2_OID.equals(algId)) { + final DerParser.Asn1Object algData = parser.readAsn1Object(DerParser.Type.SEQUENCE); + parser = algData.getParser(); + final DerParser.Asn1Object ignoreKdf = parser.readAsn1Object(DerParser.Type.SEQUENCE); + final DerParser.Asn1Object cryptSeq = parser.readAsn1Object(DerParser.Type.SEQUENCE); + parser = cryptSeq.getParser(); + final String encryptionId = parser.readAsn1Object(DerParser.Type.OBJECT_OID).getOid(); + if (encryptionId.startsWith(AES_OID) == false) { + final String name = getAlgorithmNameFromOid(encryptionId); + throw new GeneralSecurityException( + "PKCS#8 Private Key is encrypted with unsupported PBES2 algorithm [" + + encryptionId + + "]" + + (name == null ? "" : " (" + name + ")"), + e + ); + } + } + throw e; + } + } + + /** + * This is horrible, but it's the only option other than to parse the encoded ASN.1 value ourselves + * @see AlgorithmParameters#toString() and com.sun.crypto.provider.PBES2Parameters#toString() + */ + private static String getPBES2Algorithm(EncryptedPrivateKeyInfo encryptedPrivateKeyInfo) { + final AlgorithmParameters algParameters = encryptedPrivateKeyInfo.getAlgParameters(); + if (algParameters != null) { + return algParameters.toString(); + } else { + // AlgorithmParameters can be null when running on BCFIPS. + // However, since BCFIPS doesn't support any PBE specs, nothing we do here would work, so we just do enough to avoid an NPE + return encryptedPrivateKeyInfo.getAlgName(); + } + } + /** * Decrypts the password protected contents using the algorithm and IV that is specified in the PEM Headers of the file * @@ -604,7 +661,7 @@ private static String getKeyAlgorithmIdentifier(byte[] keyBytes) throws IOExcept return "EC"; } throw new GeneralSecurityException("Error parsing key algorithm identifier. Algorithm with OID [" + oidString + - "] is not żsupported"); + "] is not supported"); } public static List readCertificates(Collection certPaths) throws CertificateException, IOException { @@ -622,6 +679,56 @@ public static List readCertificates(Collection certPaths) thr return certificates; } + private static String getAlgorithmNameFromOid(String oidString) throws GeneralSecurityException { + switch (oidString) { + case "1.2.840.10040.4.1": + return "DSA"; + case "1.2.840.113549.1.1.1": + return "RSA"; + case "1.2.840.10045.2.1": + return "EC"; + case "1.3.14.3.2.7": + return "DES-CBC"; + case "2.16.840.1.101.3.4.1.1": + return "AES-128_ECB"; + case "2.16.840.1.101.3.4.1.2": + return "AES-128_CBC"; + case "2.16.840.1.101.3.4.1.3": + return "AES-128_OFB"; + case "2.16.840.1.101.3.4.1.4": + return "AES-128_CFB"; + case "2.16.840.1.101.3.4.1.6": + return "AES-128_GCM"; + case "2.16.840.1.101.3.4.1.21": + return "AES-192_ECB"; + case "2.16.840.1.101.3.4.1.22": + return "AES-192_CBC"; + case "2.16.840.1.101.3.4.1.23": + return "AES-192_OFB"; + case "2.16.840.1.101.3.4.1.24": + return "AES-192_CFB"; + case "2.16.840.1.101.3.4.1.26": + return "AES-192_GCM"; + case "2.16.840.1.101.3.4.1.41": + return "AES-256_ECB"; + case "2.16.840.1.101.3.4.1.42": + return "AES-256_CBC"; + case "2.16.840.1.101.3.4.1.43": + return "AES-256_OFB"; + case "2.16.840.1.101.3.4.1.44": + return "AES-256_CFB"; + case "2.16.840.1.101.3.4.1.46": + return "AES-256_GCM"; + case "2.16.840.1.101.3.4.1.5": + return "AESWrap-128"; + case "2.16.840.1.101.3.4.1.25": + return "AESWrap-192"; + case "2.16.840.1.101.3.4.1.45": + return "AESWrap-256"; + } + return null; + } + private static String getEcCurveNameFromOid(String oidString) throws GeneralSecurityException { switch (oidString) { // see https://tools.ietf.org/html/rfc5480#section-2.1.1.1 diff --git a/libs/ssl-config/src/test/java/org/elasticsearch/common/ssl/PemUtilsTests.java b/libs/ssl-config/src/test/java/org/elasticsearch/common/ssl/PemUtilsTests.java index 72f456daaa557..85d468def0d5a 100644 --- a/libs/ssl-config/src/test/java/org/elasticsearch/common/ssl/PemUtilsTests.java +++ b/libs/ssl-config/src/test/java/org/elasticsearch/common/ssl/PemUtilsTests.java @@ -15,6 +15,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.security.AlgorithmParameters; +import java.security.GeneralSecurityException; import java.security.Key; import java.security.KeyStore; import java.security.PrivateKey; @@ -26,6 +27,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.startsWith; import static org.hamcrest.core.StringContains.containsString; public class PemUtilsTests extends ESTestCase { @@ -79,17 +81,49 @@ public void testReadPKCS8EcKey() throws Exception { assertThat(privateKey, equalTo(key)); } - public void testReadEncryptedPKCS8Key() throws Exception { + public void testReadEncryptedPKCS8PBES1Key() throws Exception { assumeFalse("Can't run in a FIPS JVM, PBE KeySpec is not available", inFipsJvm()); Key key = getKeyFromKeystore("RSA"); assertThat(key, notNullValue()); assertThat(key, instanceOf(PrivateKey.class)); - PrivateKey privateKey = PemUtils.parsePrivateKey(getDataPath - ("/certs/pem-utils/key_pkcs8_encrypted.pem"), TESTNODE_PASSWORD); + PrivateKey privateKey = PemUtils.parsePrivateKey( + getDataPath("/certs/pem-utils/key_pkcs8_encrypted_pbes1_des.pem"), + TESTNODE_PASSWORD + ); assertThat(privateKey, notNullValue()); assertThat(privateKey, equalTo(key)); } + public void testReadEncryptedPKCS8PBES2AESKey() throws Exception { + assumeFalse("Can't run in a FIPS JVM, PBE KeySpec is not available", inFipsJvm()); + Key key = getKeyFromKeystore("RSA"); + assertThat(key, notNullValue()); + assertThat(key, instanceOf(PrivateKey.class)); + PrivateKey privateKey = PemUtils.parsePrivateKey( + getDataPath("/certs/pem-utils/key_pkcs8_encrypted_pbes2_aes.pem"), + TESTNODE_PASSWORD + ); + assertThat(privateKey, notNullValue()); + assertThat(privateKey, equalTo(key)); + } + + public void testReadEncryptedPKCS8PBES2DESKey() throws Exception { + assumeFalse("Can't run in a FIPS JVM, PBE KeySpec is not available", inFipsJvm()); + + // Sun JSE cannot read keys encrypted with PBES2 DES (but does support AES with PBES2 and DES with PBES1) + // Rather than add our own support for this we just detect that our error message is clear and meaningful + final GeneralSecurityException exception = expectThrows( + GeneralSecurityException.class, + () -> PemUtils.parsePrivateKey(getDataPath("/certs/pem-utils/key_pkcs8_encrypted_pbes2_des.pem"), TESTNODE_PASSWORD) + ); + assertThat( + exception.getMessage(), + equalTo("PKCS#8 Private Key is encrypted with unsupported PBES2 algorithm [1.3.14.3.2.7] (DES-CBC)") + ); + assertThat(exception.getCause(), instanceOf(IOException.class)); + assertThat(exception.getCause().getMessage(), startsWith("PBE parameter parsing error")); + } + public void testReadDESEncryptedPKCS1Key() throws Exception { Key key = getKeyFromKeystore("RSA"); assertThat(key, notNullValue()); @@ -134,8 +168,10 @@ public void testReadOpenSslDsaKeyWithParams() throws Exception { Key key = getKeyFromKeystore("DSA"); assertThat(key, notNullValue()); assertThat(key, instanceOf(PrivateKey.class)); - PrivateKey privateKey = PemUtils.parsePrivateKey(getDataPath("/certs/pem-utils/dsa_key_openssl_plain_with_params.pem"), - EMPTY_PASSWORD); + PrivateKey privateKey = PemUtils.parsePrivateKey( + getDataPath("/certs/pem-utils/dsa_key_openssl_plain_with_params.pem"), + EMPTY_PASSWORD + ); assertThat(privateKey, notNullValue()); assertThat(privateKey, equalTo(key)); @@ -165,8 +201,10 @@ public void testReadOpenSslEcKeyWithParams() throws Exception { Key key = getKeyFromKeystore("EC"); assertThat(key, notNullValue()); assertThat(key, instanceOf(PrivateKey.class)); - PrivateKey privateKey = PemUtils.parsePrivateKey(getDataPath("/certs/pem-utils/ec_key_openssl_plain_with_params.pem"), - EMPTY_PASSWORD); + PrivateKey privateKey = PemUtils.parsePrivateKey( + getDataPath("/certs/pem-utils/ec_key_openssl_plain_with_params.pem"), + EMPTY_PASSWORD + ); assertThat(privateKey, notNullValue()); assertThat(privateKey, equalTo(key)); diff --git a/libs/ssl-config/src/test/resources/certs/pem-utils/README.asciidoc b/libs/ssl-config/src/test/resources/certs/pem-utils/README.asciidoc index f7fbd2ad69c0d..7ed9e4c6c4c50 100644 --- a/libs/ssl-config/src/test/resources/certs/pem-utils/README.asciidoc +++ b/libs/ssl-config/src/test/resources/certs/pem-utils/README.asciidoc @@ -101,12 +101,34 @@ openssl pkcs12 -in ec.p12 -nodes -nocerts | openssl pkcs8 -topk8 -nocrypt -outfo ---- - Create `PKCS#8` encrypted key from the encrypted `PKCS#1` encoded `testnode.pem` +The `-v1 PBE-MD5-DES` parameter forces pbeWithMD5AndDES-CBC as the encryption scheme (which is also the default, but that could change with diffent OpenSSL versions) +See: http://oid-info.com/get/1.2.840.113549.1.5.3 +See: https://datatracker.ietf.org/doc/html/rfc8018#appendix-A.3 +[source,shell] +----- +openssl pkcs8 -topk8 -v1 PBE-MD5-DES -inform PEM -outform PEM -in testnode.pem -passin "pass:testnode" -out key_pkcs8_encrypted_pbes1_des.pem -passout "pass:testnode" +----- + +Create `PKCS#8` `PBES2` `AES` encrypted key from the encrypted `PKCS#1` encoded `testnode.pem` +The `-v2 aes256` parameter forces PBES2 with AES256 +See: http://oid-info.com/get/1.2.840.113549.1.5.13 +See: https://datatracker.ietf.org/doc/html/rfc8018#appendix-A.4 [source,shell] ----- -openssl pkcs8 -topk8 -inform PEM -outform PEM -in testnode.pem -out key_pkcs8_encrypted.pem +openssl pkcs8 -topk8 -v2 aes256 -inform PEM -outform PEM -in testnode.pem -passin "pass:testnode" -out key_pkcs8_encrypted_pbes2_aes.pem -passout "pass:testnode" ----- + +Create `PKCS#8` `PBES2` `DES` encrypted key from the encrypted `PKCS#1` encoded `testnode.pem` +The `-v2 des` parameter forces PBES2 with DES +See: http://oid-info.com/get/1.2.840.113549.1.5.13 +See: https://datatracker.ietf.org/doc/html/rfc8018#appendix-A.4 +[source,shell] +----- +openssl pkcs8 -topk8 -v2 des -inform PEM -outform PEM -in testnode.pem -passin "pass:testnode" -out key_pkcs8_encrypted_pbes2_des.pem -passout "pass:testnode" +----- + + [source,shell] ----- ssh-keygen -t ed25519 -f key_unsupported.pem diff --git a/libs/ssl-config/src/test/resources/certs/pem-utils/key_pkcs8_encrypted.pem b/libs/ssl-config/src/test/resources/certs/pem-utils/key_pkcs8_encrypted.pem deleted file mode 100644 index 28059d5a2266d..0000000000000 --- a/libs/ssl-config/src/test/resources/certs/pem-utils/key_pkcs8_encrypted.pem +++ /dev/null @@ -1,29 +0,0 @@ ------BEGIN ENCRYPTED PRIVATE KEY----- -MIIE6TAbBgkqhkiG9w0BBQMwDgQI2jwlFL0XId0CAggABIIEyMujZbpG6zKb2pVu -soamTaoLcZwNofS9ncGIEH1nbI8UpPY81VeOIBm4mneDt8RU5bIOXP4IZEZY9uU+ -pugKQ3hT8vBQjJujjuctUPaFxB0kGEeITOInY2jn2BFDbUgy5Z7EVD4G2K06SDDK -oD+twbzZo9x34VizwpHHb8wE+DFyYc+sp+Re2Qk3FReKgjdJezfcRHbKrrlx2rJ+ -k/YAPmzcFYVbuUiB6HY6BGzSJO1JxT8iNJE+Hmk3ZLXG590hp0vuGSkY/ihbeix4 -1rQs7u4riqXJ+DJBmXt/wXUij0/k6s4igACNsT2MkZkGEDkzqzE+kj2VYOHSX+Wd -5W0WCfftcsIQ8eow4ACec/Ns9ionLjx1xnbTjRMkpGgbVsreupU9AQ4MhLNNgwyl -six/cxUxTvH8Modd0/4KQFkeo352A6+DKCaPZ87SoF2Rge1otcJaZVcX1gBvIztB -/xzYwyUydQEwblU0kCYWRgxlKP9jxFoke2RX1BodRfAMNDxS0XyYrA/JzB7ZRsS7 -QGYPy/PPb014U3KhpJdjwbNu2VaCVdGryYA9+BTP+Vzwcp8MZoMPnnjnBh1YyVAj -c7oyzKU5e5SVsYni1Kt/536YxQgFCAUHv/g+zQqqGEvyiMXhsCwVpoy7UcFYgmlw -40g3+ejwvlO3YA67gQQKebEv6/Laz1hVNiXT0m3okAXWxXgF/g2eBO5NTRdtaWn3 -VNH5ub+LOr6cMhk9BAtKgRG+xeh8/2SqH12UbwtlmxqnBAfHtqlE6yJ1ViMDHxF9 -101xJlEONmC3fcEAjShK6LEbFwPJns3WbGc0ds36CzXWtO29XGssr+YoiF9e3Eus -/XQjmjOJxRoWkNEYsxlJ3IRH2vUcdCoAp8IlD7JYxx8UBCSJDBo7/0QKU6INeWjo -5+aNbaLAJULSKo1LTZjjANm+G+KcSnbn5Ed8fmY+D61A5/7WMIVxq/uDLFvxCnRG -QcLbtqbPztiWwWZOuTwNTA3bfAhEG0ZzNr+0z33jW5T9ChvdutgxJMf3Khazx9cx -mWyCpJwtSv7hSbp4nCS2fmHCum2yIrOnou8TSOlQFERZ3UEZMgLpWeupH/W5C3Ad -rOspFrK6K8a/iNSs5OdYUIK2iHddTs5u7AEZ9I5MTuYnccuGuXfQTTA06TJvJTax -c2oDbXMnXs4pHLiiSRp34IHIYubdrj8X5vTODC5djl8h1167ToXo5zGdXqT1om+u -4ndNLbbI1vld5G7KAL6TlTETg+N7S8v3KYoBEWzykwgqqppWnWTqPWQxM8Iph5ly -AQlzz7feERi/h/s57RZ5ksoVAdbtk2U6wgHnLrWhKZ7+ZOAfpNAjGHwWyXTzylXo -zQ9A8Kmd0jBMsru4fsGpldf4lTsqO/abUSWrAAREGnlz/ZjEb944Yox7JUhWC15C -WxXK2rFbiF3S0HtEvU17rdn4HCsZBilnY+hTpHj1MA6O451/A3ghxGXFKz/9LUcS -YBRQJaSM3hTqC3WoTVBeVc5nCFOpu4F89JqhEgXOLKweueMbTMRSNm93tXWT13s3 -Q/o0pNJv/K6+bIQwsX/oDafMXcW7STxQJObbAleRbcn8/rGS2eEnVZ6907faUR/L -7eu9vgAa/jh9FHpZ0Q== ------END ENCRYPTED PRIVATE KEY----- diff --git a/libs/ssl-config/src/test/resources/certs/pem-utils/key_pkcs8_encrypted_pbes1_des.pem b/libs/ssl-config/src/test/resources/certs/pem-utils/key_pkcs8_encrypted_pbes1_des.pem new file mode 100644 index 0000000000000..76d36a079055c --- /dev/null +++ b/libs/ssl-config/src/test/resources/certs/pem-utils/key_pkcs8_encrypted_pbes1_des.pem @@ -0,0 +1,29 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIE6TAbBgkqhkiG9w0BBQMwDgQIzMStkKSpOt0CAggABIIEyNdtzS+2uzAtCF35 +SEDSWBbtxkUAyQHxEjMxkzH8xE/60slG4yE3oPomRoE4hXOs1EUzwvKOJ7ykPXzc +zBuRTFns/b/A2ycfUOyTyblH0y2rXVcSN7Q/qVktcOoeg6mIuGHfXyJA4J9/neyy +SVGFNEWSa3kS6VtbS330deCrM6XXZmhusHMWmdmH+8jjEFrRksl/53P64VXO/THs +RtvtVJ8kGb49e38diMLuEpWbB9Pd1Nkqa4rgpcoYv2AuXXkBkDvs2iTsiSpCRuuQ +WpsKTNijVzv59LjLKki6JH7NxUef0C+MiYq+4Okbxk9apJXd5HsOEtGbVfTEOojT +bW03BHX4q/6BocdQLzMKILjkBs9XGIckRSFVId/+a1shAtAHISdIy0jq6tTCpScM +JIv8h3GhopF0EeVcij2KAEHTG3ky7RqpLZ6gTEUHDNhiNTZlMVNYo6vFk6agDzUx +Oh59UciG1t+LewpoLQy6n7PGcwoE9mTxXCWQt15RKVK+LKsWgShI4uBDhg4GMQfy +9CQT0YMXBpJQXPtf2cnpTCBFJptp1JtapnKBiHJzPmNPa0NK55dXPL6v89fFrCKp +3wurCYdNmLrS/qlhjva3/TXCfTZNQmCfl9DK+5q7nG1HTZYDfyPoAppITKbrUV9J +BSlFbBeIxqoN7bOpVhBXWYTSJBBokJED4mjwtFFMI5XE/4VTsqZ83ASjfv13xAsA +AJ+2kfjzFL2DXSXGiiPzipCeaZHFayJp6v5+81+76bXBwvrTLJ+/vvzXSOCBma2y +51qDxMhBwNewUdWsGUorcQ2lQzeRdeyFjeLNMgm3p8BXvTweae+raT9AJbtA1PvL +j7k312+DvFqg5VZkwM03kvTJeR2YBMQZub0e5biqIe8l8308Q8pZo9HTN4exGDfm +R67yLryCUPHcDfVdZoKmYeDv5h6e0cvnu3b+6ML2SVfMJ+yFqJFcWjQsr8furG0I ++3bACz9ykf5TcjjUV4ewQQp0uC0ryFBXxho1g3V4hJf86luEIqayoPLXkOCEhcy1 +oyY6h6tKXSlcYUHJagGqMyucRrs/mGcx4/YURyfxVNWQkCcUqA//+fEhWOBzFMiY +vkVWERW8KjlUtI+/kylUsgiJAIJpNJPXnltRDhdE/OT8kcxGYtl+CEIl/VN0N5nW +dNNoFN4E+zeR/KrEjhnRby/MpXHtNHVNVJbXARAkHsfCtWQ148ewuOx4IPMMiQ/C +z0DVv5GDP9+ObdW6kge/t9+fexcMH/DzfLDqO/qmP5xni4xP0JYU6wkzZ6k/F/Bz +s80PwJ/Y7LmT+1srqASm/Fetidb/shVh4VqKa5H8dYhnXfWKHghVR590qahAZtsm +1M7iqyYRW1nIplqtCPFCHSm/KDRb4Qwe/U+wjB5cYDFRfpoiZgfL+s7CWM0NU2Yp +RDW7ozCjf+w6XoCdlVZI2JppJA+zGWtUzznaTIe2RL9ioVxsREbnL/I+n0tzuLP3 +vqeyT4EfEGbcooEIPgJsARp0w20PqpqTgCMc42n4QWi6QDwdgAEP3Lob9mbYSrvp +OQWE3MxFEVfAyuaoBYJgP+aDY+UU55VwAfZeiW1+jfsvq7Uqcd9gVxwJdVA2zdlH +LXxWg4lHo5gLDVXHtQ== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/libs/ssl-config/src/test/resources/certs/pem-utils/key_pkcs8_encrypted_pbes2_aes.pem b/libs/ssl-config/src/test/resources/certs/pem-utils/key_pkcs8_encrypted_pbes2_aes.pem new file mode 100644 index 0000000000000..005d4135e9215 --- /dev/null +++ b/libs/ssl-config/src/test/resources/certs/pem-utils/key_pkcs8_encrypted_pbes2_aes.pem @@ -0,0 +1,30 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQILJlhk+DPgdgCAggA +MB0GCWCGSAFlAwQBKgQQ/UWQTH4Tb5Lg6kkhJHSmmASCBNDFk3eueF24FbgZH0Es +LiX3B48Vgl4MK+s1uWfs81Vfd6azLlSGzlrgCUnNPm0RYCpUxtaFyHFEc4Rera6W +22x/r1GUgoGOJKRt4Cv9VmAFKybC+3owsN7/NKB3WD05fl+C3s3qpcv+iq9e83TG +aaFglWm5xzKurFQ8eqnpUMOg4wVLedqj57ySx81H/9wbWvnZf7+P0V96O53zZe7f +0LaV+DRgj9fHclqwTtrHT92GQKyzhVtBc012qN0IZCNQQJU64o1X+xGmwzhvLGLd +gFi4DtK41BM3jLvl2r0fV3j/jJr8IWmsNYzQt2DW/yNA/waqwuqyZVz/6d9Kn42h +g+LfdTj2IrtCHoUCJDc80v0e6zUaFu+KYyWqkGQUH8fNYppcZEhGUsezfB1Tthtr +Wb2axp/CkQKbMRRR6lrGK4swDuGvtofnWBHHb/ORJcmpDEs72njLYMPlljdfH1ra +PuXHeSKdLB6yec0uTtzAspeCkmXJ4lQBuKyWNgZo7s4xgbkbbQ78rGqOQKtvbjVQ +2joxF6lB7kUMgx3xDgRizI+J3eGPgRBjqHVonF8kbKx9aNlwXpCYRw8z+j6Hagah +cJbSOf3AynVcMZqDrpK0ZZQJyDoPQ4FzO/x26NdcIR2mWmGK45D+sApAgr2OESWI +YBjNyE3yA7UhlM0L5rJ8qMtbkx2/sdCndz015Wa+ZfKCmkBRFvdkBZOsc7dYzpeM +bgtIRUySOvw5QjRpjjghAzZmQMiSewozXZGnlDve3ftxUlxAbm/VPeKJr3H1M8gS +ysLQm0Le9QG3Hl17s/7Eo/ZcQyo5jH7aO2tdLUY+jiAahuDzBnrmqZWJIILxxPM+ +tlqt9kmslkUz1V/bYpl8cTB6Srd2M4cRc1nHXA887EtJs3siIxKHanwu9/xaOv9G +7OUwr/zfr77hFWZAvT/0Ln26p46TwD7nK44b/sbJhRkmXl/lb3znUbkH5U8qkIny +d6kRj6/5OjBIPqF4wEjt2v2OuaL5S31e6/up0yb2fazKfHqv0A4NI3zuPKiQH7Iy +yQjqIoNmGMEOEcLfkJl8ZSaxGdHAqzZCUEzin9Xjw3nMSWOsNo+SKp0LyjgDoidm +MuYtM7uSKr632SYEHNjgp/TNAuQ875ebq573VAd9DwL49/BY9H68GSKEGTv50IuT +V5r7wlK1lWkoHCbDNTa59R/PIr+1zxpZ+rYo9rSHOHYNp/lCYTRpQtoxk4jfpreA +QYVLQ+6iBhsZHL4JX0vvj0mBge3tELrOu+wNpnA0EWiqV6DCuBzNkZVUmDClU4y4 +jfQ+VxGdOZ6wbaPvl0ocsSqOvmdQiW4LNqF6RTIZ3q0dGzZq0CyVjhp/vqDCYRPU +RJjSjubjWOidKIQwc/az3uMF5wiJlwHmzlrAK0mmxbTa32sw9qz16E+UsbJw8ujy +E/aaJvli86mHlQIzO+K0u27c/7a960Jg8vdbmnYn20YbBwll9ivnoXbJ6/h22Fpw +jlu+anmUKXx0cyxQMe97VMqkOAJUCobAEjIrHm7XTLo29Dh/SaTy1spLAlTZ+12W +C2E65oJAVL+fh2BuNGCWG6AjMUaDnvoUbc0ClTsN138fLaBg8Qf3UaqwyZ7WmGEP +JhwAbR1VXQOHLlzJ5xqroNvDuw== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/libs/ssl-config/src/test/resources/certs/pem-utils/key_pkcs8_encrypted_pbes2_des.pem b/libs/ssl-config/src/test/resources/certs/pem-utils/key_pkcs8_encrypted_pbes2_des.pem new file mode 100644 index 0000000000000..110e7b5e2a27b --- /dev/null +++ b/libs/ssl-config/src/test/resources/certs/pem-utils/key_pkcs8_encrypted_pbes2_des.pem @@ -0,0 +1,29 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFCzA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQISYrz2l4tmYACAggA +MBEGBSsOAwIHBAgqwuBynTK44ASCBMir0L/8IbtAjZCpBkHJ8ytKSP2KEivv+PsW +Xe+kwmKIIbvTgiVM7LVppTSpb6B0So0vOirm0asbKmEBj/KKmnzkbTRx/nbkPQGc +TnI1bseqo8JgjH8TglA3ozkpwNFZf4CMx8oV6yXvl66eKn6BMFbdLgVorqROhm6a +ONo2YbfvBZFHapwkBfS62nOAHs8KIqGQEwANimAwMQYpEHPTuDOpHGnNMM4AY2bu +84RqWfhMXgJtwJxjHCtSYCx05cNDpfiXjjKhr9YJwf+8fjooSmMPdZba2TeGiUWn +tUi4BL/fljk28gRUhLgcktmyoF+l2eYXNmdgJob6wKJSOhbONqxiGIGpiB527h8B +IF3unyJq/rZ44Af73i6GtNxZo5I+rXPa9uC0+159zhdGkToSLIlwUnQ9xTzgxNuc +gQhMKBlJoK1vOalfWtUHz+27JMmMYIzfdLdBA4mYb4YTwjebB7KIwEPJO6ufIXq/ +4t+TIbSSqCxkrqMIdBslB6ciOcYomLg6vK0xVnVgJA+XhzAgVmohuBZUmpSGbplE +2JXx2pKAjdiZ2X0xTJ3zbybNC3GdsbUskd4kUciJfSqSXLsm7crgJdSc1REhEI+k +mIpBU9yaEFN8S43TcQI6eB5rOVW0Tm8cPkH86S/XP1zYlgNh1zkqcO7Z0lYMTqur +3KEm2zqMUMwsOiRtwFXNirC7St73GTMFzmtdgLGywzxPas0gksSqOt1v/Gq9G7FQ +QJK4T3sOJeSMSIYzt/GIdB+Ha4wzKhaSWqdZnmskhTiXgIeLu0BRXgdY3lhg5Q+2 +xtR0TLVt26d+N03kj5HZ4Jl+DNWM3JY01ycZ/lk/CHERfpRLRGXXhXt01UloNNL2 +KmPdfbJhaCmsYnIXs02fHC6UdD5kXDRCNx9U4W9F0BAHU9brNNowtOgl4FzlTXYD +UEZk1zBPojOBfegaUiwOs60u8SMdHjgpz3AcG5YWp3idiLo9VhizYCDgv8XurSZD +KH+bCNgE9VMhsLZkyoOtZ5EmVTf2ZmTOIaTU2ddakhfLsAXQt30rAAU2DYAreDT0 +G2ZotpdxfIh98J0kVLrPKcOKxfshH55N6EWJK0YaXgvllBSzvR/l7EJU33A/FMPZ +bXWHfeRsyApXsefroMfqAuuyFAUYKFt7dPAyNpbmPw3hS9ZcKn7GSGrMKRisDuDM +bdrI2hCV/ylYIWUkj2GA/B1NGZ+iuYUKzlB37cjDeoqZhmVAY5Ns+U3+7FMAedGn +UmvM0U+nYWLx78EvzhxUZeSAgmct8NFlPLaxp964zogoMZq5Ah7RQ7fl5nr+NSBj +lPTcajhFBkwm1yEFpxzpL2LtMPEDbbInlEhKx+OEtxLTL3rlV0aZoRy4TYaToZvA +AukDSMg89XAKTSP/CtiKzO7b+iXficoFKSrUHLtyBqd5Wdv79SMfK8Jq0S9Tn5Nl +J4tI92uy/LIbR+MjWm8ViiCiRDThqGtbE+RHLY2JNsB7pSV0JLn13n1OQXi4SxF5 +s92J7C4fHX3pxziUNdMxYvXk6KYQrSBZe/Mrr0444Pmo94Sz1gwbRI4p+7r/A3h4 +5iVFoKf75q/fxww76gS0jMAoAnSEtYikKe/3c3PQWzdyh+uN/KqaliycRvyGf9s= +-----END ENCRYPTED PRIVATE KEY-----