Share this page 

Encode/decode a string in Base64Tag(s): WinAPI/Registry


WinXP (or better), this HowTo is based the Microsoft Crypto API.

Base64 can be used to quickly encoded/decode sensitive information in the Registry or INI file. Note that Base64 encoding is NOT a secure algorithm but it hides informations from casual readers.

The string realhowto in Base64 is cmVhbGhvd3Rv.

Inspired by this winsock user object.
A nice tool to check your encoded strings is http://paulschou.com/tools/xlate/.

[local function declaration]
//BOOL WINAPI CryptBinaryToString(
//    const BYTE* pbBinary,
//    DWORD cbBinary,
//    DWORD dwFlags,
//    LPTSTR pszString,
//    DWORD* pcchString
//);
FUNCTION boolean CryptBinaryToString ( &
    Blob pbBinary, &
    ulong cbBinary, &
    ulong dwFlags, &
    Ref string pszString, &
    Ref ulong pcchString ) &
LIBRARY "crypt32.dll" ALIAS FOR "CryptBinaryToStringA"

//BOOL WINAPI CryptStringToBinary(
//    LPCTSTR pszString,
//    DWORD cchString,
//    DWORD dwFlags,
//    BYTE* pbBinary,
//    DWORD* pcbBinary,
//    DWORD* pdwSkip,
//    DWORD* pdwFlags
//);
//

FUNCTION boolean CryptStringToBinary ( &
    string pszString, &
    ulong cchString, &
    ulong dwFlags, &
    Ref blob pbBinary, &
    Ref ulong pcbBinary, &
    Ref ulong pdwSkip, &
    Ref ulong pdwFlags ) &
LIBRARY "crypt32.dll" ALIAS FOR "CryptStringToBinaryA"

[instance variables]
// Base64, with certificate beginning and ending headers
CONSTANT Ulong CRYPT_STRING_BASE64HEADER = 0

// Base64, without headers
CONSTANT Ulong CRYPT_STRING_BASE64 = 1

// Pure binary copy
CONSTANT Ulong CRYPT_STRING_BINARY = 2

// Base64, with request beginning and ending headers
CONSTANT Ulong CRYPT_STRING_BASE64REQUESTHEADER = 3

// Hexadecimal only
CONSTANT Ulong CRYPT_STRING_HEX = 4

//  Hexadecimal, with ASCII character display
CONSTANT Ulong CRYPT_STRING_HEXASCII = 5

// Base64, with X.509 CRL beginning and ending headers
CONSTANT Ulong CRYPT_STRING_BASE64X509CRLHEADER = 9

// Hexadecimal, with address display
CONSTANT Ulong CRYPT_STRING_HEXADDR = 10

// Hexadecimal, with ASCII character and address display
CONSTANT Ulong CRYPT_STRING_HEXASCIIADDR = 11

// A raw hex string. WinServer 2K3, WinXP:  This value is not supported.
CONSTANT Ulong CRYPT_STRING_HEXRAW = 12
( MSDN )

Encode a String to Base64

String ls_encoded
ULong lul_len, lul_buflen
Boolean lb_rtn

Blob  value

// the value to be encoded, needs to be 3 char or more (but not 4?)
value = blob(sle_1.text)

lul_len = Len(value)
lul_buflen = lul_len * 2
ls_encoded = Space(lul_buflen)

lb_rtn = CryptBinaryToString(value, &
                lul_len, CRYPT_STRING_BASE64, &
                ls_encoded, lul_buflen)

IF NOT lb_rtn THEN
    ls_encoded = ""
ELSE
    // remove the last two chr(0)!
    ls_encoded = left(ls_encoded, len(ls_encoded) - 2 )
END IF

sle_2.text =  ls_encoded

Decode Base64 to a String

Blob lblob_data
ULong lul_len, lul_buflen, lul_skip, lul_pflags
Boolean lb_rtn

String value

value = sle_2.text // the value to be decoded

lul_len = Len(value)
lul_buflen = lul_len
lblob_data = Blob(Space(lul_len))

lb_rtn = CryptStringToBinary(value, &
                    lul_len, CRYPT_STRING_BASE64, lblob_data, &
                    lul_buflen, lul_skip, lul_pflags)

sle_1.text = string(BlobMid(lblob_data, 1, lul_buflen))

Since PB10 or better handles string as Unicode (16-bits wide and not 8-bits like PB previous versions), you must change the function declarations to :
FUNCTION boolean CryptBinaryToString ( &
    Blob pbBinary, &
    ulong cbBinary, &
    ulong dwFlags, &
    Ref string pszString, &
    Ref ulong pcchString ) &
LIBRARY "crypt32.dll" ALIAS FOR "CryptBinaryToStringA;Ansi"

FUNCTION boolean CryptStringToBinary ( &
    string pszString, &
    ulong cchString, &
    ulong dwFlags, &
    Ref blob pbBinary, &
    Ref ulong pcbBinary, &
    Ref ulong pdwSkip, &
    Ref ulong pdwFlags ) &
LIBRARY "crypt32.dll" ALIAS FOR "CryptStringToBinaryA;Ansi"
When you encode the string, you need to make sure to store in blob an Ansi encoding string.

Encode a String to Base64 (PB10+)

...
value = blob(sle_1.text,  EncodingANSI!)
...