Android Question [SOLVED] AES encryption problem

Lello1964

Well-Known Member
Licensed User
Longtime User
I have a problem with encryption lib,
i have this code :
B4X:
    Dim Kg As KeyGenerator
    Dim c As Cipher
    Dim data(),key() As Byte
    Dim bc As  ByteConverter
   
    Dim Text As String    = "090000000033140000004555525812FFFABCDE87FFCBD245"
    Dim chiave As String  = "6745230167452301FF66613800000000"
    key = bc.HexToBytes(chiave)
   
    c.Initialize("AES/ECB/NoPadding") 
   
    Kg.Initialize("AES")
    Kg.KeyFromBytes(key)
   
    data =bc.HexToBytes(Text)
   
    data = c.Encrypt(data, Kg.key, False)
    Msgbox(data,"Cripteed")

and this error :

Error occurred on line: 46 (Main)
javax.crypto.IllegalBlockSizeException: error:1e00006a:Cipher functions:OPENSSL_internal:DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH
at com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(Native Method)
at com.android.org.conscrypt.OpenSSLCipher$EVP_CIPHER.doFinalInternal(OpenSSLCipher.java:568)
at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:350)
at javax.crypto.Cipher.doFinal(Cipher.java:2056)
at anywheresoftware.b4a.agraham.encryption.CipherWrapper.doFinal(CipherWrapper.java:140)
at anywheresoftware.b4a.agraham.encryption.CipherWrapper.Encrypt(CipherWrapper.java:160)
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 b4a.example.main.afterFirstLayout(main.java:104)
at b4a.example.main.access$000(main.java:17)
at b4a.example.main$WaitForLayout.run(main.java:82)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6121)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
 

Lello1964

Well-Known Member
Licensed User
Longtime User
I use an encrypted string to communicate via USB with a device, it use no padding mode.

this is java source code library of device

B4X:
public byte[] AESnew(long pFixedKey, long pVariableKey, String pComando, boolean flg_encrypt, int lunghezza) {
//BA.Log(" result comando  " +pComando);
//BA.Log(" lunghezza comando  " +lunghezza);

int[] tmpData = new int[255];

tmpData = hexStringToByteArray(pComando);

for ( int i = 0; i<lunghezza;i++){
  //BA.Log(" result primo  " + String.valueOf(tmpData));
}

    SSP_COMMAND sspCommand = new SSP_COMMAND();
    SSP_FULL_KEY sspFullKey = new SSP_FULL_KEY();
    sspFullKey.FixedKey =  pFixedKey;
    sspFullKey.VariableKey =  pVariableKey;
    sspCommand.Key = sspFullKey;
    sspCommand.EncryptionStatus = flg_encrypt;
    sspCommand.encPktCount = 0;
    sspCommand.CommandDataLength =  lunghezza ;
    
    //BA.Log(" aaaaaa "  );
    aes_encrypt(sspFullKey, tmpData,(byte) lunghezza, 0);
    
     byte[] result = new byte[lunghezza];
    
    for(int i = 0; i < tmpData.length; i++){
        result = (byte) tmpData;
        //BA.Log(" result " +  tmpData);
        }
          
    return result;
}

public static int[] hexStringToByteArray(String s) {
    int[] b = new int[s.length() / 2];
    for (int i = 0; i < b.length; i++) {
      int index = i * 2;
      int v = Integer.parseInt(s.substring(index, index + 2), 16);
      b = v;
    }
    return b;
  }
  
