Repository: TheAlgorithms/Java
File: src/main/java/com/thealgorithms/conversions/Base64.java (Java)

Code before:

        return encode(input.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * Decodes the given Base64 encoded string to a byte array.
     *
     * @param input the Base64 encoded string to decode
     * @return the decoded byte array
     * @throws IllegalArgumentException if input is null or contains invalid Base64 characters
     */
    public static byte[] decode(String input) {
        if (input == null) {
            throw new IllegalArgumentException("Input cannot be null");
        }

        if (input.isEmpty()) {
            return new byte[0];
        }

        // Remove padding for processing
        String cleanInput = input.replace("=", "");
        int padding = input.length() - cleanInput.length();

        // Validate input length
        if ((cleanInput.length() % 4) + padding > 4) {
            throw new IllegalArgumentException("Invalid Base64 input length");
        }

        List<Byte> result = new ArrayList<>();

        // Process input in groups of 4 characters
        for (int i = 0; i < cleanInput.length(); i += 4) {
            // Get up to 4 characters
            int char1 = getBase64Value(cleanInput.charAt(i));
            int char2 = (i + 1 < cleanInput.length()) ? getBase64Value(cleanInput.charAt(i + 1)) : 0;
            int char3 = (i + 2 < cleanInput.length()) ? getBase64Value(cleanInput.charAt(i + 2)) : 0;
            int char4 = (i + 3 < cleanInput.length()) ? getBase64Value(cleanInput.charAt(i + 3)) : 0;

            // Combine four 6-bit groups into a 24-bit number
            int combined = (char1 << 18) | (char2 << 12) | (char3 << 6) | char4;

            // Extract three 8-bit bytes
            result.add((byte) ((combined >> 16) & 0xFF));
            if (i + 2 < cleanInput.length() || (i + 2 == cleanInput.length() && padding < 2)) {
                result.add((byte) ((combined >> 8) & 0xFF));
            }
            if (i + 3 < cleanInput.length() || (i + 3 == cleanInput.length() && padding < 1)) {
                result.add((byte) (combined & 0xFF));
            }
        }

Review comment (suggestion):
Some Base64 decoders are lenient and will accept inputs like QQ=, but strictly speaking (RFC 4648) the length must be a multiple of 4. If we want strict compliance, we should keep this as this repository for educational purposes.

Code after:

        return encode(input.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * Decodes the given Base64 encoded string to a byte array.
     *
     * @param input the Base64 encoded string to decode
     * @return the decoded byte array
     * @throws IllegalArgumentException if input is null or contains invalid Base64 characters
     */
    public static byte[] decode(String input) {
        if (input == null) {
            throw new IllegalArgumentException("Input cannot be null");
        }

        if (input.isEmpty()) {
            return new byte[0];
        }

        // Strict RFC 4648 compliance: length must be a multiple of 4
        if (input.length() % 4 != 0) {
            throw new IllegalArgumentException("Invalid Base64 input length; must be multiple of 4");
        }

        // Validate padding: '=' can only appear at the end (last 1 or 2 chars)
        int firstPadding = input.indexOf('=');
        if (firstPadding != -1 && firstPadding < input.length() - 2) {
            throw new IllegalArgumentException("Padding '=' can only appear at the end (last 1 or 2 characters)");
        }

        List<Byte> result = new ArrayList<>();

        // Process input in groups of 4 characters
        for (int i = 0; i < input.length(); i += 4) {
            // Get up to 4 characters
            int char1 = getBase64Value(input.charAt(i));
            int char2 = getBase64Value(input.charAt(i + 1));
            int char3 = input.charAt(i + 2) == '=' ? 0 : getBase64Value(input.charAt(i + 2));
            int char4 = input.charAt(i + 3) == '=' ? 0 : getBase64Value(input.charAt(i + 3));

            // Combine four 6-bit groups into a 24-bit number
            int combined = (char1 << 18) | (char2 << 12) | (char3 << 6) | char4;

            // Extract three 8-bit bytes
            result.add((byte) ((combined >> 16) & 0xFF));
            if (input.charAt(i + 2) != '=') {
                result.add((byte) ((combined >> 8) & 0xFF));
            }
            if (input.charAt(i + 3) != '=') {
                result.add((byte) (combined & 0xFF));