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