Android Question Problem on replace string letter by letter

Waldemar Lima

Active Member
Licensed User
hi everyone !


i am trying obfuscate base64 replacing letter by letter using this algorithm below :

note : completes the obfuscation in about 5 seconds, being too slow for software that needs to communicate with the socket server ...

What can i do to improve the performance of this algoritm ?

B4X:
Sub Base64_Obfuscate(stringcyph As String) As String
    
    Dim TempByte() As Byte = stringcyph.GetBytes("UTF8")
    Dim TempCyphered As String = cypher.EncodeBase64(TempByte)
    Dim TempResult As String
    For i = 0 To TempCyphered.Length-1
        'Minusculo
        
        If (TempCyphered.SubString2(i,i+1) = "a") Then
            TempResult = TempResult & "h"
        else if (TempCyphered.SubString2(i,i+1) = "b") Then
            TempResult = TempResult & "l"
        else if (TempCyphered.SubString2(i,i+1) = "c") Then
            TempResult = TempResult & "V"
        else if (TempCyphered.SubString2(i,i+1) = "d") Then
            TempResult = TempResult & "b"
        else if (TempCyphered.SubString2(i,i+1) = "e") Then
            TempResult = TempResult & "H"
        else if (TempCyphered.SubString2(i,i+1) = "f") Then
            TempResult = TempResult & "J"
        else if (TempCyphered.SubString2(i,i+1) = "g") Then
            TempResult = TempResult & "P"
        else if (TempCyphered.SubString2(i,i+1) = "h") Then
            TempResult = TempResult & "s"
        else if (TempCyphered.SubString2(i,i+1) = "i") Then
            TempResult = TempResult & "N"
        else if (TempCyphered.SubString2(i,i+1) = "j") Then
            TempResult = TempResult & "e"
        else if (TempCyphered.SubString2(i,i+1) = "k") Then
            TempResult = TempResult & "T"
        else if (TempCyphered.SubString2(i,i+1) = "l") Then
            TempResult = TempResult & "g"
        else if (TempCyphered.SubString2(i,i+1) = "m") Then
            TempResult = TempResult & "X"
        else if (TempCyphered.SubString2(i,i+1) = "n") Then
            TempResult = TempResult & "n"
        else if (TempCyphered.SubString2(i,i+1) = "o") Then
            TempResult = TempResult & "c"
        else if (TempCyphered.SubString2(i,i+1) = "p") Then
            TempResult = TempResult & "W"
        else if (TempCyphered.SubString2(i,i+1) = "q") Then
            TempResult = TempResult & "K"
        else if (TempCyphered.SubString2(i,i+1) = "r") Then
            TempResult = TempResult & "d"
        else if (TempCyphered.SubString2(i,i+1) = "s") Then
            TempResult = TempResult & "q"
        else if (TempCyphered.SubString2(i,i+1) = "t") Then
            TempResult = TempResult & "a"
        else if (TempCyphered.SubString2(i,i+1) = "u") Then
            TempResult = TempResult & "G"
        else if (TempCyphered.SubString2(i,i+1) = "v") Then
            TempResult = TempResult & "O"
        else if (TempCyphered.SubString2(i,i+1) = "w") Then
            TempResult = TempResult & "t"
        else if (TempCyphered.SubString2(i,i+1) = "x") Then
            TempResult = TempResult & "L"
        else if (TempCyphered.SubString2(i,i+1) = "y") Then
            TempResult = TempResult & "i"
        else if (TempCyphered.SubString2(i,i+1) = "z") Then
            TempResult = TempResult & "m"
            'Maiusculo
        else if (TempCyphered.SubString2(i,i+1) = "A") Then
            TempResult = TempResult & "j"
        else if (TempCyphered.SubString2(i,i+1) = "B") Then
            TempResult = TempResult & "f"
        else if (TempCyphered.SubString2(i,i+1) = "C") Then
            TempResult = TempResult & "p"
        else if (TempCyphered.SubString2(i,i+1) = "D") Then
            TempResult = TempResult & "o"
        else if (TempCyphered.SubString2(i,i+1) = "E") Then
            TempResult = TempResult & "z"
        else if (TempCyphered.SubString2(i,i+1) = "F") Then
            TempResult = TempResult & "u"
        else if (TempCyphered.SubString2(i,i+1) = "G") Then
            TempResult = TempResult & "v"
        else if (TempCyphered.SubString2(i,i+1) = "H") Then
            TempResult = TempResult & "r"
        else if (TempCyphered.SubString2(i,i+1) = "I") Then
            TempResult = TempResult & "k"
        else if (TempCyphered.SubString2(i,i+1) = "J") Then
            TempResult = TempResult & "x"
        else if (TempCyphered.SubString2(i,i+1) = "K") Then
            TempResult = TempResult & "R"
        else if (TempCyphered.SubString2(i,i+1) = "L") Then
            TempResult = TempResult & "U"
        else if (TempCyphered.SubString2(i,i+1) = "M") Then
            TempResult = TempResult & "y"
        else if (TempCyphered.SubString2(i,i+1) = "N") Then
            TempResult = TempResult & "S"
        else if (TempCyphered.SubString2(i,i+1) = "O") Then
            TempResult = TempResult & "D"
        else if (TempCyphered.SubString2(i,i+1) = "P") Then
            TempResult = TempResult & "I"
        else if (TempCyphered.SubString2(i,i+1) = "Q") Then
            TempResult = TempResult & "C"
        else if (TempCyphered.SubString2(i,i+1) = "R") Then
            TempResult = TempResult & "A"
        else if (TempCyphered.SubString2(i,i+1) = "S") Then
            TempResult = TempResult & "E"
        else if (TempCyphered.SubString2(i,i+1) = "T") Then
            TempResult = TempResult & "F"
        else if (TempCyphered.SubString2(i,i+1) = "U") Then
            TempResult = TempResult & "Z"
        else if (TempCyphered.SubString2(i,i+1) = "V") Then
            TempResult = TempResult & "Q"
        else if (TempCyphered.SubString2(i,i+1) = "W") Then
            TempResult = TempResult & "B"
        else if (TempCyphered.SubString2(i,i+1) = "X") Then
            TempResult = TempResult & "M"
        else if (TempCyphered.SubString2(i,i+1) = "Y") Then
            TempResult = TempResult & "y"
        else if (TempCyphered.SubString2(i,i+1) = "Z") Then
            TempResult = TempResult & "w"
        Else
            TempResult = TempResult & TempCyphered.SubString2(i,i+1)
        End If
      
    Next

    Return TempResult
    
