安卓实现魔改版 Base64 算法

版权归作者所有,如有转发,请注明文章出处:cyrus-studio.github.io/blog/

Java 实现标准 Base64 编码和解码

Base64 编码:

vbscript 复制代码
val encoded = Base64.encodeToString(str.toByteArray(), Base64.DEFAULT)

Base64 解码:

ini 复制代码
val decoded = Base64.decode(str, Base64.DEFAULT)
val decodedString = String(decoded)

C++ 实现标准 Base64 编d码和解码

创建 base64.cpp 实现 Base64 编码和解码

scss 复制代码
#include <jni.h>
#include <string>
#include <android/log.h>

static const std::string base64_chars =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz"
        "0123456789+/";

// 检查字符是否是 Base64 字符
static inline bool is_base64(unsigned char c) {
    return (isalnum(c) || (c == '+') || (c == '/'));
}

// Base64 编码函数
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
    std::string ret;
    int i = 0;
    int j = 0;
    unsigned char char_array_3[3];
    unsigned char char_array_4[4];

    while (in_len--) {
        char_array_3[i++] = *(bytes_to_encode++);
        if (i == 3) {
            char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
            char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
            char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
            char_array_4[3] = char_array_3[2] & 0x3f;

            for (i = 0; i < 4; i++) {
                ret += base64_chars[char_array_4[i]];
            }
            i = 0;
        }
    }

    if (i) {
        for (int j = i; j < 3; j++) {
            char_array_3[j] = '\0';
        }

        char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
        char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
        char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
        char_array_4[3] = char_array_3[2] & 0x3f;

        for (int j = 0; j < i + 1; j++) {
            ret += base64_chars[char_array_4[j]];
        }

        while ((i++ < 3)) {
            ret += '=';
        }
    }

    return ret;
}

// Base64 解码函数
std::string base64_decode(std::string const& encoded_string) {
    int in_len = encoded_string.size();
    int i = 0;
    int j = 0;
    int in_ = 0;
    unsigned char char_array_4[4], char_array_3[3];
    std::string ret;

    while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
        char_array_4[i++] = encoded_string[in_];
        in_++;
        if (i == 4) {
            for (i = 0; i < 4; i++) {
                char_array_4[i] = base64_chars.find(char_array_4[i]);
            }

            char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
            char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
            char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

            for (i = 0; i < 3; i++) {
                ret += char_array_3[i];
            }
            i = 0;
        }
    }

    if (i) {
        for (int j = i; j < 4; j++) {
            char_array_4[j] = 0;
        }

        for (int j = 0; j < 4; j++) {
            char_array_4[j] = base64_chars.find(char_array_4[j]);
        }

        char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
        char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
        char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

        for (int j = 0; j < i - 1; j++) {
            ret += char_array_3[j];
        }
    }

    return ret;
}

参考:Base64 decode snippet in C++

Kotlin 层中声明 native 编码和解码函数

kotlin 复制代码
// 标准 Base64(C++)
external fun nativeBase64Encode(data: ByteArray): String
external fun nativeBase64Decode(input: String): ByteArray

实现 native 函数并调用 C++ 中 Base64 编码和解码函数

scss 复制代码
extern "C" JNIEXPORT jstring JNICALL
Java_com_cyrus_example_base64_Base64Activity_nativeBase64Encode(JNIEnv* env, jobject, jbyteArray input) {
    jsize input_len = env->GetArrayLength(input);
    unsigned char* bytes_to_encode = reinterpret_cast<unsigned char*>(env->GetByteArrayElements(input, nullptr));

    std::string encoded = base64_encode(bytes_to_encode, input_len);

    env->ReleaseByteArrayElements(input, reinterpret_cast<jbyte*>(bytes_to_encode), 0);
    return env->NewStringUTF(encoded.c_str());
}

extern "C" JNIEXPORT jbyteArray JNICALL
Java_com_cyrus_example_base64_Base64Activity_nativeBase64Decode(JNIEnv* env, jobject, jstring input) {
    const char* encoded_chars = env->GetStringUTFChars(input, nullptr);
    std::string encoded_string(encoded_chars);

    std::string decoded_string = base64_decode(encoded_string);

    env->ReleaseStringUTFChars(input, encoded_chars);

    jbyteArray decoded_byte_array = env->NewByteArray(decoded_string.size());
    env->SetByteArrayRegion(decoded_byte_array, 0, decoded_string.size(), reinterpret_cast<const jbyte*>(decoded_string.c_str()));

    return decoded_byte_array;
}

Kotlin 中调用编码函数

ini 复制代码
val encoded = nativeBase64Encode(selected.toByteArray())

