Encrypting over Network

Zenerdiode

Active Member
Licensed User
I'm interested in encrypting the data packets over a TCP connection; but I'm getting an error as shown below. Am I trying to use BinaryFile in ways it was not intended? A very crude example Server/Client is included which demonstrates the error.

If I may get this working, I would like to ultimately use agraham's CryptoEx with asymetric encryption.
 

Attachments

  • B4PPC error.JPG
    B4PPC error.JPG
    12.8 KB · Views: 191
  • Server.sbp
    2.2 KB · Views: 181
  • Client.sbp
    2 KB · Views: 194

agraham

Expert
Licensed User
Longtime User
Your array lengths are wrong :(.

B4X:
Sub Globals
   'Declare the global variables here.
   Dim IP(0) As String
   Dim Secret(0) As Byte
   Dim TempArray([COLOR="Red"]1024[/COLOR]) As Byte
   DateFormat("DD/MM/YYYY")
End Sub

...

Sub TimerWFD_Tick 'Wait for Data
   If Client.DataAvailable=True Then
[COLOR="red"]      count = Stream.ReadBytes(TempArray(),1024)
      Dim Secret(count) As Byte
      ArrayCopy(TempArray(), 0, count, Secret(), 0)[/COLOR]
      TempArray()=Crypto.Decrypt("Christopher",Secret())
      TextBox1.Text=TextBox1.Text&BitWise.BytesToString(TempArray(), 0, ArrayLen(TempArray())) & CRLF
   End If
End Sub
Two things to note. TCP/IP is a stream not a packet protocol so there is no guarantee that data written in a single write will arrive in a single read. Across an internal network it probably will for amounts of data less than about 1500 bytes. Across the Internet it may not.

Asymmetric encryption is very expensive in processing time. It is usually used to transfer a once-off session key that is used for symmetric encryption during the session and discarded afterwards.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Another solution (written during agraham's post):
First I send an Int32 with the data size.
Client reading code:
B4X:
Sub TimerWFD_Tick 'Wait for Data
    If Client.DataAvailable=True Then
        len = Stream.ReadInt32
        Dim Secret(len) As byte
        Stream.ReadBytes(Secret(),len)
        TempArray()=Crypto.Decrypt("Christopher",Secret())
        TextBox1.Text=TextBox1.Text&BitWise.BytesToString(TempArray(),0,ArrayLen(TempArray()))&CRLF
    End If
End Sub
Server sending code:
B4X:
Sub TextBox2_KeyPress (key)
    If Asc(key)=13 Then
        TextBox2.IgnoreKey
        If LabClient.Text="Connected" Then
            TempArray()=BitWise.StringToBytes(TextBox2.Text,0,StrLength(TextBox2.Text))
            secret()=Crypto.Encrypt(PassPhrase,TempArray())
            Stream.WriteInt32(ArrayLen(secret())) 'write the data size
            Stream.WriteBytes(secret())
        End If
        TextBox2.Text=""
    End If
End Sub
 

Zenerdiode

Active Member
Licensed User
Andrew and Erel, thank you both for your replies. I'm sorry I haven't been able to respond until now due to work commitments. Both solutions work well, however, Andrew I had to add the following to your solution to make it work:

B4X:
Sub TimerWFD_Tick 'Wait for Data
   If Client.DataAvailable=True Then
      [COLOR="Red"]Dim TempArray(1024) As Byte[/COLOR]
      count = Stream.ReadBytes(TempArray(),1024)
      Dim Secret(count) As Byte
      ArrayCopy(TempArray(), 0, count, Secret(), 0)
      TempArray()=Crypto.Decrypt("Christopher",Secret())
      TextBox1.Text=TextBox1.Text&BitWise.BytesToString(TempArray(), 0, ArrayLen(TempArray())) & CRLF
   End If
End Sub

I don't know why, (it was trial and error) I presume it clears the Array each time. :confused:

Your array lengths are wrong :(.

Too right. I've learned that if an array is returned by a function or library, you may initialise it with a Dim Array(0) and when used with Array()= ... it will be automatically set to the correct size; but when using as above it will not, hence the initial and subsequent Dim statements setting an absolute size.

Thanks again,

Christopher
 

agraham

Expert
Licensed User
Longtime User
I don't know why, (it was trial and error)
I tested that code (as I usually try to do ) before I posted it and the post was a cut and paste from the working app but what I missed was that I only ran the code once and it works for the first pass. However assigning the return of Crypto.Decrypt to TempArray then makes that array in TempArray too small to hold the number of bytes read from the stream. I should have used a different array to hold the decrypted data!
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
I've learned that if an array is returned by a function or library, you may initialise it with a Dim Array(0) and when used with Array()= ... it will be automatically set to the correct size; but when using as above it will not, hence the initial and subsequent Dim statements setting an absolute size.
When a function returns an array, the array is not copied. You actually get a reference to the same array which was initialized somewhere in the library code.
The previous declared array gets freed.
So in that cases declaring an array of size 0 is enough.

BinaryFile methods which expect an array do not initialize the array. It is up to the developer to pass an initialized array. This allows a more efficient resource handling as you can reuse the array multiple times.
 
Top