首页 > 其他分享 >深度解密 base64 字符串的编解码原理

深度解密 base64 字符串的编解码原理

时间:2023-06-20 18:34:17浏览次数:44  
标签:编解码 b64 base64 解密 len char data 255

什么是 base64

我们知道一个字节可以表示的范围是 0 ~ 255,并且在 ASCII 码表中会对应一个字符,比如:字符 97 对应字符 'a'、90 对应字符 'Z' 等等。而在 ASCII 码表中有很多字符都是不可见字符,那么当数据在网络上传输时,由于不同设备对字符的处理会有一些不同,那些不可见字符就有可能被错误处理,所以这是不利于数据传输的。而解决办法就是先将数据进行一个 base64 编码,将其统统变成可见字符,这样出错的概率就大大降低了。

base64 应用在很多领域当中,比如:根证书、电子邮件、图片传输等等,那么下面就来分析一下 base64 到底是如何对数据进行编码的。

这里需要提一嘴,很多人会把编码(encode)和加密(encrypt)搞混,尽管它们都是将数据变成另一种格式,但两者还是不一样的。首先编码是为了方便数据传输,不是为了保证数据的机密性,比如这里的 base64,它的编码规则是公开的,只要你的数据是 base64 编码之后的,那么任何人都可以进行解码;而加密才是为了数据不被别人知道,所采取的安全策略。

base64 原理解密

我们说由于存在不可见的字符的问题,所以需要将每一个 ASCII 码都映射成可见字符。那么同 ASCII 码表一样,base64 肯定也有一张相应的表,记录了数字和字符之间的映射关系。

+----+---+----+---+----+---+----+---+
| 0  | A | 16 | Q | 32 | g | 48 | w |
| 1  | B | 17 | R | 33 | h | 49 | x |
| 2  | C | 18 | S | 34 | i | 50 | y |
| 3  | D | 19 | T | 35 | j | 51 | z |
| 4  | E | 20 | U | 36 | k | 52 | 0 |
| 5  | F | 21 | V | 37 | i | 53 | 1 |
| 6  | G | 22 | W | 38 | m | 54 | 2 |
| 7  | H | 23 | X | 39 | n | 55 | 3 |
| 8  | I | 24 | Y | 40 | o | 56 | 4 |
| 9  | J | 25 | Z | 41 | p | 57 | 5 |
| 10 | K | 26 | a | 42 | q | 58 | 6 |
| 11 | L | 27 | b | 43 | r | 59 | 7 |
| 12 | M | 28 | c | 44 | s | 60 | 8 |
| 13 | N | 29 | d | 45 | t | 61 | 9 |
| 14 | O | 30 | e | 46 | u | 62 | + |
| 15 | P | 31 | f | 47 | v | 63 | / |
+----+---+----+---+----+---+----+---+

可以看到总共由 26 个大写英文字符、26 个小写英文字符、10 个阿拉伯数字、1 个加号、1 个斜杠,总共 64 个字符组成,所以是 base64。这些字符很明显都是我们熟知的可见的字符,任何设备对它们的处理显然都是没有歧义的。

我们以字节串 b"satori" 为例,看看它 base64 编码之后的值是多少?

import base64

s = b"satori"
print(base64.b64encode(s))  # b'c2F0b3Jp'

但是问题来了,到底要怎么映射呢?下面我们来解释一下。

第一步

将待转换的字节串每三个字节分为一组,由于每个字节有 8 位,那么总共是 24 个位。

s = b"satori"
print([c for c in s])
"""
[115, 97, 116, 111, 114, 105]
"""

以上是每个字节对应的 ASCII 码,我们转成二进制格式。

第二步

然后第一步中的 24 个位再每 6 个分为一组,因此可以分为四组。

因此总共我们得到了 8 组数据:011100、110110、000101、110100、011011、110111、001001、101001。

第三步

每组数据有 6 个位,然后在高位补两个 0,于是可以得到:00011100、00110110、00000101、00110100、00011011、00110111、00001001、00101001。

将其转成十进制,得到对应的值:

print(
    [0b00011100, 0b00110110, 0b00000101, 0b00110100,
     0b00011011, 0b00110111, 0b00001001, 0b00101001]
)  # [28, 54, 5, 52, 27, 55, 9, 41]

