Forum > General

[Solved] AES Decrypt

<< < (2/2)

Xor-el:

--- Quote from: lainz on May 11, 2021, 05:20:25 pm ---Hi, I'm using CryptoJS to encrypt a JSON with AES in the browser.

Now I need to decrypt that with FPC.

I know there is TDPC_Rijndael with Dcpcrypt package, but I don't know how to use it to decrypt.

I have this code working in Java:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---package ...; import android.os.Build; import androidx.annotation.RequiresApi; import java.nio.charset.StandardCharsets;import java.security.DigestException;import java.security.InvalidAlgorithmParameterException;import java.security.InvalidKeyException;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.util.Arrays;import java.util.Base64; import javax.crypto.BadPaddingException;import javax.crypto.Cipher;import javax.crypto.IllegalBlockSizeException;import javax.crypto.NoSuchPaddingException;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec; public class DecryptAES {     public static String decrypt(String secret, String cipherText) throws NoSuchAlgorithmException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException {         byte[] cipherData = android.util.Base64.decode(cipherText, 0);        byte[] saltData = Arrays.copyOfRange(cipherData, 8, 16);         MessageDigest md5 = MessageDigest.getInstance("MD5");        final byte[][] keyAndIV = GenerateKeyAndIV(32, 16, 1, saltData, secret.getBytes(StandardCharsets.UTF_8), md5);        SecretKeySpec key = new SecretKeySpec(keyAndIV[0], "AES");        IvParameterSpec iv = new IvParameterSpec(keyAndIV[1]);         byte[] encrypted = Arrays.copyOfRange(cipherData, 16, cipherData.length);        Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding");        aesCBC.init(Cipher.DECRYPT_MODE, key, iv);        byte[] decryptedData = aesCBC.doFinal(encrypted);        String decryptedText = new String(decryptedData, StandardCharsets.UTF_8);         return decryptedText;    }     /**     * Generates a key and an initialization vector (IV) with the given salt and password.     * <p>     * This method is equivalent to OpenSSL's EVP_BytesToKey function     * (see https://github.com/openssl/openssl/blob/master/crypto/evp/evp_key.c).     * By default, OpenSSL uses a single iteration, MD5 as the algorithm and UTF-8 encoded password data.     * </p>     * @param keyLength the length of the generated key (in bytes)     * @param ivLength the length of the generated IV (in bytes)     * @param iterations the number of digestion rounds     * @param salt the salt data (8 bytes of data or <code>null</code>)     * @param password the password data (optional)     * @param md the message digest algorithm to use     * @return an two-element array with the generated key and IV     */    public static byte[][] GenerateKeyAndIV(int keyLength, int ivLength, int iterations, byte[] salt, byte[] password, MessageDigest md) {         int digestLength = md.getDigestLength();        int requiredLength = (keyLength + ivLength + digestLength - 1) / digestLength * digestLength;        byte[] generatedData = new byte[requiredLength];        int generatedLength = 0;         try {            md.reset();             // Repeat process until sufficient data has been generated            while (generatedLength < keyLength + ivLength) {                 // Digest data (last digest if available, password data, salt if available)                if (generatedLength > 0)                    md.update(generatedData, generatedLength - digestLength, digestLength);                md.update(password);                if (salt != null)                    md.update(salt, 0, 8);                md.digest(generatedData, generatedLength, digestLength);                 // additional rounds                for (int i = 1; i < iterations; i++) {                    md.update(generatedData, generatedLength, digestLength);                    md.digest(generatedData, generatedLength, digestLength);                }                 generatedLength += digestLength;            }             // Copy key and IV into separate byte arrays            byte[][] result = new byte[2][];            result[0] = Arrays.copyOfRange(generatedData, 0, keyLength);            if (ivLength > 0)                result[1] = Arrays.copyOfRange(generatedData, keyLength, keyLength + ivLength);             return result;         } catch (DigestException e) {            throw new RuntimeException(e);         } finally {            // Clean out temporary data            Arrays.fill(generatedData, (byte)0);        }    }     public static void main(String[] args) {     }}
As well I have this example on how to use Rijndael:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---var  Cipher : TDCP_rijndael;  Key    : AnsiString;  IV     : AnsiString;   CBC    : AnsiString;  Buffer : AnsiString;begin  Result := '';  Key  := ??;  IV   := ??;  CBC :=DecodeStringBase64(sText);  Cipher := TDCP_rijndael.Create(nil);  try    Cipher.Init(Key[1], 128, @IV[1]);    SetLength(Buffer, Length(CBC));    Cipher.DecryptCBC(CBC[1], Buffer[1], 16);    Result := Buffer;  finally    Cipher.Free;  end;
Here the problem is how to fill the Key and IV, and use the salt as well like is done with the Java code.

Test data:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---text: 'hello world'pass: 'o0t878'encrypted: 'U2FsdGVkX1/YzdOqaSV3F1JhH/80gyk7qK5VtJdpj5Y='
Any help is appreciated.

--- End quote ---

The demo attached below should solve your issue, However do note that this is a very bad approach to generate a salt and IV.
There are specialized KDF's for that such as PBKDF2, Scrypt, Argon2. all these KDF's mentioned are well supported by CryptoLib.
Please do note you need the following packages, they can be gotten in OPM.

CryptoLib4Pascal
SimpleBaseLib4Pascal
HashLib4Pascal

Xor-el:

--- Quote from: lainz on May 14, 2021, 10:30:03 pm ---Hi, I think I must learn first the basics of cryptography, else this can be done wrong.

I change the goal of this thread, still at cryptography: How I can start to learn cryptography? Any online documentation you recommend?

--- End quote ---

Glad you agree that Cryptography is not something to be rushed.
that been said, I suggest you begin by understanding symmetric and asymmetric Cryptography for a start.
Then you proceed to proper practices in Crypto.

PierceNg:

--- Quote from: lainz on May 14, 2021, 10:30:03 pm ---Hi, I think I must learn first the basics of cryptography, else this can be done wrong.

I change the goal of this thread, still at cryptography: How I can start to learn cryptography? Any online documentation you recommend?

--- End quote ---

You can pick something from this list to start: https://github.com/sobolevn/awesome-cryptography

Study and practice, basically.

lainz:
@PierceNg and @Xor-el thanks for the help, this thread is solved. Start to study and practice for me.

Navigation

[0] Message Index

[*] Previous page

Go to full version