Kotlin 中调用解码函数

ini 复制代码
val decodedString = String(nativeBase64Decode(selected))

自定义码表

Base64 的标准编码表是:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

自定义 Base64 码表就是 替换这个字符映射,比如:

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_

这里我把大小写字母顺序调转,还有用 -_ 代替了 +/。

Kotlin 端用 external 关键字声明对应的 native 方法。

kotlin 复制代码
// 自定义 Base64 编码和解码
external fun customBase64Encode(data: ByteArray): String
external fun customBase64Decode(encoded: String): ByteArray

C++ 实现 customBase64Encode 和 customBase64Decode(使用自定义 Base64 码表)。

c 复制代码
#include <jni.h>
#include <string>
#include <vector>
#include <android/log.h>

#define LOG_TAG "Base64Custom"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)

// 自定义 Base64 码表
static const std::string CUSTOM_BASE64_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";

// **自定义 Base64 编码**
extern "C"
JNIEXPORT jstring JNICALL
Java_com_cyrus_example_base64_Base64Activity_customBase64Encode(JNIEnv *env, jobject thiz, jbyteArray data) {
    jsize len = env->GetArrayLength(data);
    std::vector<unsigned char> input(len);
    env->GetByteArrayRegion(data, 0, len, reinterpret_cast<jbyte *>(input.data()));

    std::string encoded;
    int val = 0, valb = -6;
    for (unsigned char c : input) {
        val = (val << 8) + c;
        valb += 8;
        while (valb >= 0) {
            encoded.push_back(CUSTOM_BASE64_ALPHABET[(val >> valb) & 0x3F]);
            valb -= 6;
        }
    }
    if (valb > -6) {
        encoded.push_back(CUSTOM_BASE64_ALPHABET[((val << 8) >> (valb + 8)) & 0x3F]);
    }
    return env->NewStringUTF(encoded.c_str());
}

// **自定义 Base64 解码**
extern "C"
JNIEXPORT jbyteArray JNICALL
Java_com_cyrus_example_base64_Base64Activity_customBase64Decode(JNIEnv *env, jobject thiz, jstring encodedStr) {
    const char *encoded = env->GetStringUTFChars(encodedStr, nullptr);
    if (encoded == nullptr) return nullptr; // 内存分配失败

    std::string input(encoded);
    env->ReleaseStringUTFChars(encodedStr, encoded);

    std::vector<unsigned char> output;
    std::vector<int> T(256, -1);
    for (int i = 0; i < CUSTOM_BASE64_ALPHABET.size(); i++) {
        T[CUSTOM_BASE64_ALPHABET[i]] = i;
    }

    int val = 0, valb = -8;
    for (unsigned char c : input) {
        if (T[c] == -1) break;
        val = (val << 6) + T[c];
        valb += 6;
        if (valb >= 0) {
            output.push_back((val >> valb) & 0xFF);
            valb -= 8;
        }
    }

    jbyteArray result = env->NewByteArray(output.size());
    env->SetByteArrayRegion(result, 0, output.size(), reinterpret_cast<jbyte *>(output.data()));
    return result;
}

Kotlin 中调用编码函数

ini 复制代码
val encoded = customBase64Encode(selected.toByteArray())

Kotlin 中调用解码函数

ini 复制代码
val decodedString = String(customBase64Decode(selected))

动态码表

基于输入字符串长度的动态 Base64 码表,让 Base64 码表动态变化,方法是:

  1. 根据输入字符串的长度计算一个 XOR(异或)值。

  2. 使用 XOR 值对标准 Base64 码表进行偏移,生成新的 Base64 码表。

  3. 在编码和解码时使用这个动态码表。

计算 xor_key = length % 64,用于 异或 码表索引

  • xor_key 控制字符映射偏移。

  • i ^ xor_key 让字符位置变化。

c 复制代码
#include <jni.h>
#include <string>
#include <vector>
#include <android/log.h>

#define TAG "DynamicBase64"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)

// 标准 Base64 码表
static const std::string BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

// 根据字符串长度生成 Base64 动态码表
std::string generateDynamicBase64Alphabet(size_t length) {
    std::string dynamicBase64(64, ' ');
    int xor_key = length % 64;

    for (int i = 0; i < 64; i++) {
        int new_index = i ^ xor_key;  // 计算新的索引
        dynamicBase64[new_index] = BASE64_ALPHABET[i];  // 重新排列字符
    }

    return dynamicBase64;
}

动态 Base64 编码

  • 码表基于 输入长度变化,用 异或(XOR)运算 生成新字符映射。

  • 使 Base64 在不同长度下编码不同的字符串。