8 组数据对应的十进制数为 28、54、5、52、27、55、9、41。

第四步

根据每组得到的码值在 base64 编码对照表中映射出对应的字符,28 对应 c、54 对应 2、5 对应 F、52 对应 0、27 对应 b、55 对应 3、9 对应 J、41 对应 p,因此最终得到的结果就是 c2F0b3Jp,和 Python 计算的结果是一样的。

关于为什么要 3 个字节分为一组,原因是 6 和 8 的最小公倍数是 24,而 3 个字节正好是 24 个位。

整体来说还是比较简单好理解的,就是将原来的一组 3 个字节变成 4 个字节(所以 base64 编码之后的数据大小会比原来多大约三分之一)。并且此时每个字节只用了 6 个位(前两位补 0),取值范围正好是 0 ~ 63,和 base64 编码对照表匹配。

但是这里还存在一个问题,就是我们上面的字节串正好是 6 个字节,是 3 的倍数。那如果不是 3 的倍数怎么办?假设字节串只有一个字节,比如:b"A",对应的 ASCII 码为 65,二进制格式为 01000001。

即使只有 1 个字节,还是当成 3 个字节来处理,而多余的两个字节暂时先不管,然后依旧分为 4 组。第一组是 010000,前面补 0 之后得到 00010000、对应的结果为 16,根据 base64 对照表我们得到对应的字符为 Q;第二组只有 01,后面没东西了,那么此时后面全部按 0 处理,即 010000,然后前面补 0 得到 00010000,因此对应的字符也是 Q;而第三组和第四种组则是完全没有内容,这种情况直接对应 =。因此 b"A" 在 base64 编码之后得到的结果就是 QQ==,同理 b"satoriA" 在 base64 编码之后得到的结果就是 c2F0b3JpQQ==

import base64

print(base64.b64encode(b"satori"))  # b'c2F0b3Jp'
print(base64.b64encode(b"A"))  # b'QQ=='
print(base64.b64encode(b"satoriA"))  # b'c2F0b3JpQQ=='

除了一个字节之外,还有一种特殊情况,就是每 3 个字节一组,但只有两个字节,显然两者是类似的。我们还是来分析一下,以 b"satoriAV" 为例,显然我们只需要分析 AV 即可。

第一组:补 0 之后 00010000 对应十进制为 16,根据对照表得到字符 Q;第二组:补 0 之后 00010101 对应十进制为 21,根据对照表得到字符 V;第三组:补 0 之后 00011000 对应十进制为 24,根据对照表得到字符 Y;第四组全部为空,因此直接得到 =。所以 b"AV" 在 base64 编码之后对应的字符为 QVY=

import base64

print(base64.b64encode(b"satori"))  # b'c2F0b3Jp'
print(base64.b64encode(b"AV"))  # b'QVY='
print(base64.b64encode(b"satoriAV"))  # b'c2F0b3JpQVY='

所以假设原始字节串长度为 N,那么编码成 base64 之后的字节串长度 M 就等于 N * 8 // 6,当然这是在 n 是 3 的倍数的情况下,如果不是的话。

  • 如果 N % 3 == 1,即 N * 8 % 6 == 2,那么 M 要在原来的基础上再加上 3
  • 如果 N % 3 == 2,即 N * 8 % 6 == 4,那么 M 要在原来的基础上再加上 2

以上就是 base64 的原理,当然我们除了可以进行编码、也可以进行解码,不过是把过程逆过来了而已。base64 编码数据主要是为了传输和存储,正如我们最开始所说,base64 只能说是一种编码、不能算是加密。

C 语言实现 base64

绝大部分语言都内置了 base64 相关的库,可以直接对数据进行编码和解码,那么我们可不可以自己实现呢?显然是可以的,我们来试一下,由于 Python 太简单了,所以这里我们就用 C 来实现。

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

// base64 映射表
static const unsigned char base64_enc_map[64] =
{
    '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', '+', '/'
};

/* 将字符串 data 编码成 base64 格式的字符串
 * @data: 原始字符串
 * @len: 原始字符串的长度,不包括 \0
 */
