From ebdbd1869fb33ea5e54699ad17acf3a0c2ef3ae1 Mon Sep 17 00:00:00 2001
From: muskaan62 <muskaanbegum23@gmail.com>
Date: Fri, 1 Nov 2024 10:19:51 +0530
Subject: [PATCH] fix issue-2530 encrypted private keys is not working issue

---
 .../jdbc/SQLServerCertificateUtils.java       | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCertificateUtils.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCertificateUtils.java
index e51328cfc..6a03f8b7d 100644
--- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCertificateUtils.java
+++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCertificateUtils.java
@@ -57,6 +57,11 @@
 import org.bouncycastle.openssl.PEMParser;
 import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
 import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
+import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
+import org.bouncycastle.operator.InputDecryptorProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
+import org.bouncycastle.pkcs.PKCSException;
 
 
 final class SQLServerCertificateUtils {
@@ -318,6 +323,8 @@ private static void logSuccessMessage(String nameInCert, String hostName) {
     private static final String CLIENT_KEY = "client-key";
     // PKCS#1 format
     private static final String PEM_RSA_PRIVATE_START = "-----BEGIN RSA PRIVATE KEY-----";
+    private static final String PEM_RSA_ENCRYPTED_PRIVATE_START =
+            "-----BEGIN ENCRYPTED PRIVATE KEY-----";
     // PVK format
     private static final long PVK_MAGIC = 0xB0B5F11EL;
     private static final byte[] RSA2_MAGIC = {82, 83, 65, 50};
@@ -384,13 +391,19 @@ private static PrivateKey loadPrivateKeyFromPKCS1(String key, String keyPass) th
             Object object = pemParser.readObject();
             JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
             KeyPair kp;
-            if (object instanceof PEMEncryptedKeyPair && keyPass != null) {
+            if (object instanceof PKCS8EncryptedPrivateKeyInfo && keyPass != null) {
+                JceOpenSSLPKCS8DecryptorProviderBuilder builder = new JceOpenSSLPKCS8DecryptorProviderBuilder();
+                InputDecryptorProvider decryptorProvider = builder.build(keyPass.toCharArray());
+                return converter.getPrivateKey(((PKCS8EncryptedPrivateKeyInfo)object).decryptPrivateKeyInfo(decryptorProvider));
+            } else if (object instanceof PEMEncryptedKeyPair && keyPass != null) {
                 PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(keyPass.toCharArray());
                 kp = converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv));
             } else {
                 kp = converter.getKeyPair((PEMKeyPair) object);
             }
             return kp.getPrivate();
+        } catch (PKCSException | OperatorCreationException e) {
+            throw new RuntimeException(e);
         }
     }
 
@@ -400,6 +413,7 @@ private static PrivateKey loadPrivateKeyFromPVK(String keyPath,
         ByteBuffer buffer = ByteBuffer.allocate((int) f.length());
 
         try (FileInputStream in = new FileInputStream(f); FileChannel channel = in.getChannel()) {
+            channel.read(buffer);
             ((Buffer) buffer.order(ByteOrder.LITTLE_ENDIAN)).rewind();
 
             long magic = buffer.getInt() & 0xFFFFFFFFL;
@@ -465,7 +479,8 @@ static PrivateKey loadPrivateKey(String privateKeyPemPath,
 
         if (privateKeyPem.contains(PEM_PRIVATE_START)) { // PKCS#8 format
             return loadPrivateKeyFromPKCS8(privateKeyPem);
-        } else if (privateKeyPem.contains(PEM_RSA_PRIVATE_START)) { // PKCS#1 format
+        } else if (privateKeyPem.contains(PEM_RSA_PRIVATE_START) ||
+                privateKeyPem.contains(PEM_RSA_ENCRYPTED_PRIVATE_START)) { // PKCS#1 format
             return loadPrivateKeyFromPKCS1(privateKeyPem, privateKeyPassword);
         } else {
             return loadPrivateKeyFromPVK(privateKeyPemPath, privateKeyPassword);