2015-09-27 2 views
0

Я пытаюсь base64 кодировать строку в Юникоде. Я столкнулся с проблемами, после кодирования вывод - это моя строка base64'ed, однако в каждом коде есть нулевые байты в случайных местах, я не знаю, почему, или как их получить.C++ Base64 Unicode - null bytes

Вот моя Base64Encode функция:

static char Base64Digits[] = 
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/"; 
int Base64Encode(const BYTE* pSrc, int nLenSrc, wchar_t* pDst, int nLenDst) 
{ 
    int nLenOut= 0; 
    while (nLenSrc > 0) { 
    if (nLenOut+4 > nLenDst) return(0); // error 

    // read three source bytes (24 bits) 
    BYTE s1= pSrc[0]; // (but avoid reading past the end) 
    BYTE s2= 0; if (nLenSrc>1) s2=pSrc[1]; //------ corrected, thanks to jprichey 
    BYTE s3= 0; if (nLenSrc>2) s3=pSrc[2]; 

    DWORD n; 
    n = s1; // xxx1 
    n <<= 8; // xx1x 
    n |= s2; // xx12 
    n <<= 8; // x12x 
    n |= s3; // x123 

    //-------------- get four 6-bit values for lookups 
    BYTE m4= n & 0x3f; n >>= 6; 
    BYTE m3= n & 0x3f; n >>= 6; 
    BYTE m2= n & 0x3f; n >>= 6; 
    BYTE m1= n & 0x3f; 

    //------------------ lookup the right digits for output 
    BYTE b1 = Base64Digits[m1]; 
    BYTE b2 = Base64Digits[m2]; 
    BYTE b3 = Base64Digits[m3]; 
    BYTE b4 = Base64Digits[m4]; 

    //--------- end of input handling 
    *pDst++ = b1; 
    *pDst++ = b2; 
    if (nLenSrc >= 3) { // 24 src bits left to encode, output xxxx 
    *pDst++ = b3; 
    *pDst++ = b4; 
    } 
    if (nLenSrc == 2) { // 16 src bits left to encode, output xxx= 
    *pDst++ = b3; 
    *pDst++ = '='; 
    } 
    if (nLenSrc == 1) { // 8 src bits left to encode, output xx== 
    *pDst++ = '='; 
    *pDst++ = '='; 
    } 
    pSrc += 3; 
    nLenSrc -= 3; 
    nLenOut += 4; 
} 
// Could optionally append a NULL byte like so: 
// *pDst++= 0; nLenOut++; 
return(nLenOut); 
} 

Не обмануть кого угодно, но я скопировал функцию от here

Вот как я вызываю функцию:

wchar_t base64[256]; 

Base64Encode((const unsigned char *)UserLoginHash, lstrlenW(UserLoginHash) * 2, base64, 256); 

Итак, почему в генерируемом хэше есть случайные null-байты или «пробелы»? Что нужно изменить, чтобы я мог избавиться от них?

+1

Можете ли вы привести пример этих «нулевых байтов»? Как вы их наблюдаете? –

+0

Код выглядит хорошо для меня. –

+1

base64 не создает нулевые выходные символы. Если ваш вывод имеет в нем значения NULL, ваша реализация неверна. При этом 16-битные символы Unicode в диапазонах '0x00XX' и' 0xXX00' имеют в них нулевые байты. base64 работает с байтами, а не с символами, и он просто кодирует нулевые входные байты. –

ответ

0

Проблема, из того, что я вижу, заключается в том, что по мере того, как работает кодер, иногда он добавляет значение к определенному значению символа, например, U + 0070 + U + 0066 (это только пример). В какой-то момент эти значения равны нулевому терминатору (\ 0) или чем-то эквивалентному ему, что делает его таким, чтобы программа не читала эту точку при выводе строки и заставляла ее казаться короче, чем она должна быть.

Я столкнулся с этой проблемой с моим собственным алгоритмом кодирования раньше, и лучшим решением является добавление большей вариативности к вашему алгоритму; поэтому вместо добавления символов в строку вычитайте часть, умножьте или XOR в некоторой точке алгоритма. Это должно удалить (или, по крайней мере, уменьшить шансы) нулевых терминаторов, появляющихся там, где вы их не хотите. Это может, однако, принять некоторые пробные ошибки с вашей стороны, чтобы увидеть, что работает, а что нет.

2

Попробуйте что-нибудь еще. Части, скопированные из моего собственного датчика base64:

static const wchar_t *Base64Digits = L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/"; 

int Base64Encode(const BYTE* pSrc, int nLenSrc, wchar_t* pDst, int nLenDst) 
{ 
    int nLenOut = 0; 

    while (nLenSrc > 0) { 
     if (nLenDst < 4) return(0); // error 

     // read up to three source bytes (24 bits) 
     int len = 0; 
     BYTE s1 = pSrc[len++]; 
     BYTE s2 = (nLenSrc > 1) ? pSrc[len++] : 0 
     BYTE s3 = (nLenSrc > 2) ? pSrc[len++] : 0; 
     pSrc += len; 
     nLenSrc -= len; 

     //------------------ lookup the right digits for output 
     pDst[0] = Base64Digits[(s1 >> 2) & 0x3F]; 
     pDst[1] = Base64Digits[(((s1 & 0x3) << 4) | ((s2 >> 4) & 0xF)) & 0x3F]; 
     pDst[2] = Base64Digits[(((s2 & 0xF) << 2) | ((s3 >> 6) & 0x3)) & 0x3F]; 
     pDst[3] = Base64Digits[s3 & 0x3F]; 

     //--------- end of input handling 
     if (len < 3) { // less than 24 src bits encoded, pad with '=' 
      pDst[3] = L'='; 
      if (len == 1) 
      pDst[2] = L'='; 
     } 

     nLenOut += 4; 
     pDst += 4; 
     nLenDst -= 4; 
    } 

    if (nLenDst > 0) *pDst = 0; 

    return (nLenOut); 
}