unsigned char * base64_encode(const unsigned char *data, size_t len)
{   
    size_t i, n;
    int c1, c2, c3;
    unsigned char *b64_data, *p;
    // 如果长度为 0,直接返回空字符串
    if (len == 0) {
        b64_data = (unsigned char *)malloc(1);
        b64_data[0] = 0;
        return b64_data;
    }
        
    // 长度为 len 的字符串,总共有 len * 8 个位,再除以 6,便可计算出要分多少组
    n = (len << 3) / 6;
    switch ((len << 3) - n * 6) {  // 等价于 len * 8 % 6
        case 2:
            n += 3;
            break;
        case 4:
            n += 2;
            break;
        default:
            break;
    }
    // 为 base64 字符串申请空间
    b64_data = (unsigned char *)malloc(n + 1);
    memset((void *) b64_data, 0, n + 1);
    // 遍历原始字符串,一次遍历 3 个字节
    // 如果原始字符串的长度少于 3 字节,那么就无需遍历了
    // 所以中止条件是 i < len / 3 * 3
    for (i = 0, p = b64_data; i < len / 3 * 3; i += 3) {
        c1 = *data++;
        c2 = *data++;
        c3 = *data++;
        // 3 个字节,24 个位,每 6 个为一组
        // 用 c1 的前 6 个位作为 8 位整数(高位补零)
        *p++ = base64_enc_map[c1 >> 2];
        // 用 c1 的后 2 个位和 c2 的前 4 个位组合作为 8 位整数(高位补零)
        *p++ = base64_enc_map[((c1 & 0b11) << 4) + (c2 >> 4)];
        // 用 c2 的后 4 个位和 c3 的前 2 个位组合作为 8 位整数(高位补零)
        *p++ = base64_enc_map[((c2 & 0b1111) << 2) + (c3 >> 6)];
        // 用 c3 的后 6 个位作为 8 位整数(高位补零)
        *p++ = base64_enc_map[c3 & 0b111111];
    }
    // 如果 len 是 3 的倍数,那么此时 i 应该和 len 相等
    // 如果 len 不是 3 的倍数,那么 i = len - 1 或 len - 2
    if (i < len) {
        c1 = *data++;
        // 如果 i == len - 2,说明多出来两个字节,赋给 c1 和 c2
        // 否则多出来一个字节(此时 c2 == 0)
        c2 = i == len - 2 ? *data++ : 0;
        *p++ = base64_enc_map[c1 >> 2];
        *p++ = base64_enc_map[((c1 & 0b11) << 4) + (c2 >> 4)];
        // 如果多出来两个字节,那么使用 c2 的后 4 个位,否则用 '=' 填充
        if (i == len - 2) 
            *p++ = base64_enc_map[(c2 & 0b1111) << 2];
        else
            *p++ = '=';
        // 原始字符串的三个字节,编码之后会对应四个字节,所以还差一个 '='
        *p++ = '=';
    }
    return b64_data;
}          

int main(void) {
    char *s1 = "satori";
    char *s2 = "satoriA";
    char *s3 = "satoriAV";
    printf("%s\n", base64_encode((const unsigned char *)s1, strlen(s1)));
    printf("%s\n", base64_encode((const unsigned char *)s2, strlen(s2)));
    printf("%s\n", base64_encode((const unsigned char *)s3, strlen(s3)));
    /*
    c2F0b3Jp
    c2F0b3JpQQ==
    c2F0b3JpQVY=
    */
    // free
}

以上就是 base64 的编码过程,再来看看解码,直接反过来就行。

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

// 从原始字符串到 base64 字符串的映射关系为
// 0 -> 'A',1 -> 'B',2 -> 'C',······,62 -> '+',63 -> '/',使用数组再合适不过
// 现在则是反过来,变成 'A' -> 0,'B' -> 1,'C' -> 2,····,'+' -> 62,'/' -> 63
// 要维护这个映射关系,采用字典是最合适的,但 C 里面没有字典这种复杂的数据结构,所以需要另想办法
// 由于 C 里面字符就是一个整数,所以依旧可以使用数组
// 比如 '+',它就是一个整数,值为 43,由 62 映射得到
// 那么在下面这个数组中,索引为 43 的元素就是 62,剩余用不到的元素就用 255 代替
static const unsigned char base64_dec_map[128] = {
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255,  62, 255, 255, 255,  63,  52,  53,
     54,  55,  56,  57,  58,  59,  60,  61, 255, 255,
    255,  64, 255, 255, 255,   0,   1,   2,   3,   4,
      5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
     15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
     25, 255, 255, 255, 255, 255, 255,  26,  27,  28,
     29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
     39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
     49,  50,  51, 255, 255, 255, 255, 255
};