ini 复制代码
// 动态 Base64 编码
std::string dynamicBase64Encode(const uint8_t* data, size_t length) {
    std::string base64Alphabet = generateDynamicBase64Alphabet(length);
    std::string encoded;
    int val = 0, valb = -6;

    for (size_t i = 0; i < length; i++) {
        val = (val << 8) + data[i];
        valb += 8;
        while (valb >= 0) {
            encoded.push_back(base64Alphabet[(val >> valb) & 0x3F]);
            valb -= 6;
        }
    }
    if (valb > -6) {
        encoded.push_back(base64Alphabet[((val << 8) >> (valb + 8)) & 0x3F]);
    }
    return encoded;
}

动态 Base64 解码

  • 用 相同的 XOR 码表恢复原数据。

  • 需 传入原始字符串长度 以正确解码。

c 复制代码
// 动态 Base64 解码
std::vector<uint8_t> dynamicBase64Decode(const std::string& input, size_t originalLength) {
    std::string base64Alphabet = generateDynamicBase64Alphabet(originalLength);
    std::vector<int> T(256, -1);

    for (int i = 0; i < 64; i++) {
        T[base64Alphabet[i]] = i;  // 生成解码表
    }

    std::vector<uint8_t> decoded;
    int val = 0, valb = -8;
    for (unsigned char c : input) {
        if (T[c] == -1) break;
        val = (val << 6) + T[c];
        valb += 6;
        if (valb >= 0) {
            decoded.push_back((val >> valb) & 0xFF);
            valb -= 8;
        }
    }
    return decoded;
}

声明 native 编码和解码函数

kotlin 复制代码
// 动态 Base64 编码和解码
external fun dynamicBase64Encode(input: ByteArray): String
external fun dynamicBase64Decode(input: String, originalLength: Int): ByteArray

C++ 中实现 native 编码和解码函数

scss 复制代码
// JNI 动态 Base64 编码
extern "C" JNIEXPORT jstring JNICALL
Java_com_cyrus_example_base64_Base64Activity_dynamicBase64Encode(JNIEnv* env, jobject, jbyteArray input) {
    jsize length = env->GetArrayLength(input);
    jbyte* data = env->GetByteArrayElements(input, nullptr);

    std::string encoded = dynamicBase64Encode(reinterpret_cast<uint8_t*>(data), length);

    env->ReleaseByteArrayElements(input, data, JNI_ABORT);
    return env->NewStringUTF(encoded.c_str());
}

// JNI 动态 Base64 解码
extern "C" JNIEXPORT jbyteArray JNICALL
Java_com_cyrus_example_base64_Base64Activity_dynamicBase64Decode(JNIEnv* env, jobject, jstring input, jint originalLength) {
    const char* encodedStr = env->GetStringUTFChars(input, nullptr);
    std::vector<uint8_t> decoded = dynamicBase64Decode(std::string(encodedStr), originalLength);
    env->ReleaseStringUTFChars(input, encodedStr);

    jbyteArray output = env->NewByteArray(decoded.size());
    env->SetByteArrayRegion(output, 0, decoded.size(), reinterpret_cast<jbyte*>(decoded.data()));
    return output;
}

Kotlin 中调用 native 方法编码

ini 复制代码
val data = str.toByteArray()
stringLength = data.size
val encoded = dynamicBase64Encode(data)

Kotlin 中调用 native 方法解码

ini 复制代码
val decodedBytes = dynamicBase64Decode(selected, stringLength)
val decodedString = String(decodedBytes)

完整源码

完整源码地址:github.com/CYRUS-STUDI...

相关推荐
2401_827364561 分钟前
迷宫【BFS+结构体\pair】
算法·宽度优先
Bruce Jue2 小时前
算法刷题--贪心算法
算法·贪心算法
jiet_h2 小时前
Android Compose: `remember` 与 `ViewModel` 保存数据的优缺点对比
android
haoqi好奇3 小时前
uniapp+node+mysql接入deepseek实现流式输出
android·mysql·uni-app
慕容魏3 小时前
入门到入土,Java学习 day16(算法1)
java·学习·算法
认真的小羽❅3 小时前
动态规划详解(二):从暴力递归到动态规划的完整优化之路
java·算法·动态规划
alexhilton4 小时前
高效地在Jetpack Compose中设计UI组件
android·kotlin·android jetpack
恋猫de小郭4 小时前
Flutter 小技巧之通过 MediaQuery 优化 App 性能
android·前端·flutter
Android采码蜂4 小时前
SurfaceFlinger10-Transaction在sf进程中的提交过程
android
LiDAR点云4 小时前
Matlab中快速查找元素索引号
数据结构·算法·matlab