Android Question [SOLVED]B4XEncryption Decrypt

Jorgelcr

Active Member
Licensed User
Longtime User
Hello,
I want to save the password field in an encrypted mysql table.
I do this using EncryptText. It is saved correctly. I have the problem to do the operation the other way around.
I get an error in the DecryptText function when I pass the value saved in the table.

Error :
o1WkPWBQVtrbZIwnk014ZES3FWF6Lt+FzwJU8WIQ5bWBKausJr1b7g== ' value saved in the table
Error occurred on line: 714 (B4XMainPage)
javax.crypto.BadPaddingException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT
at com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(Native Method)
at com.android.org.conscrypt.OpenSSLCipher$EVP_CIPHER.doFinalInternal(OpenSSLCipher.java:602)
at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:365)
at javax.crypto.Cipher.doFinal(Cipher.java:2055)
at anywheresoftware.b4a.object.B4XEncryption.Decrypt(B4XEncryption.java:47)
at com.criollo.b4xmainpage._decrypttext(b4xmainpage.java:325)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:348)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:144)
at anywheresoftware.b4a.BA$2.run(BA.java:387)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7397)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)
 

Jorgelcr

Active Member
Licensed User
Longtime User
The problem is that every time I encrypt it generates a different string, then it doesn't match what's entered with what's saved

B4X:
'ALTA USUARIO'
Dim Su As StringUtils
Dim Crypt() As Byte         = EncryptText(password.Text, "XXXXXXXXXXX")
Dim TxtEnCrypt As String    = Su.EncodeBase64(Crypt)
            
ExecuteRemoteQuery(INSERT INTO Usuarios (ID, Usuario,Email,Password) VALUES (Null,'"& nombrecliente.Text &"', '"& mail.Text &"' ,'"& TxtEnCrypt &"')","ALTA")

**********
'COMPROBACION
ExecuteRemoteQuery("Select * From Usuarios Where Email='"& mail.Text &"'"" , "listusuarios")

' Respuesta job'

Case "listusuarios"
    Dim USUAR As List
    USUAR = parser.NextArray
    If USUAR.SIZE >0 Then
        Dim m As Map
        m = USUAR.Get(0)
                    
        Dim Su As StringUtils
                
        Dim BtCrypt1() As Byte= Su.DecodeBase64(m.Get("Password"))
        Dim TxtDeCrypt1 As String    = DecryptText(BtCrypt1, "XXXXXXXXXXX")
            
    end if
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
The problem may lie in your Encrypt/Decrypt functions which you have not provided, or perhaps your "Password" field is not large enough to accommodate the encrypted text. Also, I would like to reiterate what @Erel and @cklester indicated that you should never store passwords themselves, even encrypted ones. Just store a calculated hash of the password plain text plus your own salt value.

I would add some LOG statements to show the plain text and encrypted value before the INSERT and more LOG statements to show the value from the database and the decrypted values.
 
Upvote 0

OliverA

Expert
Licensed User
The problem is that every time I encrypt it generates a different string
That is normal for B4XEncryption. It uses a Salt when encrypting data. This Salt is randomly generated and serves to make it harder to decrypt your data via dictionary/brute-force attacks. There are two solutions to this:
1) Use an encryption method that does not use a salt. Only do this if you absolutely need to decrypt the information. For passwords, you usually do not decrypt them.
2) Use a hash. A hash algorithm will always give you the same result for a given string. Hashes are one-way and cannot be decrypted. This is perfect for passwords.

I do this using EncryptText. It is saved correctly. I have the problem to do the operation the other way around.
I get an error in the DecryptText function when I pass the value saved in the table.

Error :
o1WkPWBQVtrbZIwnk014ZES3FWF6Lt+FzwJU8WIQ5bWBKausJr1b7g== ' value saved in the table
I guess DecryptText is a little bit of a misnomer. It actually decrypts a byte array. You seem to be feeding it the base64 encoded string. You need to first decode the base64 encoded string and then feed the generated byte array and your password that you used to encrypt the data to DecryptText to decrypt your data.
 
Upvote 0

cklester

Well-Known Member
Licensed User
That is normal for B4XEncryption. It uses a Salt when encrypting data.

If that's the case, the salt needs to be stored in the database for later use. I'm not sure why an encryption algorithm, the data from which you expect to decrypt later, would use a secret salt. Kinda defeats the purpose of encrypt/decrypt. :-D
 
Upvote 0

OliverA

Expert
Licensed User
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Use an encryption method that does not use a salt. Only do this if you absolutely need to decrypt the information. For passwords, you usually do not decrypt them.
That's not correct. B4XEncryption can of course encrypt and then decrypt the encrypted data. The data includes the (unencrypted) salt.
 
Upvote 0

OliverA

Expert
Licensed User
1) Use an encryption method that does not use a salt. Only do this if you absolutely need to decrypt the information. For passwords, you usually do not decrypt them.
That's not correct. B4XEncryption can of course encrypt and then decrypt the encrypted data. The data includes the (unencrypted) salt.
Yeah that was a badly worded answer to this
The problem is that every time I encrypt it generates a different string, then it doesn't match what's entered with what's saved
It's the salt that generates a different output for the same input (plaintext and password). I meant to say to use a non-salted encryption method if the same output is needed for the same input. For his scenario though, he should really go for hashing (with a salt. See: https://auth0.com/blog/adding-salt-to-hashing-a-better-way-to-store-passwords/)
 
Upvote 0

Jorgelcr

Active Member
Licensed User
Longtime User
In the end fix encryption in md5. In the table I save the password value in md5, chosen by the user.
For the logging I generate the md5 entered by the user with the save and I access if it agrees.
To remember the password, I generate an automatic one and send it to the user by mail if he wishes, he can change it from his profile.

Thank you all!!
 
Upvote 0

OliverA

Expert
Licensed User
I save the password value in md5
You are on the right track, but I would not use MD5. I leave it up to you to do some research on that subject (MD5).
 
Upvote 0
Top