unsigned char *base64_decode(const unsigned char *b64_data, size_t len) {
    size_t i, n;
    int c1, c2, c3, c4;
    unsigned char *data, *p;

    if (len == 0) {
        data = (unsigned char *)malloc(1);
        data[0] = 0;
        return data;
    }
    // base64 字符串的长度除以 4、再乘以 3,即可得到原始字符串的长度
    n = len / 4 * 3;
    data = (unsigned char *)malloc(n + 1);
    memset((void *)data, 0, n + 1);
    // 每 4 个字节为一组,
    for (i = 0, p = data; i < len; i += 4) {
        c1 = base64_dec_map[*b64_data++];
        c2 = base64_dec_map[*b64_data++];
        c3 = *b64_data == '=' ? 0 : base64_dec_map[*b64_data++];
        c4 = *b64_data == '=' ? 0 : base64_dec_map[*b64_data++];
        *p++ = (c1 << 2) + ((c2 & 0b110000) >> 4);
        *p++ = ((c2 & 0b1111) << 4) + ((c3 & 0b111100) >> 2);
        *p++ = ((c3 & 0b11) << 6) + c4;
    }
    return data;
}

int main(void) {
    char *s1 = "c2F0b3Jp";
    char *s2 = "c2F0b3JpQQ==";
    char *s3 = "c2F0b3JpQVY=";
    printf("%s\n", base64_decode((const unsigned char *)s1, strlen(s1)));
    printf("%s\n", base64_decode((const unsigned char *)s2, strlen(s2)));
    printf("%s\n", base64_decode((const unsigned char *)s3, strlen(s3)));
    /*
    satori
    satoriA
    satoriAV
    */
}

以上我们就用 C 实现了字符串的 base64 编解码,还是不难的。

封装 Python 扩展

我们将上面实现的的功能封装成 Python 扩展,然后暴露给 Python,并测试它和内置的 base64 模块之间的性能差异。需要用到以下几个文件:

b64module.c

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

static const unsigned char base64_enc_map[64] = {
    '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', '+', '/'
};

static const unsigned char base64_dec_map[128] = {
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255,  62, 255, 255, 255,  63,  52,  53,
     54,  55,  56,  57,  58,  59,  60,  61, 255, 255,
    255,  64, 255, 255, 255,   0,   1,   2,   3,   4,
      5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
     15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
     25, 255, 255, 255, 255, 255, 255,  26,  27,  28,
     29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
     39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
     49,  50,  51, 255, 255, 255, 255, 255
};

/* 将字符串 data 编码成 base64 格式的字符串 */
unsigned char *base64_encode(const unsigned char *data, size_t len) {
    size_t i, n;
    int c1, c2, c3;
    unsigned char *b64_data, *p;
    if (len == 0) {
        b64_data = (unsigned char *)malloc(1);
        b64_data[0] = 0;
        return b64_data;
    }

    n = (len << 3) / 6;
    switch ((len << 3) - n * 6) {
        case 2:
            n += 3;
            break;
        case 4:
            n += 2;
            break;
        default:
            break;
    }
    b64_data = (unsigned char *)malloc(n + 1);
    memset((void *) b64_data, 0, n + 1);
    for (i = 0, p = b64_data; i < len / 3 * 3; i += 3) {
        c1 = *data++;
        c2 = *data++;
        c3 = *data++;
        *p++ = base64_enc_map[c1 >> 2];
        *p++ = base64_enc_map[((c1 & 0b11) << 4) + (c2 >> 4)];
        *p++ = base64_enc_map[((c2 & 0b1111) << 2) + (c3 >> 6)];
        *p++ = base64_enc_map[c3 & 0b111111];
    }
    if (i < len) {
        c1 = *data++;
        c2 = i == len - 2 ? *data++ : 0;
        *p++ = base64_enc_map[c1 >> 2];
        *p++ = base64_enc_map[((c1 & 0b11) << 4) + (c2 >> 4)];
        if (i == len - 2)
            *p++ = base64_enc_map[(c2 & 0b1111) << 2];
        else
            *p++ = '=';
        *p++ = '=';
    }
    return b64_data;
}

