Skip to main content
dwaynea8754223
Known Participant
September 14, 2023
Answered

Coldfusion 2023 seems to be missing some JAVA

  • September 14, 2023
  • 2 replies
  • 4496 views

var keySpec = createObject("java", "javax.crypto.spec.PBEKeySpec").init(arguments.password.toCharArray(), salt, 128, 80);

 

results in error:

java.lang.reflect.InaccessibleObjectException: Unable to make public boolean com.sun.crypto.provider.PBKDF2KeyImpl.equals(java.lang.Object) accessible: module java.base does not "opens com.sun.crypto.provider" to unnamed module @db99785

 

this code works on previous versions of CF/Java. Is there something I should add to the JVM arguments?

Correct answer xfreeman89x

I’m aware of this function, which is in this repository (https://github.com/marcins/cf-google-authenticator/blob/master/authenticator/GoogleAuthenticator.cfc), and as far as I’m concerned, I don’t feel comfortable having to add exceptions to the server that might increase the attack surface by using the configuration

--add-opens=java.base/some.package.name=ALL-UNNAMED


Instead, I changed the function by using ColdFusion’s native functions that do the same thing. Specifically, the GeneratePBKDFKey function is what we need (https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-e-g/generatepbkdfkey.html).

Here’s the code with the changes:

public string function generateKey(required string password, string salt = "", numeric iterationCount = 128, numeric keySizeBits = 80) 
{
    // Se salt non fornito, generiamo 16 byte casuali
    if (Len(arguments.salt) == 0) {
        arguments.salt = generateRandomString();
    }
    else if (Len(salt) != 16) {
        throw(message="Salt must be 16 bytes", errorCode="GoogleAuthenticator.BadSalt");
    }

    var derivedKey = GeneratePBKDFKey("PBKDF2WithHmacSHA1" , arguments.password, arguments.salt, arguments.iterationCount, arguments.keySizeBits);

    return Base32encode(binaryDecode(derivedKey, "base64"));
}


Hope this helps.

Best regards,
Salvatore

2 replies

BKBK
Community Expert
Community Expert
September 14, 2023

ColdFusion 2023 is not missing the Java class, javax.crypto.spec.PBEKeySpec. It is right there. You can confirm this by running the test code:

 

<cfscript>
    testObject= createObject("java","javax.crypto.spec.PBEKeySpec");
    writedump(testObject);
</cfscript>

 

Though ColdFusion is weakly-typed, newer versions get progressively more accurate with regard to type. So CF2023 might not tolerate code which CF2016 accepted. My guess is that that is the issue you now face.

 

Here and there, your code uses Java types as if they are native CFML types. For example, the constructor, createObject("java", "javax.crypto.spec.PBEKeySpec").init(arguments.password.toCharArray(), salt, 128, 80); requires that the argument salt be a Java byte-array. However, your code is passing it as a ColdFusion array. In fact, the code is mixing up byte-array and CFML-array as if they are interchangeable. Thus, salt is initialized as a ColdFusion array, []. Yet the same variable is used to store buffer.array(), which is a Java byte-array. That might be the cause of the issue.

 

Now, on to a possible solution. I shall assume that the argument salt is coming into the function as a ColdFusion array, not as a Java byte array.

 

Then:

  1. Replace 
    remote string function generateKey (required string password, array salt = [])
    {
        if (arrayLen(salt) == 0)​
     with
    remote string function generateKey (required string password, array salt = [])
    {
        // Convert from CFML array to Java byte-array 
        var saltByteArray=javacast("byte[]",arguments.salt);
        if (arrayLen(arguments.salt) == 0)​
  2.  Replace

 

arguments.salt = buffer.array();
secureRandom.nextBytes(arguments.salt);

 

with

 

saltByteArray=buffer.array();
secureRandom.nextBytes(saltByteArray);

 

3. Replace

 

var keySpec = createObject("java", "javax.crypto.spec.PBEKeySpec").init(arguments.password.toCharArray(), salt, 128, 80);

 

with

 

var keySpec = createObject("java", "javax.crypto.spec.PBEKeySpec").init(arguments.password.toCharArray(), saltByteArray, 128, 80);

 

 



BKBK
Community Expert
Community Expert
September 14, 2023

A demo to illustrate:

<cfscript>
cfArray=[];
byteArray=javacast("byte[]",cfArray);

writeOutput("Type of CF array [] is: <strong>#cfArray.getClass().getName()#</strong>");
writeOutput("<p>");
writeOutput("Type of Java Byte array obtained from [] using Javacast is: <strong>#byteArray.getClass().getSimpleName()#</strong>");
</cfscript>

 

Output of the demo:

 

Charlie Arehart
Community Expert
Community Expert
September 14, 2023

Before presuming that's the issue (or asking for your values passed into the two args, so we can try to recreate it), can you first just edit the file in any way to force its recompilation?

 

Second, in what version did it work? If that is still around, perhaps someone dropped in a class or jar that was being leveraged, such that putting it into cf2023's same folder could fix things. 

/Charlie (troubleshooter, carehart. org)
dwaynea8754223
Known Participant
September 14, 2023

thanks for the quick response.

this is a function in a cfc. not sure I understand the path to force recompilation. I don't believe there are any custom classes or jar file. This was working on CF2016. I believe all Java is native. That said, I read a little about modules, or lack there of, and through maybe the JVM arguments may be required to load the crypto class.

 

 

    /**
    * Generates a Base32 encoded secret key for use with the token functions
    *
    * @9397041 password a password to be used as the seed for the secret key
    * @9397041 salt a Java byte[16] array containing a salt - if left blank a random salt will be generated (recommended)
    * @Return the Base32 encoded secret key
    */
    remote string function generateKey (required string password, array salt = [])
    {
        if (arrayLen(salt) == 0)
        {
            var secureRandom = createObject("java", "java.security.SecureRandom").init();
            var buffer = createObject("java", "java.nio.ByteBuffer").allocate(16);
            arguments.salt = buffer.array();
            secureRandom.nextBytes(arguments.salt);
        }
        else if(arrayLen(salt) != 16)
        {
            throw(message="Salt must be byte[16]", errorcode="Authenticator.BadSalt");
        }

        var keyFactory = createObject("java", "javax.crypto.SecretKeyFactory").getInstance("PBKDF2WithHmacSHA1");
        var keySpec = createObject("java", "javax.crypto.spec.PBEKeySpec").init(arguments.password.toCharArray(), salt, 128, 80);
        var secretKey = keyFactory.generateSecret(keySpec);
        return Base32encode(secretKey.getEncoded());
    }

 

 

 

Inspiring
April 2, 2025

I don't have any issue with this...appears like a better solution. My only issue is that the java module was loaded on previous versions of CF. I upgraded to 2023 and my app stopped working. At the very least, the JVM config changes should be documented, and sometimes it's difficult to know exactly what these modules do, so the docs should elaborate sufficiently.


@dwaynea8754223 Using --add-opens explicitly forces the JVM to open private packages, bypassing the newer security measures. This expands the attack surface (if untrusted code ever runs on your JVM) and breaks encapsulation, meaning future changes to those internal classes could lead to additional problems.

In short, --add-opens is not “dangerous” in the immediate sense, but it’s a temporary patch that circumvents Java’s newer security mechanisms. ColdFusion 2023 runs on a more recent Java, which explains the unexpected error. I agree there should have been clearer documentation on this, but changes in the broader Java ecosystem aren’t always highlighted in CF release notes.

I hope this clarifies why it happens. You can certainly keep using --add-opens, but it’s a workaround that slightly undermines Java’s isolation. If you want to avoid it, consider ColdFusion’s built-in GeneratePBKDFKey (I discovered was included already in ColdFusion 11) function or a third-party provider like BouncyCastle, though that can sometimes involve classpath conflicts in CF.
Hope this can clarify your concerns, often some undocumented changes comes from the underlying Java updates and are really difficult to discover when you are using Java classes in your ColdFusion code with createObject function.

Salvatore

Salvatore Cerruto