void EncryptSSPPacket(SSP_COMMAND cmd) {
        final byte FIXED_PACKET_LENGTH = 7;
        final byte C_MAX_KEY_LENGTH = 16;
        byte pkLength, i, packLength = 0;
        int crc;
        int[] tmpData = new int[255];

         pkLength = (byte) (cmd.CommandDataLength);
      //  pkLength = (byte) (cmd.CommandDataLength + FIXED_PACKET_LENGTH);
        for (i = 0; i < cmd.CommandDataLength; i++) {
            tmpData[i + 5] = cmd.CommandData;
        }

    //    aes_encrypt(cmd.Key, tmpData, pkLength, 0);
/*
        if (pkLength % C_MAX_KEY_LENGTH != 0) {
            packLength = (byte) (C_MAX_KEY_LENGTH - (pkLength % C_MAX_KEY_LENGTH));
        }
        pkLength += packLength;

        tmpData[0] = cmd.CommandDataLength;  

        for (i = 0; i < 4; i++) {
            tmpData[1 + i] = (byte) ((cmd.encPktCount >> (8 * i) & 0xFF));
        }

        for (i = 0; i < cmd.CommandDataLength; i++) {
            tmpData[i + 5] = cmd.CommandData;
        }


        for (i = 0; i < packLength; i++) {
            tmpData[5 + cmd.CommandDataLength + i] = (byte)rand.GenerateRandomNumber();


        crc = cal_crc_loop_CCITT_A((pkLength - 2), 0, tmpData, CRC_SSP_SEED, CRC_SSP_POLY);

        tmpData[pkLength - 2] = (crc & 0xFF);
        tmpData[pkLength - 1] = ((crc >> 8) & 0xFF);

    // aes_encrypt(cmd.Key, tmpData, pkLength, 0);

        pkLength++;  

        cmd.CommandDataLength = pkLength;
        cmd.CommandData[0] = SSP_STEX;
        for (i = 0; i < pkLength - 1; i++) {
            cmd.CommandData[1 + i] = tmpData;
        }

        cmd.encPktCount++;  
*/
    }
 
Last edited:
Upvote 0

rosippc64a

Active Member
Licensed User
Longtime User
If you use nopadding, the you must pad manually. it works (DATA_MULTIPLE_OF_BLOCK_LENGTH) :
B4X:
    Dim Text As String    = "090000000033140000004555525812FFFABCDE87FFCBD2450000000000000000"
    Dim chiave As String  = "6745230167452301FF66613800000000"
 
Upvote 0

Peter Simpson

Expert
Licensed User
Longtime User
@Lello1964 have you tried using my library???


Also you have been a member since 2011, please use the code take when posting code, it makes for easier reading.
Code_Tags.jpg
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
//BA.Log(" aaaaaa " );
aes_encrypt(sspFullKey, tmpData,(byte) lunghezza, 0);
I’m pretty sure this call does AES encryption with padding. Seeing the source to that function would prove/disprove that.
for (i = 0; i < pkLength - 1; i++) {
cmd.CommandData[1 + i] = tmpData;
}
This strips out the padding (after encryption)
 
Upvote 0

Lello1964

Well-Known Member
Licensed User
Longtime User
Sorry, for no posting code but i had to leave quickly
@Lello1964 have you tried using my library???


Also you have been a member since 2011, please use the code take when posting code, it makes for easier readin
@Lello1964 have you tried using my library???


Also you have been a member since 2011, please use the code take when posting code, it makes for easier reading.
View attachment 88670
Sorry for no posting but i had to leave quickly
 
Upvote 0

Lello1964

Well-Known Member
Licensed User
Longtime User
I’m pretty sure this call does AES encryption with padding. Seeing the source to that function would prove/disprove that.

This strips out the padding (after encryption)
B4X:
            Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));

this is original java : "AES/ECB/NoPadding
 
Upvote 0

Lello1964

Well-Known Member
Licensed User
Longtime User
@Lello1964 have you tried using my library???


Also you have been a member since 2011, please use the code take when posting code, it makes for easier reading.
View attachment 88670
I have saw you library, but how set "AES/ECB/NoPadding" ?
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Show all of the code of the aes_encrypt. There is no way (I could be wrong, maybe) that the function uses NoPadding but does not pad the to be encrypted packet. With NoPadding, the packet HAS to be the proper length. Also, what is up with EncryptSSPPacket(SSP_COMMAND cmd)? I see no encryption done in that routine. How does it relate to what the issue is here?

The more I look at what you have provided, the less sense it makes to me
B4X:
     byte[] result = new byte[lunghezza];
    
    for(int i = 0; i < tmpData.length; i++){
        result = (byte) tmpData;
        //BA.Log(" result " +  tmpData);
        }