/* 将 base64 格式的字符串 b64_data 解码成原始字符串 */
unsigned char *base64_decode(const unsigned char *b64_data, size_t len) {
    size_t i, n;
    int c1, c2, c3, c4;
    unsigned char *data, *p;

    if (len == 0) {
        data = (unsigned char *)malloc(1);
        data[0] = 0;
        return data;
    }
    n = len / 4 * 3;
    data = (unsigned char *)malloc(n + 1);
    memset((void *)data, 0, n + 1);
    for (i = 0, p = data; i < len; i += 4) {
        c1 = base64_dec_map[*b64_data++];
        c2 = base64_dec_map[*b64_data++];
        c3 = *b64_data == '=' ? 0 : base64_dec_map[*b64_data++];
        c4 = *b64_data == '=' ? 0 : base64_dec_map[*b64_data++];
        *p++ = (c1 << 2) + ((c2 & 0b110000) >> 4);
        *p++ = ((c2 & 0b1111) << 4) + ((c3 & 0b111100) >> 2);
        *p++ = ((c3 & 0b11) << 6) + c4;
    }
    return data;
}

b64module.h

#include <stdio.h>

unsigned char *base64_encode(const unsigned char *data, size_t len);
unsigned char *base64_decode(const unsigned char *b64_data, size_t len);

my_base64.c

#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "b64module.h"

static PyObject *b64encode(PyObject *self, PyObject *data) {
    if (!PyBytes_CheckExact(data)) {
        PyErr_Format(PyExc_ValueError, 
            "data must be a bytes, not '%s'\n", Py_TYPE(data)->tp_name);
        return NULL;
    }
    char *src = PyBytes_AsString(data);
    ssize_t len = strlen(src);
    unsigned char *dst = base64_encode((unsigned char *)src, len);
    PyObject *b64_data = PyBytes_FromString((const char *)dst);
    free(dst);
    return b64_data;
}

#define is_valid_b64_character(c) \
    (((c) >= 'A' && (c) <= 'Z') || \
     ((c) >= 'a' && (c) <= 'z') || \
     ((c) >= '0' && (c) <= '9') || \
     ((c) == '+') || ((c) == '/'))

static PyObject *b64decode(PyObject *self, PyObject *b64_data) {
    if (!PyBytes_CheckExact(b64_data)) {
        PyErr_Format(PyExc_ValueError, 
            "b64_data must be a bytes, not '%s'", Py_TYPE(b64_data)->tp_name);
        return NULL;
    }
    char *src = PyBytes_AsString(b64_data);
    ssize_t len = strlen(src);
    // 检验一下 base64 字符串的合法性
    // 长度必须是 4 的整数倍
    if (len % 4 != 0) {
        PyErr_Format(PyExc_ValueError, "b64_data length must be 4n");
        return NULL;
    }
    // 字符必须是 'a' ~ 'z'、'A' ~ 'Z'、'+'、'/'、'=',并且 '=' 要在字符串的最后
    int flag = 1;
    int i;
    for (i = 0; i < len - 2; i++) {
        if (!is_valid_b64_character(src[i])) {
            flag = 0;
            break;
        }
    }
    // 单独判断最后两个字符,如果倒数第二个字符为 '=',那么最后一个必须也是 '='
    if (src[i] == '=') {
        if (src[i + 1] != '=')
            flag = 0;
    } else if (!is_valid_b64_character(src[i])) {
        flag = 0;
    } else {
        // 到这里说明倒数第二个字符不为 '='
        if (!(src[i + 1] == '=' || is_valid_b64_character(src[i + 1]))) {
            flag = 0;
        }
    }
    if (!flag) {
        PyErr_Format(PyExc_ValueError, "invalid b64_data");
        return NULL;
    }
    unsigned char *dst = base64_decode((unsigned char *)src, len);
    PyObject *data = PyBytes_FromString((const char *)dst);
    free(dst);
    return data;
}

static PyMethodDef methods[] = {
    {"b64encode", (PyCFunction) b64encode, METH_O, NULL},
    {"b64decode", (PyCFunction) b64decode, METH_O, NULL},
    {NULL, NULL, 0, NULL}
};

