Avatar

Blog (pg. 20)

  • Published on
    I recently wrote a wrapper class implementing the .NET System.Security.Cryptography.TripleDESCryptoServiceProvider to quickly allow you to encrypt a plaintext string and return the Base64 encoded string of the encrypted bytes created by the TripleDES cipher (and decrypt that string back to plaintext!). This provides a very simple way to encrypt and decrypt your data without the need to store it as a binary image. The VB.NET code is shown below:
    Public Class TripleDES
            Private _k, _iv As Byte()
    
            Public Sub New(ByVal key As Byte(), ByVal iv As Byte())
                _k = key
                _iv = iv
            End Sub
    
            Public Property Key() As Byte()
                Get
                    Return _k
                End Get
                Set(ByVal value As Byte())
                    _k = value
                End Set
            End Property
    
            Public Property IV() As Byte()
                Get
                    Return _iv
                End Get
                Set(ByVal value As Byte())
                    _iv = value
                End Set
            End Property
    
            Public Function Encrypt(ByVal plaintext As String) As String
                Dim cipher As New System.Security.Cryptography.TripleDESCryptoServiceProvider()
                cipher.BlockSize = 64
    
                Dim cipherText As String
                Using cipherTextStream As New IO.MemoryStream()
                    Using cryptoStream As New System.Security.Cryptography.CryptoStream(cipherTextStream, cipher.CreateEncryptor(_k, _iv), System.Security.Cryptography.CryptoStreamMode.Write)
                        Dim bytes As Byte() = Text.Encoding.UTF8.GetBytes(plaintext)
                        cryptoStream.Write(bytes, 0, bytes.Length)
                        cryptoStream.FlushFinalBlock()
    
                        cipherText = Convert.ToBase64String(cipherTextStream.ToArray())
                    End Using
                End Using
    
                Return cipherText
    
            End Function
    
            Public Function Decrypt(ByVal ciphertext As String) As String
                Dim cipher As New System.Security.Cryptography.TripleDESCryptoServiceProvider()
                cipher.BlockSize = 64
    
                Dim plaintext As String
                Using plaintextStream As New IO.MemoryStream()
                    Using cryptoStream As New System.Security.Cryptography.CryptoStream(plaintextStream, cipher.CreateDecryptor(_k, _iv), System.Security.Cryptography.CryptoStreamMode.Write)
                        Dim bytes As Byte() = Convert.FromBase64String(ciphertext)
                        cryptoStream.Write(bytes, 0, bytes.Length)
                        cryptoStream.FlushFinalBlock()
    
                        plaintext = Text.Encoding.UTF8.GetString(plaintextStream.ToArray())
                    End Using
                End Using
    
                Return plaintext
    
            End Function
        End Class
    To use it, simply instanciate it with your Key and Initialization Vector. Make sure your K and IV are the same when decrypting data you encrypted with them!
  • Published on
    To generate random passwords I have written a simple class in VB.NET, which accepts a string containing valid password characters and then generates passwords of n length using the specified characters.
    Public Class PasswordGenerator
            Private _pwChars As String
    
            Public Sub New()
                MyClass.New("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
            End Sub
    
            Public Sub New(ByVal validChars As String)
                _pwChars = validChars
            End Sub
    
            Public Function GeneratePassword(ByVal length As Integer) As String
                Dim password As String = ""
                Dim rndNum As New Random()
    
                For i As Integer = 1 To length
                    password &= _pwChars.Substring(rndNum.Next(0, _pwChars.Length - 1), 1)
                Next
    
                Return password
            End Function
    
        End Class
  • Published on
    If you are trying to Make Thread-Safe Calls to Windows Forms Controls then you can run into deadlock problems when calling 'Invoke' from your thread, if your main thread is waiting for a Thread.Join on the calling thread. I posted a workaround for this on the Microsoft site, which uses an extra thread to make the call to Invoke method, to avoid the deadlock. VB.NET example:
    Private Sub SetText(ByVal str_text As String)
            If Me.textbox1.InvokeRequired = True Then
                    'call an asyncronous invoke, by calling it then forcing a DoEvents
                    Dim asyncInvokeThread As New Threading.Thread(New Threading.ParameterizedThreadStart(AddressOf AsyncInvoke))
                    asyncInvokeThread.IsBackground = True
                    asyncInvokeThread.Start(str_text)
    
                    Application.DoEvents()
            Else
                    me.textbox1.text=str_text
            End If
    End Sub
    Private Sub AsyncInvoke(ByVal obj_text As Object)
            Dim str_text As String = CStr(obj_text)
            Dim d As New SetTextCallback(AddressOf SetText)
            Me.Invoke(d, New Object() {str_message})
    End Sub
  • Published on
    I joined in a "competition" with some of the experts in the assembly forums over at experts-exchange to write the fastest assembly code Base64 encoder, following the guidelines of the RFC3548. Several versions emerged, some using lookup tables to precompute results, which faired well on CPUs which large caches. My version was more about opcode optimization and using bitwise arithmetic over decimal arithmetic, which achieved best results on CPUs that have better pipelining. Code:
      void ToBase64( BYTE* pSrc, char* pszOutBuf, int len )
    {
          char* chr_table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    
           __asm{
                      mov ecx, len
                      mov esi, pSrc                              //;bytes from source
                      mov edi, chr_table
                      push ebp
                      mov ebp, pszOutBuf
    
    src_byteLoop:
    
                      xor eax, eax
    
                      //;read 3 bytes
                      mov ah, byte ptr[esi]
                      mov al, byte ptr[esi+1]
                      shl eax, 16
                      mov ah, byte ptr[esi+2]
    
                      //;manipulate in edx bitset1
                      mov edx, eax
                      shl eax, 6                                    //;done first 6 bits
    
                      shr edx, 26            
                      mov bl, byte ptr [edi+edx]            //;put char in buffer
                      mov byte ptr[ebp], bl
                      inc ebp                                          //;next buf
    
                      //;manipulate in edx bitset2
                      mov edx, eax
                      shl eax, 6                                    //;done first 6 bits
    
                      shr edx, 26
                      mov bl, byte ptr [edi+edx]            //;put char in buffer
                      mov byte ptr[ebp], bl
                      inc ebp                                          //;next buf
    
                      //;manipulate in edx bitset3
                      mov edx, eax
                      shl eax, 6                                    //;done first 6 bits
    
                      shr edx, 26
                      mov bl, byte ptr [edi+edx]            //;put char in buffer
                      mov byte ptr[ebp], bl
                      inc ebp                                          //;next buf
    
                      //;manipulate in edx bitset4
                      mov edx, eax
                      shl eax, 6                                    //;done first 6 bits
    
                      shr edx, 26
                      mov bl, byte ptr [edi+edx]            //;put char in buffer
                      mov byte ptr[ebp], bl
                      inc ebp                                          //;next buf
    
                      //;done these bytes
                      add esi, 3
                      sub ecx, 3
    
                      cmp ecx, 3
                      jge src_byteLoop                        //;still got src bytes
    
                      xor eax, eax                              //;set to zero (pad count)
                      cmp ecx, 0
                      jz finished
    
                            //;need to pad out some extra bytes
    
                            //;read in 3 bytes regardless of junk data following pSrc - already zero from above)
                            mov ah, byte ptr[esi]
                            mov al, byte ptr[esi+1]
                            shl eax, 16
                            mov ah, byte ptr[esi+2]
    
                            sub ecx, 3                                    //;bytes just read
                            neg ecx                                          //;+ve inverse
                            mov edx, ecx                              //;save how many bytes need padding
    
                            //;as per the RFC, any padded bytes should be 0s
                            mov esi, 0xFFFFFF
                            lea ecx, dword ptr[ecx*8+8]            //;calculate bitmask to shift
                            shl esi, cl
                            and eax, esi                              //;mask out the junk bytes
    
                            mov ecx, edx                              //;restore pad count
    
                            //;manipulate in edx byte 1
                            mov edx, eax
                            shl eax, 6                                    //;done first 6 bits                        
    
                            shr edx, 26
                            mov bl, byte ptr [edi+edx]            //;put char in buffer
                            mov byte ptr[ebp], bl
                            inc ebp                                          //;next buf
    
                            //;manipulate in edx byte 2
                            mov edx, eax
                            shl eax, 6                                    //;done first 6 bits                        
    
                            shr edx, 26
                            mov bl, byte ptr [edi+edx]            //;put char in buffer
                            mov byte ptr[ebp], bl
                            inc ebp                                          //;next buf
    
                            //;manipulate in edx byte 3
                            mov edx, eax
                            shl eax, 6                                    //;done first 6 bits                        
    
                            shr edx, 26
                            mov bl, byte ptr [edi+edx]            //;put char in buffer
                            mov byte ptr[ebp], bl
                            inc ebp                                          //;next buf
    
                            //;manipulate in edx byte 3
                            mov edx, eax
                            shl eax, 6                                    //;done first 6 bits                        
    
                            shr edx, 26
                            mov bl, byte ptr [edi+edx]                  //;put char in buffer
                            mov byte ptr[ebp], bl
                            inc ebp                                          //;next buf
    
                            mov eax, ecx                              //;'return' pad count
    
    finished:
                      test eax, eax
                      jz end
                      //;some bytes were padding, put them as =
    
                            sub ebp, eax                        //;move ptr back for num bytes to pad
    padChars:
                            mov byte ptr[ebp], 0x3d            //;=
                            inc ebp
                            dec eax
    
                            jnz padChars
    
    end:
                      pop ebp
            }      
    }
    There were several key points to my optimization technique:
    • Firstly unrolling of loops, which basically means eliminating any kind of loop structures in the code, in favour of manually typing the code to perform the operations on the data. In terms of asm optimizations this reduces branching and shifting EIP too often.
    • Another key point, was minimizing the load/store operations performed. To keep these down, you can use indirect addressing to get to the byte in memory you are interested in.e.g. mov edx, base add edx, edi mov bl, byte ptr[edx] becomes mov bl, [edx+edi]
    • As Base64 encoding requires you to work at bit level using 3 bytes at a time, you can speed up the conversion of the bit sets by using the binary arithmetic operations of SHL and SHR (shift left/right) to progressively take the most significant bits of one DWORD and operate on them with a lower significance by shifting them.For example, if EAX contains a DWORD and you copy that the EDX. You can get rid of the left most 6 bits of EAX by shifting left 6. You can deal with those 6 bits in EDX, by shifting EDX right 26 times. This is much quicker than shifting out one bit at a time.
    My final throughput on the official test machine was 196.92 MB/s, which is almost double the throughput of the CryptoAPI function, which came in at 104.05 MB/s
  • Published on
    When writing the "UltraChat" program, at university, I needed to write a port scanner that would look for running UltraChat servers. A port scanner basically attempts to connect to a host on a given port and return true or false if a connection was (or wasn't) established. The problem with doing this is that when a connection cannot be establish, Winsock (windows sockets) will keep trying, allowing for servers that are slow to reply. Which then slows the whole process down. To get around this I used a simple threading and timer technique to kill the request if it doesnt succeed within a given time. Code:
    bool quickConnect(char* remoteHostIP, int port)
    {
          struct sockaddr_in sAddress;
    
          //set up connection info
          sAddress.sin_family = AF_INET;
          sAddress.sin_port = htons(port);                                                      //port
          sAddress.sin_addr.S_un.S_addr = inet_addr(remoteHostIP);                  //IP
    
          //use a thread to do the connection
          HANDLE tConnThread;
          DWORD threadID;
          DWORD tExitCode=0;
    
          tConnThread=CreateThread(NULL,0,&quickConnectTTL,&sAddress,0,&threadID);
    
          //now wait 1seconds maximum for response
          SYSTEMTIME now;
          GetSystemTime(&now);
    
          int finishTime=(now.wDay * 24 * 60)+(now.wHour * 60)+(now.wSecond)+1;
          int nowTime=0;
    
          while(nowTime<finishTime){
                GetSystemTime(&now);
                nowTime=(now.wDay * 24 * 60)+(now.wHour * 60)+(now.wSecond);
                //check if already exited, dont waste time
                GetExitCodeThread(tConnThread,&tExitCode);
                if(tExitCode!=STILL_ACTIVE){
                      break;
                }
          }
    
          //get the return value from connection
          GetExitCodeThread(tConnThread,&tExitCode);
    
          //if thread did not exit, time is up, close the thread and assume no server
          if(tExitCode==STILL_ACTIVE){
                TerminateThread(tConnThread,0);
                tExitCode=0;
          }
    
          CloseHandle(tConnThread);
    
          bool present;
          //check return values
          if(tExitCode==1){
                present=true;
          }
          else{
                present=false;
          }
    
          return present;
    
    }
    
    DWORD WINAPI quickConnectTTL(LPVOID sAddressPTR){
          //copy struct info from PTR
          struct sockaddr_in sAddress;
          memcpy(&sAddress,sAddressPTR,sizeof(struct sockaddr_in));
    
          //connect to remote host
          int concode;
          SOCKET s=socket(AF_INET,SOCK_STREAM,0);
          concode=connect(s ,(struct sockaddr *)&sAddress,sizeof(sAddress));
    
          if(concode==SOCKET_ERROR){
                ExitThread(0);
                return 0;
          }
          else{
                closesocket(s);
                ExitThread(1);
                return 1;
          }
    }
    The above example waits 1 second for a reply, and then assumes a false result. To use the code, you need to include the windows sockets headers and initialise the winsock, then call quickConnect passing the host/port.