Base32

Från Täpp-Anders
Hoppa till navigeringHoppa till sök

För bakgrundsinformation se Base64.

Implementation

C

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// BASE32 kodningstabell
static const char base32_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";

// Funktion för BASE32 kodning
char* base32_encode(const unsigned char* input, size_t length) {
    // Beräkna utdatalängd: 8 tecken för varje 5 bytes
    size_t output_length = 8 * ((length + 4) / 5);
    char* encoded = malloc(output_length + 1);
    if (encoded == NULL) return NULL;
    
    size_t i = 0, j = 0;
    unsigned long buffer = 0;
    int bits_left = 0;
    
    while (i < length || bits_left > 0) {
        // Fyll buffert med upp till 5 bytes
        if (bits_left < 5 && i < length) {
            buffer = (buffer << 8) | input[i++];
            bits_left += 8;
        }
        
        // Om vi har minst 5 bitar, ta ut ett BASE32-tecken
        if (bits_left >= 5) {
            int value = (buffer >> (bits_left - 5)) & 0x1F;
            encoded[j++] = base32_table[value];
            bits_left -= 5;
        } else if (i >= length) {
            // Padding för sista gruppen
            encoded[j++] = '=';
            bits_left = 0;
        }
    }
    
    // Fyll på med padding till multipel av 8
    while (j % 8 != 0) {
        encoded[j++] = '=';
    }
    
    encoded[j] = '\0';
    return encoded;
}

// Funktion för BASE32 avkodning
unsigned char* base32_decode(const char* input, size_t* output_length) {
    size_t input_length = strlen(input);
    if (input_length % 8 != 0) return NULL; // BASE32 måste vara multipler av 8
    
    // Räkna faktiska databytes (exkludera padding)
    size_t padding = 0;
    for (int i = input_length - 1; i >= 0 && input[i] == '='; i--) {
        padding++;
    }
    
    // Beräkna utdatalängd
    *output_length = (input_length * 5) / 8 - padding;
    unsigned char* decoded = malloc(*output_length);
    if (decoded == NULL) return NULL;
    
    // Skapa lookup-tabell
    unsigned char decode_table[256] = {0};
    for (int i = 0; i < 32; i++) {
        decode_table[(unsigned char)base32_table[i]] = i;
    }
    
    unsigned long buffer = 0;
    int bits_left = 0;
    size_t j = 0;
    
    for (size_t i = 0; i < input_length; i++) {
        if (input[i] == '=') break;
        
        buffer = (buffer << 5) | decode_table[(unsigned char)input[i]];
        bits_left += 5;
        
        if (bits_left >= 8) {
            decoded[j++] = (buffer >> (bits_left - 8)) & 0xFF;
            bits_left -= 8;
        }
    }
    
    return decoded;
}

// Testprogram
int main() {
    const char* original = "Hello World!";
    size_t input_length = strlen(original);
    
    // Kodning
    char* encoded = base32_encode((const unsigned char*)original, input_length);
    if (!encoded) {
        printf("Kodningsfel\n");
        return 1;
    }
    
    // Avkodning
    size_t decoded_length;
    unsigned char* decoded = base32_decode(encoded, &decoded_length);
    if (!decoded) {
        printf("Avkodningsfel\n");
        free(encoded);
        return 1;
    }
    
    // Skriv ut resultat
    printf("Original: %s\n", original);
    printf("BASE32: %s\n", encoded);
    printf("Decoded: %.*s\n", (int)decoded_length, decoded);
    
    // Frigör minne
    free(encoded);
    free(decoded);
    
    return 0;
}