What is done here? An result byte array is generated with the length of lunghezza. Yet you iterate through the whole length of tmpData (which is)
B4X:
int[] tmpData = new int[255];
256 bytes long. Yet not even the values of each tmpData element is transferred to result, just an abbreviated address of tmpData. Neither result's nor tmpData's values are being stepped through. Is this some translation from C pointer code to Java? If so, Java's pointers <> C pointers.
 
Upvote 0

Lello1964

Well-Known Member
Licensed User
Longtime User
i have tryed to use Java code :
B4X:
ComandoCriptatoByte2 =Main.NativeMe.RunMethod("AESnew",Array As Object (Main.lFixedKey,Main.lVariableKey  , tmpComando,True, lung) )

where
Main.lFixedKey= 81985526925837671
Main.lVariableKey = 1334568616
tmpComando= "090000000033140000004555525812FFFABCDE87FFCBD245"
lung= 24

but have this error :

java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:131)
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 anywheresoftware.b4a.debug.Debug.delegate(Debug.java:265)
at b4a.example1.funzioni._creacomandocriptato(funzioni.java:461)
at b4a.example1.usbserialopper._inviacomandoopper(usbserialopper.java:547)
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:351)
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:370)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6121)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
Caused by: java.lang.ArrayIndexOutOfBoundsException: length=16; index=16
at b4a.example1.main.aes_encrypt(main.java:3285)
at b4a.example1.main.AESnew(main.java:3178)
... 23 more
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Where is your Java code? In Main? Then the method must be declared static. In a class? Then why are you using Main's NativeMe object? Also, you are not testing if Main is active (since it is an activity) before calling the code.
 
Upvote 0

Lello1964

Well-Known Member
Licensed User
Longtime User
this is java code :

B4X:
import java.io.*;
import java.util.*;
import javax.crypto.*;
import javax.crypto.spec.*;

public final int ssp_CMD_SYNC = 0x11;
public final int SSP_STX = 0x7F;
public final int SSP_STEX = 0x7E;
    public final int CRC_SSP_SEED = 0xFFFF;
    public final int CRC_SSP_POLY = 0x8005;
public final long MAX_RANDOM_INTEGER = 2147483647L;
    
public class SSP_COMMAND {
    public SSP_FULL_KEY Key = new SSP_FULL_KEY();
    public int BaudRate = 9600;
    public long Timeout = 500;
    public String ComPort;
    public int SSPAddress = 0;
    public int RetryLevel = 3;
    public boolean EncryptionStatus = false;
    public int CommandDataLength;
    public int[] CommandData = new int[255];
    public PORT_STATUS ResponseStatus;
    public int ResponseDataLength;
    public int[] ResponseData = new int[255];
    public int encPktCount;
    public int sspSeq;
}

public class SSP_COMMAND_INFO {
    public boolean Encrypted;
    public SSP_PACKET Transmit = new SSP_PACKET();
    public SSP_PACKET Receive = new SSP_PACKET();
    public SSP_PACKET PreEncryptedTransmit = new SSP_PACKET();
    public SSP_PACKET PreEncryptedRecieve = new SSP_PACKET();
}

public static class SSP_FULL_KEY {
    public long FixedKey;
    public long VariableKey;
}

public class SSP_KEYS {
    public long Generator;
    public long Modulus;
    public long HostInter;
    public long HostRandom;
    public long SlaveInterKey;
    public long SlaveRandom;
    public long KeyHost;
    public long KeySlave;
}

public class SSP_PACKET {
    public int packetTime;
    public int PacketLength;
    public int[] PacketData = new int[255];
}

