v6.6.x Problems with gauth backup scratch codes when encrypting

62 views
Skip to first unread message

Bill Baran (Sirkut)

unread,
Apr 7, 2023, 3:29:27 AM4/7/23
to CAS Community
Hello,

When I don't encrypt the scratch codes, by leaving cas.authn.mfa.gauth.core.scratch-codes.encryption.key unset, backup recovery keys work fine.
When I encrypt them then they seem to store fine but an exception is thrown when I try to use them.

2023-04-06 15:43:51,053 WARN [org.apereo.cas.util.function.FunctionUtils] - <EncryptionOperationNotPossibleException>
org.jasypt.exceptions.EncryptionOperationNotPossibleException: null
at org.jasypt.encryption.pbe.StandardPBEBigIntegerEncryptor.decrypt(StandardPBEBigIntegerEncryptor.java:586) ~[jasypt-1.9.3.jar!/:?]
at org.jasypt.util.numeric.AES256IntegerNumberEncryptor.decrypt(AES256IntegerNumberEncryptor.java:116) ~[jasypt-1.9.3.jar!/:?]
at org.apereo.cas.util.cipher.JasyptNumberCipherExecutor.decode(JasyptNumberCipherExecutor.java:45) ~[cas-server-core-util-api-6.6.1.jar!/:6.6.1]
at org.apereo.cas.util.cipher.JasyptNumberCipherExecutor.decode(JasyptNumberCipherExecutor.java:19) ~[cas-server-core-util-api-6.6.1.jar!/:6.6.1]
at org.apereo.cas.util.crypto.DecodableCipher.decode(DecodableCipher.java:37) ~[cas-server-core-api-util-6.6.1.jar!/:6.6.1]
at org.apereo.cas.otp.repository.credentials.BaseOneTimeTokenCredentialRepository.lambda$decode$0(BaseOneTimeTokenCredentialRepository.java:69)

It seems to throw one of these for each scratch code, suggesting it cannot decrypt them.

Stepping through the code, the problem seems to first show up in NumberUtils.processBitIntegerEncrypted(): 71
         System.arraycopy(byteArray, (initialSize - 4), encryptedMessageExpectedSizeBytes, 0, 4);
encryptedMessageExpectedSizeBytes just ends up being [0,0,0,0].

I"m using
cas.authn.mfa.gauth.core.scratch-codes.encryption.key=DTcyfU3VagtfbyxvmFOTM6N0tfeLUTuWlQy_R83GZIo

My original source was using 
cas.authn.mfa.gauth.core.scratch-codes.encryption.key-size=256
but I saw another example with
cas.authn.mfa.gauth.core.scratch-codes.encryption.key-size=16
But both seem to behave the same.

I'm storing the codes in an Oracle database. And they look like:
-45042011719129430758667059667890329945100000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-79896184794635338776074275007870804906200000000000000000000000000000000000000000000000000000000000000000000000000000000000000

It seems like they have too much zero padding at the end?

Anyone have any ideas?

Thanks,

Bill Baran

Y G

unread,
Oct 3, 2025, 11:13:57 AMOct 3
to CAS Community, Bill Baran (Sirkut)
Hello,
Sorry for replying for an old post, but after making a quick search here about it, it seemed appropriate to mention it here. 
This issue still exists in 7.3.0-RC4.
İ tried to dig deeper, and it seems when you don't enable scratch code encryption, everything works fine. Generated scratch codes are saved to db with no problem. But when you enable stracth code encryption via giving an encryption key, it seems generated encrypted data is not saved to database correctly, and the result is that ...NotPossible exceptions in the logs, trying to decode wrongly saved encrypted data. Here's my comparison(i've configured Oracle Db when using JPA Google Authenticator Registration)

These are the encrypted scracth code values generated when registering for a Gauth registration:
0 = {BigInteger@30766} "74390327901165487589042810459668035849965803676032964530798248789989118113915071073724609341869107731245151461522467880697904"
1 = {BigInteger@30767} "31098340099237752696611328623475865901965829521053904268191167607710748925647405841488195117829588026398554928042734308556848"
2 = {BigInteger@30768} "48866283722722524070646562624431068327656549331910107200557373347389263660524925534527052815330236684521350282046463006474288"
3 = {BigInteger@30769} "79550534388854180271521592348935516269389872899526914767802743611662281484131413831867033783920870484440519501135977402859568"
4 = {BigInteger@30770} "-45554420184713133554819952257786444999779498264418386315388310059246872189840796162401323743639635010650104503797263926034384"
and after the db save operation, i found out that this is what saved in db: 
74390327901165487589042810459668035849900000000000000000000000000000000000000000000000000000000000000000000000000000000000000
31098340099237752696611328623475865901900000000000000000000000000000000000000000000000000000000000000000000000000000000000000
48866283722722524070646562624431068327600000000000000000000000000000000000000000000000000000000000000000000000000000000000000
79550534388854180271521592348935516269300000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-45554420184713133554819952257786444999700000000000000000000000000000000000000000000000000000000000000000000000000000000000000

it seems you cannot store > 38 digits in Oracle NUMBER type. 

Exposing unencrypted scratch codes in a database table is a security concern for me, like `come-and-hack-me` kind of invitation in my opinion, so, is there any way to make this encryption saving mechanism to work?

cause.png


Thank you and have a nice day.
YG

7 Nisan 2023 Cuma tarihinde saat 10:29:27 UTC+3 itibarıyla Bill Baran (Sirkut) şunları yazdı:

Y G

unread,
Oct 3, 2025, 5:02:31 PMOct 3
to CAS Community, Y G, Bill Baran (Sirkut)
Hello again, 
On the latest Cas Overlay(7.3.0-RC4), to make scratch code encryption work on Oracle db's quickly, i've prepared this CustomCipherExecutorForGauthScratchCodes, overriding the default one
And then, i've added this to the CasOverlayOverrideConfiguration, registering/overriding the scratch code encryption operations to this new one, using the configured key too: 

/**
* This is for fixing the gauth scratch code encrypted value Oracle Db saving problems. This one
* registers the new CipherExecutor instead of the default one defined in cas-server-support-gauth
* module:
* {@link
* GoogleAuthenticatorAuthenticationEventExecutionPlanConfiguration.GoogleAuthenticatorMultifactorAuthenticationCoreConfiguration#googleAuthenticatorScratchCodesCipherExecutor}
*/
@Bean
public CipherExecutor<Number, Number> googleAuthenticatorScratchCodesCipherExecutor(
final CasConfigurationProperties casProperties) {
val key =
casProperties.getAuthn().getMfa().getGauth().getCore().getScratchCodes().getEncryption()
.getKey();
return new 
CustomCipherExecutorForGauthScratchCodes(key, "googleAuthenticatorScratchCodesCipherExecutor");
}

Hope it helps.
Have a nice day,
YG


3 Ekim 2025 Cuma tarihinde saat 18:13:57 UTC+3 itibarıyla Y G şunları yazdı:
Reply all
Reply to author
Forward
0 new messages