2FA Wrong TOTP

Hey,
I’m currently doing some testing with two-factor authentication.
For this I wrote a test script in Java to create a totp from an existing key.
I used the library “dev.samstevens.totp”.
The script works so far and I wanted to test it now in Lucee.
Unfortunately the lucee returns wrong totps. However, the time is correct when testing, so I don’t know what else it could be.
If I set the commandbox to Adobe 2021 the correct ones (like in the Java testscript) come out.
So the code works when running directly with java or adobe 2021, only on lucee it returning wrong results.
The only real dependency the library has is “Commens-Codec”. However, I included that in my test jar. Maybe the old “Commens-Codec” is loaded from the Lucee again, which has a bug?

Do any of you already have 2FA running or use this library?

My Code:
Java:

    public static String generate(String secret) throws CodeGenerationException, UnknownHostException {
        TimeProvider timeProvider = new NtpTimeProvider("pool.ntp.org");
        CodeGenerator codeGenerator = new DefaultCodeGenerator();
        long currentBucket = Math.floorDiv(timeProvider.getTime(), 30);
        return codeGenerator.generate(secret, currentBucket);
    }

test.cfm

<cfset time = createObject("java", "de.totptest.App").getTime() />
<cfset totp = createObject("java", "de.totptest.App").generate(secret) />
<cfdump var="#time#"/>
<cfdump var="#totp#"/>

application.cfc

component {
  this.name = "totp Test4";
  this.javaSettings.loadPaths = ["TotpTest-0.1.0-jar-with-dependencies.jar"];
}

Lucee version: 5.3.8.206
Java 8/11 (both tested)
OS: Ubuntu 20.04

try with 5.3.9-RC2

it now uses org.apache.commons.commons-codec;bundle-version=1.15.0, (was 1.9 in 5.3.8)

1 Like

Yep with 5.3.9-RC2 its working.
It seems to be a problem which commons-codec Base32 which was fixed in 1.10.
Is there a way that my library uses that version instead of 1.9? Or do i have to wait for the lucee 5.3.9 release?

Currently my “TotpTest-0.1.0-jar-with-dependencies.jar” included commons codec 1.15 but it seems lucee still uses the bundled version.

you’ll need to use java loader

You really shouldn’t need a java library with dependencies to do TOTP… In the past I did it using the java crypt functions directly, some java.math.* stuff… The only part that needed a java library was generating a QR code image.

It’s probably even easier nowadays since CF10 added HMAC functions.

i.e. check here
https://jasonsteinshouer.com/2019/05/26/totp-2fa-in-cfml.html
and here

There may be better options.

1 Like

This one’s cleaner.

It even uses qrcode.js to do the QR code.

The part in the cfc that does hmac can be modified:
i.e. line 84

        var key = base32decode(arguments.base32Secret);
        var secretKeySpec = createObject("java", "javax.crypto.spec.SecretKeySpec" ).init(key, "HmacSHA1");
        var mac = createObject("java", "javax.crypto.Mac").getInstance(secretKeySpec.getAlgorithm());
        mac.init(secretKeySpec);
        var buffer = createObject("java", "java.nio.ByteBuffer").allocate(8);
        buffer.putLong(arguments.counter);
        var h = mac.doFinal(buffer.array());

becomes something like

        var key = base32decode(arguments.base32Secret);

        var buffer = createObject("java", "java.nio.ByteBuffer").allocate(8);
        buffer.putLong(arguments.counter);
        var h = BinaryDecode( hmac( buffer.array(), key, "HMACSHA1" ) , "hex" );

The buffer part can probably be done with binarydecode as well.

Just use this existing CFML library

https://www.forgebox.io/view/totp

It doesn’t require any jars and already does all the hard math for you. It even generates the QR codes for you.

2 Likes

Cool thanks! :+1:
I will look into both. Without a extra library it would be a nicer solution!

I think when you use the QRcode generator it will ask for cfxzing as a dependency, which comes with a included java library.