End Sub
 

Lee Gillie CCP

Active Member
Licensed User
I think for sure I would work on an input and output byte array rather than strings at a very minimum. Further use the input byte value as an index to a byte array of translated values. You may need to initialize both a forward and backward translation array, depending on your need. You should not need any IF statements or CASE. Once it is all done loading the output byte array, THEN convert that to a UTF8 string. Just some thoughts.
 

stevel05

Expert
Licensed User
Try using CharAt instead of substring and StringBuilder to build the output string.

How long is the string you are using? Make sure you are testing in release mode.
 
Last edited:

Ormente

Member
Licensed User
You can improve further by placing the result of TempCyphered.SubString2(i,i+1) (or charAt, now) in a variable you reuse for each test, to avoid re-calling (ie. re-calculating) the same operation over and over.

You can also do the same thing differently :
- First alternative : use a map you build in advance, mapping each character to its replacement, so each replacement can be done with a simple GetValueAt().
- Second one : substitute the value of "a" from your current character, then use the result as an indice (position) to get the replacement from the string "hlVbHJps..."
 

stevel05

Expert
Licensed User
Try this version:
B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Private Cypher As StringUtils
    Private CypherMap As Map
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
    
    PopulateMap
    Dim S As String = "01234567891012345678910123456789101234567891012345678910123456789101234567891012345678910123456789101234567891012345678910123456789101234567891012345678910123456789101234567891"
    
    Log(Base64_Obfuscate(S))
    
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Base64_Obfuscate(stringcyph As String) As String
    
    Dim StartTime As String = DateTime.Now
    
    Dim TempByte() As Byte = stringcyph.GetBytes("UTF8")
    Dim TempCyphered As String = Cypher.EncodeBase64(TempByte)
    Dim TempResult As StringBuilder
    TempResult.Initialize
    For i = 0 To TempCyphered.Length-1
        TempResult.Append(CypherMap.GetDefault(TempCyphered.CharAt(i),TempCyphered.CharAt(i)))
    Next

    Log("2 Took " & (DateTime.Now - StartTime))

    Return TempResult.ToString
    
End Sub

