Learn how to use Base64 in programming languages: C#, C++, C, Java
, ,

C++ Base64 Guide: Encoding and Decoding Explained

Like C, C++ does not natively support Base64 decoding, so to implement it in C++ you must either use an external library or write your own implementation to execute the method.

In this article, we’ll introduce you to suitable external libraries and explain the Base64 algorithm in case you want to implement it yourself.

What is Base64?

Base64 is a method for encoding binary data into a human-readable format that may be easily shared between systems. Encoding includes transforming byte sequences into a set of ASCII characters to ensure interoperability with text-based platforms. Although it is not ideal for encryption, Base64 encoding is useful for situations such as incorporating images in emails or embedding files within code since it simplifies the handling of binary data in a variety of applications.

What is C++?

C++ is a robust and versatile programming language that is well-known for its speed and flexibility. It combines high-level and low-level programming features, making it appropriate for a wide range of applications ranging from system software to game creation. C++ supports object-oriented programming, memory management, and the ability to write efficient and optimized code.

Base64 Encoding and Decoding in C++

C++ does not have any native functions for Base64 encoding and decoding. Base64 encoding and decoding can, however, be accomplished using standard library functions for character manipulation and arithmetic operations. This necessitates the creation of custom code to divide the binary data into groups, translate those groups into ASCII characters, and manage padding.

Many developers prefer to use third-party libraries that provide ready-made functions for Base64 encoding and decoding to simplify the process and boost code efficiency. Here are some popular libraries to consider:

  1. Boost C++ Libraries: The Boost C++ Libraries include a base64 module that provides functions for encoding and decoding data. Boost is widely used and well-documented, making it a reliable choice.
  2. OpenSSL: While OpenSSL is primarily known for its cryptography features, it also includes functions for Base64 encoding and decoding. The library is widely used in security-sensitive applications and provides efficient solutions.
  3. Poco C++ Libraries: Poco is another set of C++ libraries that includes a Base64 class, making it easy to perform encoding and decoding operations.

When using third-party libraries, you typically follow these steps:

  1. Include the Library Headers: Include the appropriate header files from the library in your C++ source code using the #include directive.
  2. Linking: If the library is provided as a compiled object file or shared library, you need to link your code with it during the compilation process. Refer to the library’s documentation for specific linking instructions.
  3. Use Library Functions: Once the library is included and linked, you can use its functions to perform Base64 encoding and decoding operations on your data.

Here is a more detailed description.

Example: Base64 Encoding with OpenSSL

Here’s a basic example in C++ that uses OpenSSL to encode binary data into Base64:

#include <openssl/bio.h>
#include <openssl/evp.h>
 
std::string Base64Encode(const std::string &input) {
    BIO *bio, *b64;
    BUF_MEM *bufferPtr;
 
    b64 = BIO_new(BIO_f_base64());
    bio = BIO_new(BIO_s_mem());
    bio = BIO_push(b64, bio);
 
    BIO_write(bio, input.c_str(), input.length());
    BIO_flush(bio);
    BIO_get_mem_ptr(bio, &bufferPtr);
 
    std::string encoded(bufferPtr->data, bufferPtr->length);
    BIO_free_all(bio);
 
    return encoded;
}
 
int main() {
    std::string data = "B64Encode.com";
    std::string encoded = Base64Encode(data);
    std::cout << "Encoded: " << encoded << std::endl;
 
    return 0;
}

In this example, the OpenSSL library is used to perform Base64 encoding on the input data. The Base64Encode function takes binary input data and returns its Base64-encoded version.

Example: Base64 Decoding with OpenSSL

Here’s a basic example of Base64 decoding in C++ using OpenSSL:

#include <openssl/bio.h>
#include <openssl/evp.h>
 
std::string Base64Decode(const std::string &input) {
    BIO *bio, *b64;
    char *buffer = new char[input.size()];
 
    b64 = BIO_new(BIO_f_base64());
    bio = BIO_new_mem_buf(input.c_str(), -1);
    bio = BIO_push(b64, bio);
 
    BIO_read(bio, buffer, input.size());
    BIO_free_all(bio);
 
    std::string decoded(buffer);
    delete[] buffer;
 
    return decoded;
}
 
int main() {
    std::string encodedData = "QjY0RW5jb2RlLmNvbQ==";
    std::string decoded = Base64Decode(encodedData);
    std::cout << "Decoded: " << decoded << std::endl;
 
    return 0;
}

In this example, the Base64Decode function decodes a Base64-encoded string into its original binary form using OpenSSL. The function receives the specified encoded string and returns the decoded binary data.

