B4J Question .net code to B4J

aaronk

Well-Known Member
Licensed User
Hi,

I am trying to the AES encryption and deception working in my B4J app.

I thought I had this working in the past, but looks like I didn't get it fully working after all.

I have been told that the AES uses AES-128 in ECB mode.

I have been told the following .net code works:

B4X:
Public Class AES
 
    Dim cAES As RijndaelManaged
 
    Public Sub New(ByVal AESkey As Byte())
 
        Dim InitVector() As Byte = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 
        cAES = New RijndaelManaged
        cAES.BlockSize = 128
        cAES.KeySize = 128
        cAES.Mode = CipherMode.ECB
        cAES.IV = InitVector
        cAES.Padding = PaddingMode.Zeros
        cAES.Key = AESkey
 
    End Sub
 
    Public Sub Decrypt(ByRef cBytes As Byte(), ByVal NumBytes As Integer)
 
        Dim PlainBytes(IOBuffSize) As Byte
        Dim i As Integer
 
        Dim cDecryptor As ICryptoTransform = cAES.CreateDecryptor()
 
        ' Skip over the first 13 bytes - they are already in the plain.
        For i = 13 To NumBytes - 16 Step 16
            cDecryptor.TransformBlock(cBytes, i, 16, PlainBytes, i)
        Next
        Array.Copy(PlainBytes, 13, cBytes, 13, NumBytes - 13)
 
    End Sub
 
    Public Sub Encrypt(ByRef cBytes As Byte(), ByRef NumBytes As Integer)
 
        Dim EncryptedBytes(IOBuffSize) As Byte
        Dim i As Integer
 
        ' pad to a multiple of 16
        Dim numPadBytes As Integer = 16 - ((NumBytes - 13) Mod 16)
        ReDim Preserve cBytes(NumBytes + numPadBytes - 1)
        For i = NumBytes To NumBytes + numPadBytes - 1
            cBytes(i) = 0
        Next i
        NumBytes += numPadBytes
 
        Dim cEncryptor As ICryptoTransform = cAES.CreateEncryptor()
 
        ' Skip over the first 13 bytes - they are left in the plain.
        For i = 13 To NumBytes - 1 Step 16
            cEncryptor.TransformBlock(cBytes, i, 16, EncryptedBytes, i)
        Next
        Array.Copy(EncryptedBytes, 13, cBytes, 13, NumBytes - 13)
 
    End Sub
 
End Class

The data I need to decrypt (which is sent from the product in the field) is sent to my B4J app as a UDP message.

I tried using the following B4J code to decrypt the message:

B4X:
Private Sub RMSockUDP_PacketArrived (Packet As UDPPacket)
    Decrypt(Packet.Data)
End Sub

Sub Decrypt(value() As Byte) As String
    Try
        Dim raw() As Byte = value
        bb.Initialize
        bb.Append(raw)
        Dim binaryflag() As Byte = Array As Byte(0x33, 0x36, 0x37, 0x30, 0x42, 0x42, 0x39, 0x46, 0x2f,0x2f,0x31,0x2f,0x2f)
        If bb.IndexOf(binaryflag) > -1 Then
            Dim msgbytes() As Byte = bb.SubArray2(13,bb.IndexOf2(Array As Byte(0x0),13))
        End If

        kg.Initialize("AES")
        kg.KeyFromBytes("0123456789ABCDEF".GetBytes("UTF8")) ' the key to encrypt the message was 0123456789ABCDEF
        C.Initialize("AES/ECB/NoPadding")
        msgbytes = C.Decrypt(msgbytes, kg.Key, False)
        
        Return BConv.StringFromBytes(msgbytes, "UTF8").Trim
    Catch
        Log("Error: " & LastException.message)
    End Try
End Sub

Using my B4J code above it shows the following error:
Error: java.lang.IllegalArgumentException: Null input buffer

Based on the .Net code above, is the B4J code correct or have I done something wrong ?

I am guessing I have done something wrong since it's showing the above error, and I can't work it out.
 

Daestrum

Well-Known Member
Licensed User
Can you post the encrypted message as hex bytes - printing as a string seems to corrupt the chars (it probably recognises some Unicode chars and displays them).
 
Upvote 0

aaronk

Well-Known Member
Licensed User
I attached it as an txt file which is the hex of the encrypted message.

After decrypting it, it should become: 3670BB9F//0//0000754C//00409D27558D//05.03.10//02.00.45//Hello
 

Attachments

  • hex.txt
    15.6 KB · Views: 69
Upvote 0

Daestrum

Well-Known Member
Licensed User
Finally got it working ( it was the unencrypted header causing the block size to fail)
It returned this from your file data :
3670BB9F//1//0000754C//00409D27558D//05.03.10//02.00.45//Hello
and yes I forgot to change the //1// to //0// as its unencrypted.

This is the relevant code for decrypting.
I must say I found it very interesting to solve, thank you for posting your question.

B4X:
Sub Decrypt(value() As Byte) As String
 Dim msg_string As String
 Dim dataString As String = BConv.StringFromBytes(value,"utf8")
 Dim header As String = dataString.SubString2(0,dataString.LastIndexOf("//")+2)
 If header.Contains("//1//") Then
  Log("is encoded")
  Dim keyBytes() As Byte = "0123456789ABCDEF".GetBytes("utf8")
  Dim decryptedmsgbytes() As Byte  = asjo(Me).RunMethod("doit3",Array(value,keyBytes,header.Length))
 
  Dim value1 As String = BytesToString(decryptedmsgbytes, 0, decryptedmsgbytes.Length, "utf8")
 ' the bit I forgot :)
 header = header.Replace("//1//","//0//") 
  msg_string = header&value1.SubString2(0,value1.IndexOf(CRLF))
 Else
  msg_string = dataString.SubString2(0,dataString.IndexOf(CRLF))
 End If
 Return msg_string.trim
End Sub

Sub asjo(o As JavaObject) As JavaObject
 Return o
End Sub

#if java
import javax.crypto.*;
import java.io.IOException;
import java.security.Security;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public static byte[] doit3(byte[] cText, byte[] key,int headerLength) throws Exception {
  String cipherText = new String(cText);
  cipherText = cipherText.substring(headerLength);
  double d = cipherText.length() / 16.0D;
  int dd = (int)d;
  int copyLength = (dd * 16) - (16 - (headerLength%16));
  //
  // I honestly dont know why I need the previous line seems like the header screws it
  //
  byte[] data = Arrays.copyOfRange(cText, headerLength, copyLength);
  Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
  cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"));
  return cipher.doFinal(data);
}
#End If
** I changed the original 13 in the code to headerLength so it can handle different header lengths.
 
Last edited:
Upvote 0
Top