Public Sub PopulateMap
    
    CypherMap = CreateMap("a":"h", _
    "b":"l", _
     "c":"V", _
     "d":"b", _
     "e":"H", _
     "f":"J", _
     "g":"P", _
     "h":"s", _
     "i":"N", _
     "j":"e", _
     "k":"T", _
     "l":"g", _
     "m":"X", _
     "n":"n", _
     "o":"c", _
     "p":"W", _
     "q":"K", _
     "r":"d", _
     "s":"q", _
     "t":"a", _
     "u":"G", _
     "v":"O", _
     "w":"t", _
     "x":"L", _
     "y":"i", _
     "z":"m", _
     "A":"j", _
     "B":"f", _
     "C":"p", _
     "D":"o", _
     "E":"z", _
     "F":"u", _
     "G":"v", _
     "H":"r", _
     "I":"k", _
     "J":"x", _
     "K":"R", _
     "L":"U", _
     "M":"y", _
     "N":"S", _
     "O":"D", _
     "P":"I", _
     "Q":"C", _
     "R":"A", _
     "S":"E", _
     "T":"F", _
     "U":"Z", _
     "V":"Q", _
     "W":"B", _
     "X":"M", _
     "Y":"y", _
     "Z":"w")
            
End Sub
 

Jeffrey Cameron

Well-Known Member
Licensed User
Why not just use the existing cryptography to encrypt your data, the encrypted result can be base-64 encoded (saving you one extra step)?
For example:
B4X:
' Note:  Requires Encryption, ByteConverter and StringUtils libraries

Private Const USER_IV8 As String = "Mz1Yz5lf"                'must be eight bytes
Private Const USER_KEY As String = "4rnk3ly2thSetest"        'must be 16 bytes


Public Sub TripleDESEncrypt(dataToEncrypt As String) As String
    Dim kg As KeyGenerator
    Dim poC As Cipher
    Dim Bconv As ByteConverter
    Dim poSU As StringUtils

    Dim data(0) As Byte
    Dim iv(0) As Byte
    iv = Bconv.StringToBytes(USER_IV8, "ASCII")
    
    'DO NOT INITIALIZE THE Ciper VARIABLE WITH ITS OWN INITIALIZE METHOD
    ' if you will be using .NET to decrypt the data.
    '  USE THE ROUTINE --  Android changed from bouncy castle on Marshmallow to another default
    InitializeCipher(poC, "DESede/CBC/PKCS7Padding")
  
    poC.InitialisationVector = iv
    kg.Initialize("DESEDE")

    kg.KeyFromBytes(Bconv.StringToBytes(USER_KEY, "ASCII"))
    data = Bconv.StringToBytes(dataToEncrypt, "ASCII")
    data = poC.Encrypt(data, kg.Key, True)
  
    '    Dim piIndex As Int
    '    Log("Plaintext: [" & dataToEncrypt & "]")
    '    Log("Encrypted Bytes (" & data.Length & "): ")
    '    For piIndex = 0 To data.Length - 1
    '        Log("     Byte [" & NumberFormat(piIndex, 2, 0) & "] value [" & NumberFormat(data(piIndex), 3, 0)  & "]")
    '    Next
    'Dim psBase As String = poSU.EncodeBase64(data)
    'Log("     Base-64 encoded [  " & psBase  & "  ]")

    Return poSU.EncodeBase64(data)
End Sub

Public Sub TripleDESDecrypt(Base64EncryptedData As String ) As String
    Dim kg As KeyGenerator
    Dim poC As Cipher
    Dim Bconv As ByteConverter
    Dim poSU As StringUtils
    Dim data(0) As Byte
    Dim iv(0) As Byte

    Try
        iv = Bconv.StringToBytes(USER_IV8, "ASCII")
        
        ' DO NOT INITIALIZE THE Ciper VARIABLE WITH ITS OWN INITIALIZE METHOD
        ' USE THE ROUTINE --  Android changed from bouncy castle on Marshmallow to another default
        InitializeCipher(poC, "DESede/CBC/PKCS7Padding")

        poC.InitialisationVector = iv
        kg.Initialize("DESEDE")
        kg.KeyFromBytes(Bconv.StringToBytes(USER_KEY, "ASCII"))
        
        data = poSU.DecodeBase64(Base64EncryptedData)
        data = poC.Decrypt(data, kg.Key, True)

        Return Bconv.StringFromBytes(data, "ASCII")
    Catch
        Log("Data decrypt error: " & LastException.Message)
        Return ""
    End Try
End Sub

'  This routine will initialize the Cyper data type using the pre-Marshmallow OS standard of "BC" instead of the AndroidSSL standard.
Private Sub InitializeCipher(c As Cipher, transformation As String)
    Dim r As Reflector
    Dim o As Object = r.RunStaticMethod("javax.crypto.Cipher", "getInstance", Array(transformation, "BC"), _
     Array As String("java.lang.String", "java.lang.String"))
    r.Target = c
    r.SetField2("cipher", o)
End Sub
 
Last edited:
Top