2017-01-25 8 views
0

Я работал над реализацией декодера base64 в C. Я читал об конвертации base64 в таких местах, как Wikipedia page, а также с помощью онлайн converters для проверки моей работы. Кажется прямолинейным: просто замените каждый символ base64 на соответствующую 6-битную двоичную строку!C: Base 64 to двоичное преобразование

My Base64-to-binary decoding является правильным, если строка base64 для декодирования кратна 4. Если длина строки не кратна 4 или имеются одинаковые знаки для заполнения, мой код делает не соответствуют результатам от онлайн-конвертеров.

Мне показалось, что я понял прокладку - просто замените символ '=' нулями (6, для 6 бит). Тем не менее, я все еще не согласую результат конвертера, когда он используется.

Вот код, который я написал:

int main(void){ 

    printf("Testing b642bin ...\n\n"); 
    printf("Case 1: Converting 'AA==' to bin:\n"); 
    printf("Expected Result: 000000000000000000000000\n"); 
    printf("Actual Result: %s\n\n", b642bin("AA==")); 
    printf("Case 2: Converting '+aHg' to bin:\n"); 
    printf("Expected Result: 111110011010000111100000\n"); 
    printf("Actual Result: %s\n\n", b642bin("+aHg")); 
    printf("Case 3: Converting 'kNSHd94m7d+=' to bin:\n"); 
    printf("Expected Result: 1001000011010100100001110111011111011110001001101110110111011111\n"); 
    printf("Actual Result: %s\n\n", b642bin("kNSHd94m7d+=")); 

    return 0; 
} 

char bin6_table[65][7] = {"000000", "000001", "000010", "000011", "000100", 
         "000101","000110", "000111", "001000", "001001", 
         "001010", "001011", "001100", "001101", "001110", 
         "001111", "010000", "010001", "010010", "010011", 
         "010100", "010101", "010110", "010111", "011000", 
         "011001", "011010", "011011", "011100", "011101", 
         "011110", "011111", "100000", "100001", "100010", 
         "100011", "100100", "100101", "100110", "100111", 
         "101000", "101001", "101010", "101011", "101100", 
         "101101", "101110", "101111", "110000", "110001", 
         "110010", "110011", "110100", "110101", "110110", 
         "110111", "111000", "111001", "111010", "111011", 
         "111100", "111101", "111110", "111111", "000000"}; 

char base64_table[65] =  {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 
         'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 
         'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 
         'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 
         'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 
         'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 
         'w', 'x', 'y', 'z', '0', '1', '2', '3', 
         '4', '5', '6', '7', '8', '9', '+', '/','='}; 

char* b64Char2bin(char b64){ 

    int n = 64; 
    int k; 
    char *bin; 

    for(k=0;k<n;k++){ 
     if (b64 == base64_table[k]) { 
      bin = bin6_table[k]; 
      break; 
     } 
    } 
    return bin; 
} 

char* b642bin(char *b64_str) { 

    int i; 
    size_t len = strlen(b64_str); 

    char* bin_str = (char*)malloc(((len * 6) + 1) * sizeof(char)); 
    for (i = 0; i < (int)len; i++) { 
     const char* binSextet = b64Char2bin(b64_str[i]); 
     memcpy(&bin_str[6*i], binSextet,7); 
    } 

    return bin_str; 
} 

Результат выглядит следующим образом:

Тестирование b642bin ...

Case 1: Converting 'AA==' to bin: 
Expected Result: 000000000000000000000000 
Actual Result: 000000000000000000000000 

Case 2: Converting '+aHg' to bin: 
Expected Result: 111110011010000111100000 
Actual Result: 111110011010000111100000 

Case 3: Converting 'kNSHd94m7d+=' to bin: 
Expected Result: 1001000011010100100001110111011111011110001001101110110111011111 
Actual Result: 100100001101010010000111011101111101111000100110111011011101111110000000 

Если преобразователь я предоставил правильно, Я не понимаю Base64. Ясно, что вы не просто заменяете каждый символ соответствующими 6 битами двоичного кода. Почему дела 1 и 2 верны, но дело 3 нет?

ответ

0

Байты (ну, октеты, если вы хотите получить все технические), имеют длину 8 бит. Base64 кодирует 6 бит за раз. Заполнение используется, когда количество байтов, которые были закодированы , не является, а кратным три, поэтому число бит не равно, умноженное на шесть. При декодировании base64 с заполнением вы не выводите больше нулевых битов, вы выводите меньше бит для создания правильного количества байтов.

В качестве конкретного примера:

Base64: ////
Двоичный: 11111111 11111111 11111111

Base64: //8=
Двоичный: 11111111 11111111

Base64: /w==
Двоичный: 11111111

+0

Каждый случай, который вы предоставили, имеет смысл. Не могли бы вы объяснить пример 3 в моем примере? Первые 10 символов Base64 отлично кодируют 10 * 6 бит = 60 бит, что по-прежнему составляет 4 бита, равных 8 байтам, поэтому я понимаю, что нам нужно еще 4 бита. Тем не менее, 11-й символ Base64, '+', задается в двоичном формате как «111110» - 5 бит без 0-х - кажется, нам нужно 65 бит для кодирования этой строки. Вы можете это объяснить? Как бы выглядело преобразование для kNSHd94m7d + = vs. kNSHd94m7d8 = и почему? – Matt

+0

@Matt правильный кодировщик Base64 не будет генерировать 'kNSHd94m7d + ='. Строгий декодер отклонил бы его как недействительный; прощающий будет декодировать его так же, как 'kNSHd94m7d8 ='. – hobbs

+0

(только 'A',' Q', 'g' или' w' должны предшествовать '==' и только 'A',' E', 'I',' M', 'Q',' U ',' Y', 'c',' g', 'k',' o', 's',' w', '0',' 4' или '8' должны предшествовать' = 'в правильном Base64 .) – hobbs