Implementing Base64 Encoding Algorithm in Pseudocode

If you don’t want to use an external library, you can try to implement Base64 encoding and decoding yourself. The good news is that Base64 is not a very complicated method, so it is not too difficult to program.

Since Base64 encoding operates on a language-independent concept, any programming language can use it. The following illustration shows how to use a language-independent technique to implement Base64 encoding.

If you want more details, this article explains Base64 in more detail.

Here’s an example of a language-agnostic algorithm in pseudocode:

function base64_encode(input)
    // The base character set
    const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
 
    // The length of the input
    let input_length = length(input)
 
    // The output
    let output = ""
 
    // Process the input in 3-byte blocks
    for i from 0 to input_length - 1 step 3
        // The value of the block
        let block_value = (input[i] << 16) + (input[i + 1] << 8) + input[i + 2]
 
        // Encode the block into 4 characters
        for j from 0 to 3
            let index = (block_value >> ((3 - j) * 6)) & 0x3F
            output += BASE64_CHARS[index]
        end for
    end for
 
    // Pad the output length with '=' characters if necessary
    let padding = input_length % 3
    if padding > 0
        for i from 0 to (3 - padding)
            output[output.length - i - 1] = '='
        end for
    end if
 
    return output
end function

Here is an explanation of the code, broken down into a list:

  1. The binary data to be encoded is passed as an input parameter to the base64_encode function.
  2. The basic character set for the encoding, which consists of 64 characters, is designated by the constant BASE64_CHARS.
  3. The length of the input data is used to calculate the input_length variable.
  4. The output variable, which will hold the result of the encoding, is initially set to an empty string.
  5. A for loop that iterates from 0 to input_length – 1 with a step of 3 processes the input data in 3-byte blocks.
  6. The first byte is shifted left by 16 bits for each block, the second byte is shifted left by 8 bits, and the third byte is added to determine the block_value variable for each block.
  7. A second for loop that iterates from 0 to 3 is then used to encode the block into 4 characters.
  8. For each character, an index is calculated by shifting the block_value to the right by a multiple of 6 bits and masking it with 0x3F.
  9. The character at this index in the BASE64_CHARS constant is then appended to the output string.
  10. After all blocks have been processed, the output length is padded with ‘=’ characters if necessary.
  11. To accomplish this, the padding is determined by dividing the input_length by 3.
  12. A for loop iterates from 0 to (3 – padding) and replaces the final characters of the output string with ‘=‘ characters if padding is higher than 0.
  13. The function then returns the result that was encoded and saved in the output variable.

Implementing Base64 Decoding Algorithm in Pseudocode

Now let’s look at decoding independently of the programming language.

function base64_decode(input)
    // The base character set
    const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
 
    // The length of the input
    let input_length = length(input)
 
    // The output
    let output = []
 
    // Process the input in 4-character blocks
    for i from 0 to input_length - 1 step 4
        // The value of the block
        let block_value = (index_of(BASE64_CHARS, input[i]) << 18) + (index_of(BASE64_CHARS, input[i + 1]) << 12) + (index_of(BASE64_CHARS, input[i + 2]) << 6) + index_of(BASE64_CHARS, input[i + 3])
 
        // Decode the block into 3 bytes
        for j from 0 to 2
            let byte = (block_value >> ((2 - j) * 8)) & 0xFF
            output.append(byte)
        end for
    end for
 
    // Remove any padding bytes from the output
    let padding = count(input, '=')
    if padding > 0
        output = output[0:output.length - padding]
    end if
 
    return output
end function
  • The base64_decode function takes an input parameter, which is the string of characters to be decoded.
  • The BASE64_CHARS constant is defined as the base character set for the decoding, which consists of 64 characters.
  • The length of the input string is used to calculate the input_length variable.
  • The output variable, which will hold the result of the decoding, is initialized as an empty array.
  • The input data is processed in 4-character blocks using a for loop that iterates from 0 to input_length - 1 with a step of 4.
  • For each block, the block_value variable is calculated by shifting the index of each character in the BASE64_CHARS constant to the left by a multiple of 6 bits and adding them together.
  • Then, a second for loop iterating from 0 to 2 decodes the block into 3 bytes.
  • By moving the block_value to the right by a multiple of 8 bits and masking it with 0xFF, a value is computed for each byte. This value is then appended to the output array.
  • If necessary, any padding bytes are taken out of the output once all blocks have been processed. The count function is used to determine how many padding characters (‘=‘) are present in the input, and then the appropriate number of bytes are subtracted from the end of the output array.
  • Finally, the function returns the decoded result stored in the output array.