static PyModuleDef module = {
    PyModuleDef_HEAD_INIT,
    "my_base64",
    "我们自己实现的 base64",
    -1,
    methods,
    NULL, NULL, NULL, NULL
};

PyMODINIT_FUNC PyInit_my_base64(void) {
 return PyModule_Create(&module);
}

以上我们就封装了一个解析 base64 字符串的模块,将其编译成扩展,然后来测试一下:

import base64
import my_base64

data = "这是一段很长的字符串,到底有多长我也不知道,总之就是非常长".encode("utf-8")
print(
    base64.b64encode(data) == my_base64.b64encode(data)
)  # True

b64_data = base64.b64encode(data)
print(my_base64.b64decode(b64_data) == data)  # True

结果没有问题,那么速度呢?我们实现的和解释器自带的,哪个速度更快呢?

在解码方面势均力敌,但编码是我们赢了。

标签:编解码,b64,base64,解密,len,char,data,255
From: https://www.cnblogs.com/traditional/p/17494401.html

相关文章

  • js加密与java解密的RSA(公钥/私钥)算法
    前言:公司用的加密算法是对称密钥加密算法,服务器上的公钥与客户端的私钥都是相同的,如果不小心泄露或者通过反编译软件把客户端重新编译就会泄露密钥,这样加密后的数据就不安全了。商量使用非对称密钥RSA来解决这种问题,非对称密钥分为公钥和私钥,公钥可以公开给客户端分发给所有......
  • js base64编解码
     在JavaScript中,有两个原生支持的函数被分别用来处理解码和编码Base64字符串:btoa():“btoa”应读作“binarytoASCII”,atob():“atob”应读作“ASCIItobinary” varstr='eyJjb2RlIjoyMDAsIm1lc3NhZ2UiOiJPSyJ9'//base64字符串/ASCII字符vardata=atob(st......
  • 2、【java数据安全】base64与报文摘要MD(md5、sha、mac)简单介绍及应用场景、示例
    (文章目录)本文简单的介绍了Base64、消息摘要和其使用示例,并且使用示例以三种不同实现方式及测试本文介绍三种实现方式,即JDK、apachecommons.codec和bouncycastle三种。一、maven依赖<dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <......
  • Android基于KeyStore对数据进行加解密
    问题背景在我们App开发过程中,可能会涉及到一些敏感和安全数据需要加密的情况,比如登录token的存储。我们往往会使用一些加密算法将这些敏感数据加密之后再保存起来,需要取出来的时候再进行解密。此时就会有一个问题:用于加解密的Key该如何存储?为了保证安全性,Android提供了KeyStore......
  • Base64加密算法以及在IDA中的识别
    Base64加密算法以及在IDA中的识别一、何为Base64算法?Base64是一种基于64个可打印字符来表达二进制数据的表示方法。由于2的6次方等于64,所以每6个比特为一个单元。对于某个可打印字符。为什么这样说呢?我们首先了解一下Base64是如何设计的。3个字节有24个比特,在Base64中6个比特一......
  • 解密加密
    /*#include<iostream>usingnamespacestd;intmain(intargc,char**argv){stringa;cin>>a;for(inti=0;i<a.size();i++){charb=a[i];intc=b;cout<<"第"<<i<<"位:"&......
  • 读取ftp以base64返回到前端
    需求:库中存放文件服务器的文件绝对路径文件(d:\abc\111\abc.pdf),搭建的ftp会指向d:\abc,故ftp:/192.1.1.12:21/111/abc.pdf能取到文件。请用C#代码并base64格式返回到前端。usingSystem;usingSystem.Collections.Generic;usingSystem.Data;usingSystem.Linq;usingSystem......
  • 【图像加密】基于双随机实现图像加密解密附matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 解密
    #include<bits/stdc++.h>usingnamespacestd;intmain(intargc,char**argv){stringa="11010512010597110103989711010311510411710897111989711011611111712211111710910110511910110510997111989711110997";while(a.size()>1){......
  • 解密 加密
    /*#include<iostream>usingnamespacestd;intmain(intargc,char**argv){stringa;cin>>a;for(inti=0;i<a.size();i++){charb=a[i];intc=b;cout<<"第"<<i<<"位:"&......