public byte[] AESnew(long pFixedKey, long pVariableKey, String pComando, boolean flg_encrypt, int lunghezza) {
//BA.Log(" result comando  " +pComando);
//BA.Log(" lunghezza comando  " +lunghezza);

int[] tmpData = new int[255];

tmpData = hexStringToByteArray(pComando);

for ( int i = 0; i<lunghezza;i++){
  //BA.Log(" result primo  " + String.valueOf(tmpData[i]));
}

    SSP_COMMAND sspCommand = new SSP_COMMAND();
    SSP_FULL_KEY sspFullKey = new SSP_FULL_KEY();
    sspFullKey.FixedKey =  pFixedKey;
    sspFullKey.VariableKey =  pVariableKey;
    sspCommand.Key = sspFullKey;
    sspCommand.EncryptionStatus = flg_encrypt;
    sspCommand.encPktCount = 0;
    sspCommand.CommandDataLength =  lunghezza ;
   
    //BA.Log(" aaaaaa "  );
    aes_encrypt(sspFullKey, tmpData,(byte) lunghezza, 0);
   
     byte[] result = new byte[lunghezza];
   
    for(int i = 0; i < tmpData.length; i++){
        result[i] = (byte) tmpData[i];
        //BA.Log(" result " +  tmpData[i]);
        }
         
    return result;
}

    void  aes_encrypt(SSP_FULL_KEY sspKey, int[] data, byte length, int offset) {
        int i;
        byte[] data_byte = new byte[length];
        byte[] key = new byte[16];
        byte[] enc_data_byte;

        for (i = 0; i < length; i++) {
            data_byte[i] = (byte) data[i];
        }

        for (i = 0; i < 8; i++) {
            key[i] = (byte) (sspKey.FixedKey >> (8 * i));
            key[i + 8] = (byte) (sspKey.VariableKey >> (8 * i));
        }

        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));
            ByteArrayInputStream bIn = new ByteArrayInputStream(data_byte);
            CipherInputStream cIn = new CipherInputStream(bIn, cipher);
            ByteArrayOutputStream bOut = new ByteArrayOutputStream();
            int ch;
            while ((ch = cIn.read()) >= 0) {
                bOut.write(ch);
            }
            enc_data_byte = bOut.toByteArray();
        } catch (Exception e) {
            return;
        }

        for (i = 0; i < length; i++) {
            data[i] = enc_data_byte[i];
            data[i] &= 0xFF;
        }
        return ;
    }
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Where did you put this code? In Main? Then the declaration needs to be
B4X:
public static byte[] AESnew(long pFixedKey, long pVariableKey, String pComando, boolean flg_encrypt, int lunghezza) {
It needs to be declared static. Either that, or move the java code to a class module.
 
Upvote 0

Lello1964

Well-Known Member
Licensed User
Longtime User
the problem isn't java code, it's ok:
if i try to encrypt this string : "0200000000490112FFFABCDE87FF2456" , no errors if lenght = 32
The problem is using a string like "090000000033140000004555525812FFFABCDE87FFCBD245" lenght = 48.
I have tryed to fill to 64 : "090000000033140000004555525812FFFABCDE87FFCBD2450000000000000000" then no errors, but device doesn't decrypt correctly the string.
Also using "AES/ECB/PKCS5Padding " device doesn't decrypt correctly the string.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Ok, so both aes_encrypt AND the B4A code you initially posted fail with data that is not a multiple of 16 (strangely, length of 48 should have worked). That's a given with no padding. There is just no way around it. If you use NoPadding, you have to ensure yourself that the data is the proper length before encrypting or decrypting the data. So where are the specifications of what your are trying to accomplish and/or communicate with? BTW, the error in post#11 is actually an index out of bounds error. Your accessing index 16, even though the max index should be 15 (length = 16).
 
Upvote 0

Lello1964

Well-Known Member
Licensed User
Longtime User
I have SOLVED, "090000000033140000004555525812FFFABCDE87FFCBD2450000000000000000" are bytes !! lenght=24 Bytes, isn't multiple of 16 !!!!!!

SOLVED padding to 64 Byte.

Thanks all for help.
 
Upvote 0

rosippc64a

Active Member
Licensed User
Longtime User
If you use nopadding, the you must pad manually. it works (DATA_MULTIPLE_OF_BLOCK_LENGTH) :
B4X:
    Dim Text As String    = "090000000033140000004555525812FFFABCDE87FFCBD2450000000000000000"
    Dim chiave As String  = "6745230167452301FF66613800000000"


As I wrote in #4 message! :)
 
Upvote 0
Top