News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Base64 encoding and decoding

Started by Biterider, November 16, 2023, 04:30:18 AM

Previous topic - Next topic

Biterider

Hi
While I'm dealing with a network issue, I decided to take a break and deal with a dependency I want to eliminate.
Base64 encoding/decoding (RFC-4648) has been implemented by MS in the crypto API (Crypt32.dll).
While reading about the topic, I came across the statement several times that the performance of the API is not the best. Because of this, I decided to invest a little time to check this out.
To make a fair comparison, I included all the necessary steps, from querying the buffer size and memory allocation, up to the final result.
I developed this lookup algo and compared it to the original API.
I developed an encoding and a decoding method using lookup tables and compared the timing with the original API.
The time difference measured with a rough measuring method is striking.
My trivial, non-optimised code runs ~20x faster...  :dazzled:

Here the testbed
  New SW::StopWatch
  OCall SW::StopWatch.Init, NULL
  mov xax, offset BINARY
  mov pBinary, xax

  ;================================================================
  OCall SW::StopWatch.Reset
  OCall SW::StopWatch.Start
  invoke CryptBinaryToStringA, pBinary, dBinarySize, CRYPT_STRING_BASE64, NULL, addr dEncryptedBufferSize
  .if eax
    MemAlloc dEncryptedBufferSize
    .if xax
      mov pEncryptedBuffer, xax
      invoke CryptBinaryToStringA, pBinary, dBinarySize, CRYPT_STRING_BASE64, pEncryptedBuffer, addr dEncryptedBufferSize
    .endif
  .endif
  OCall SW::StopWatch.Stop
  OCall SW::StopWatch.GetTimeStrA, addr Runtime
  DbgStrA Runtime, "µS for CryptBinaryToStringA"
 
  OCall SW::StopWatch.Reset
  OCall SW::StopWatch.Start
  invoke CryptStringToBinaryA, pEncryptedBuffer, dEncryptedBufferSize, CRYPT_STRING_BASE64, NULL, addr dDecryptedBufferSize, NULL, NULL
  .if eax
    MemAlloc dDecryptedBufferSize
    .if xax
      mov pDecryptedBuffer, xax
      invoke CryptStringToBinaryA, pEncryptedBuffer, dEncryptedBufferSize, CRYPT_STRING_BASE64, pDecryptedBuffer, addr dDecryptedBufferSize, NULL, NULL
    .endif
  .endif
  OCall SW::StopWatch.Stop
  OCall SW::StopWatch.GetTimeStrA, addr Runtime
  DbgStrA Runtime, "µS for CryptStringToBinaryA"
 
  ;================================================================
  DbgLine

  OCall SW::StopWatch.Reset
  OCall SW::StopWatch.Start
  invoke Base64Encode, pBinary, dBinarySize
  mov pEncryptedBuffer, xax
  mov dEncryptedBufferSize, ecx
  OCall SW::StopWatch.Stop
  OCall SW::StopWatch.GetTimeStrA, addr Runtime
  DbgStrA Runtime, "µS for Base64Encode"


  OCall SW::StopWatch.Reset
  OCall SW::StopWatch.Start
  invoke Base64Decode, pEncryptedBuffer, dEncryptedBufferSize
  mov pDecryptedBuffer, xax
  mov dDecryptedBufferSize, ecx
  OCall SW::StopWatch.Stop
  OCall SW::StopWatch.GetTimeStrA, addr Runtime
  DbgStrA Runtime, "µS for Base64Decode"

Attached are the encoding and decoding bitness neutral procedures .

Regards, Biterider