Runtime Decryption in WebLogic

Here are the detailed steps for encrypting and decrypting Java class files at runtime in a WebLogic server environment:

Step 1: Encrypt the Class Files

  1. Generate an AES Encryption Key:

    • Use a secure method to generate an AES key.

    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import java.util.Base64;
    
    public class KeyGeneratorExample {
        public static void main(String[] args) throws Exception {
            KeyGenerator keyGen = KeyGenerator.getInstance("AES");
            keyGen.init(256); // 256-bit key
            SecretKey secretKey = keyGen.generateKey();
            String encodedKey = Base64.getEncoder().encodeToString(secretKey.getEncoded());
            System.out.println("AES Key: " + encodedKey);
        }
    }
    • Save the generated key securely. Example output: AES Key: abcdefghijklmnopqrstuvwxyz1234567890ABCDEF

  2. Encrypt the Class File:

    • Use the AES key to encrypt the class file.

    import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.util.Base64;
    
    public class EncryptClassFile {
        public static void main(String[] args) throws Exception {
            String key = "your_base64_encoded_key"; // Replace with your key
            byte[] keyBytes = Base64.getDecoder().decode(key);
            SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
    
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
    
            byte[] classFileBytes = Files.readAllBytes(Paths.get("YourClassFile.class"));
            byte[] encryptedClassFile = cipher.doFinal(classFileBytes);
    
            Files.write(Paths.get("YourClassFile.class.enc"), encryptedClassFile);
            System.out.println("Class file encrypted successfully.");
        }
    }
    • Replace "YourClassFile.class" with the path to your class file.


Step 2: Deploy the Encrypted WAR File

  1. Replace Original Class Files with Encrypted Ones:

    • Rename the encrypted class file with the .class.enc extension and place it in the same directory within the WAR file.

    mv YourClassFile.class.enc /path/to/war/WEB-INF/classes/YourClassFile.class.enc
  2. Repackage the WAR File:

    • Use the jar command to repackage the WAR file.

    cd /path/to/war
    jar -cvf ../encrypted.war *
  3. Deploy the WAR File:

    • Deploy the encrypted WAR file to your WebLogic server using the WebLogic Administration Console or the command line.


Step 3: Configure Runtime Decryption

  1. Modify the Application to Decrypt at Runtime:

    • Add decryption logic to your application to decrypt the class files at runtime before loading them.

  2. Load the Decryption Key Securely:

    • Store the decryption key securely, such as in a secure key management service or environment variable.

  3. Implement Custom ClassLoader:

    • Implement a custom ClassLoader that loads and decrypts the class files at runtime.

    import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.util.Base64;
    
    public class EncryptedClassLoader extends ClassLoader {
        private SecretKeySpec secretKey;
    
        public EncryptedClassLoader(ClassLoader parent, String key) {
            super(parent);
            byte[] keyBytes = Base64.getDecoder().decode(key);
            this.secretKey = new SecretKeySpec(keyBytes, "AES");
        }
    
        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            try {
                String path = name.replace('.', '/') + ".class.enc";
                byte[] encryptedClassFile = Files.readAllBytes(Paths.get(getClass().getResource("/" + path).toURI()));
    
                Cipher cipher = Cipher.getInstance("AES");
                cipher.init(Cipher.DECRYPT_MODE, secretKey);
                byte[] classFileBytes = cipher.doFinal(encryptedClassFile);
    
                return defineClass(name, classFileBytes, 0, classFileBytes.length);
            } catch (Exception e) {
                throw new ClassNotFoundException(name, e);
            }
        }
    
        public static void main(String[] args) throws Exception {
            String decryptionKey = "your_base64_encoded_key"; // Replace with your key
            EncryptedClassLoader classLoader = new EncryptedClassLoader(ClassLoader.getSystemClassLoader(), decryptionKey);
            Class<?> clazz = classLoader.loadClass("YourClassName");
            Object instance = clazz.newInstance();
            // Invoke methods on the instance
        }
    }
  4. Package Your Custom ClassLoader:

    Compile your custom ClassLoader and package it into a JAR file. This JAR file will be included in your WebLogic server's classpath or within your application.

  5. Modify weblogic.xml:

    The weblogic.xml deployment descriptor is used to configure various settings specific to WebLogic Server. To ensure WebLogic uses your custom ClassLoader, follow these steps:

    • Open the weblogic.xml file located in the WEB-INF directory of your application.

    • Add the necessary configurations to use your custom ClassLoader.

    Here’s an example of what your weblogic.xml might look like:

    xml

    <?xml version="1.0" encoding="UTF-8"?>
    <weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-web-app
        http://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
    
        <context-root>/yourapp</context-root>
    
        <container-descriptor>
            <prefer-application-packages>
                <package-name>com.yourpackage.*</package-name>
            </prefer-application-packages>
        </container-descriptor>
    
        <library-ref>
            <library-name>custom-classloader-lib</library-name>
            <specification-version>1.0</specification-version>
            <implementation-version>1.0</implementation-version>
        </library-ref>
    
        <class-loader-structure>
            <class-loader-structure>
                <class-loader>
                    <name>customClassLoader</name>
                    <system-properties>
                        <property>
                            <name>encryptedClassLoader</name>
                            <value>com.yourpackage.EncryptedClassLoader</value>
                        </property>
                        <property>
                            <name>decryptionKey</name>
                            <value>your_base64_encoded_key</value>
                        </property>
                    </system-properties>
                </class-loader>
            </class-loader-structure>
        </class-loader-structure>
    </weblogic-web-app>

  6. Deploy the Application:

    • Ensure the custom ClassLoader JAR file is included in your WAR file or placed in the WebLogic server's classpath.

    • Deploy the WAR file to your WebLogic server.


Important Considerations

  • Security: Ensure that the decryption key is stored securely and not hard-coded in the application.

  • Performance: Runtime decryption may introduce performance overhead.

  • Testing: Thoroughly test the application to ensure that the decryption process works correctly and does not introduce any issues.

Last updated