• 自定义Base 64加密


    一.前言

        最近做软件需要一个功能,就是对文件进行加密。本来嘛,加密算法一堆一堆的,但是试了几个成熟的加密算法后发现对文件进行加密需要的时间很长,特别是上G的文件,这样客户是接受不了的。最后没办法了,好坏也要找一个吧,就选定用Base64加密。标准的base64加密很简单,而且编码表也是固定的,所以只要稍加修改,也能成为有效的加密工具,虽然有一点弱,本来嘛这种加密也是“防君子不防小人”的。

    下载地址:http://download.csdn.net/source/2915065

    二.Base64加密原理

      ①.把3个字符变成4个字符

      ②.每76个字符加一个换行符

      ③.最后的结束符也要处理

     

        这样说会不会太抽象了?不怕,我们来看一个例子:

      转换前 aaaaaabb ccccdddd eeffffff

      转换后 00aaaaaa 00bbcccc 00ddddee 00ffffff

     

      应该很清楚了吧?上面的三个字节是原文,下面的四个字节是转换后的Base64编码,其前两位均为0。

     

    转换后,我们用一个码表来得到我们想要的字符串(也就是最终的Base64编码),这个表是这样的:(摘自RFC2045)

      

    索引

    对应字符

    索引

    对应字符

    索引

    对应字符

    索引

    对应字符

    0

    A

    17

    R

    34

    i

    51

    z

    1

    B

    18

    S

    35

    j

    52

    0

    2

    C

    19

    T

    36

    k

    53

    1

    3

    D

    20

    U

    37

    l

    54

    2

    4

    E

    21

    V

    38

    m

    55

    3

    5

    F

    22

    W

    39

    n

    56

    4

    6

    G

    23

    X

    40

    o

    57

    5

    7

    H

    24

    Y

    41

    p

    58

    6

    8

    I

    25

    Z

    42

    q

    59

    7

    9

    J

    26

    a

    43

    r

    60

    8

    10

    K

    27

    b

    44

    s

    61

    9

    11

    L

    28

    c

    45

    t

    62

    +

    12

    M

    29

    d

    46

    u

    63

    /

    13

    N

    30

    e

    47

    v

       

    14

    O

    31

    f

    48

    w

       

    15

    P

    32

    g

    49

    x

       

    16

    Q

    33

    h

    50

    y

       

        让我们再来看一个实际的例子,加深印象!

        转换前 10101101 10111010 01110110

        转换后 00101011 00011011 00101001 00110110

        十进制 43 27 41 54

        对应码表中的值 r b p 2

        所以上面的24位编码,编码后的Base64值为 rbp2

      

      原文的字节不够的地方可以用全0来补足,转换时Base64编码用=号来代替。这就是为什么有些Base64编码会以一个或两个等号结束的原因,但等号最多只有两个。因为:

      余数 = 原文字节数 MOD 3

    所以余数任何情况下都只可能是0,1,2这三个数中的一个。如果余数是0的话,就表示原文字节数正好是3的倍数(最理想的情况啦)。如果是1的话,为了让Base64编码是3的倍数,就要补2个等号;同理,如果是2的话,就要补1个等号。

    三.自定义编码

        我们把上面标准的编码表定义成我们自己的编码就行了。如果要加密后的字符是可以看见的,最好选ASCII 码在0-128之间的。即字符在"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"之间。上面A的ASCII码是65,B是66,最大的是z=122,都在128之间。

        我们重新定义上面字符表的顺序,也就是自己排排上面字符串的顺序,目的是打乱上面那个表的映射。这样只有我们自己知道映射表,也就只有我们自己知道钥匙了,所以别人用标准的Base64编码表也就不能顺利解码了。

        再强调一遍,这种加密很弱,是效率优先的加密算法。

    四.自定义编码实现

     

        网上标准的Base64加密算法很多,我随便找一了个,部分代码如下:

    //加密表  
    static char BASE64_ALPHABET [64] =  
    {  
      
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',        //   0 -   9  
      
        'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',        //  10 -  19  
      
        'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',        //  20 -  29   
      
        'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',        //  30 -  39   
      
        'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',        //  40 -  49   
      
        'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',        //  50 -  59   
      
        '8', '9', '+', '/'                                       //  60 -  63   
      
    };  
      
      
    //解密表  
    static char BASE64_DEALPHABET [128] =   
    {  
      
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //   0 -   9   
      
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //  10 -  19   
      
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //  20 -  29   
      
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  //  30 -  39   
      
        0,  0,  0, 62,  0,  0,  0, 63, 52, 53,  //  40 -  49   
      
        54, 55, 56, 57, 58, 59, 60, 61,  0,  0, //  50 -  59   
      
        0, 0,  0,  0,  0,  0,  1,  2,  3,  4,   //  60 -  69   
      
        5,  6,  7,  8,  9, 10, 11, 12, 13, 14,  //  70 -  79   
      
        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, //  80 -  89   
      
        25,  0,  0,  0,  0,  0,  0, 26, 27, 28, //  90 -  99   
      
        29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // 100 - 109   
      
        39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // 110 - 119   
      
        49, 50, 51,  0,  0,  0,  0,  0          // 120 - 127   
      
    };  

    首先有一点可以肯定,那就是这两个表是有一定的关系。我们唯一要做的就是找出这两个表之间的对应关系。

    是什么关系呢?我们知道A的ASCII码是65,我们观察解密表中第65位是0,再看B的ASCII码是66,解密表是的66位是1。是不是有点明白了?!!

    结论就是,加密表中的ASCII码的值对应解密表的位,加密表的位对应解密表的值。

     

    用代码表示就是这样的:

    for (i = 0; i < 64; ++i)  
    {  
        int code = BASE64_ALPHABET[i];  
      
        BASE64_DEALPHABET[code] = i;  
    }  

    五.问题

    1.如果你想加密表再复杂点,最好来点什么乱码或不能打印的字符,这样解密表也要跟着变。这里我想说的是解密数组大小范围你自己要估计,要尽量使有效的数据多,不要浪费空间。

    2. 这种加密比较弱,对方穷举就行破解,也用不了多少时间。他的目的是“防君子不防小人”和提高效率而已。

     六. 附录

    下面是我自己写的Base64 dll使用的一些说明:

    /*******************************************  
    功能: 重置加密表 
    描述: 默认是ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ 
    如果你想自己定义加密表,直接调用此接口即可, 
    如:SetNew_ALPHABET("3456789+/CDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012AB"); 
    ********************************************/  
    bool            SetNew_ALPHABET(CString strTable);  
      
    /*******************************************  
    功能: 对字符串进行加密解密 
    ********************************************/  
    void            EncodeBuffer (char* p_pInputBuffer, unsigned int p_InputBufferLength, char*p_pOutputBufferString);   
    unsigned int    DecodeBuffer (char* p_pInputBufferString, char* p_pOutputBuffer);   
      
    /*******************************************  
    功能: 对单个文件进行加密解密 
    ********************************************/  
    unsigned int    EncodeFile (CString SourceFileName, CString EncodedFileName);  
    unsigned int    DecodeFile (CString SourceFileName, CString DecodedFileName);  
      
    /*******************************************  
    功能: 对目录下所有文件进行加密解密 
    ********************************************/  
    unsigned int    EncodeDir (CString SourceDirName, CString EncodedDirName);  
    unsigned int    DecodeDir (CString SourceDirName, CString DecodedDirName);  

    怎么样,简单吧!!有了这两张表,就相当于有了钥匙!想怎么加密就随你了。

  • 相关阅读:
    Linux内核中的双向链表struct list_head
    Linux文件的基本操作函数
    Ubuntu下载源码并编译
    Ubuntu搭建交叉编译开发环境
    终端下更改printk打印级别
    进程内存分配
    程序的内存分配
    C语言数据类型char
    RSA算法原理(简单易懂)
    常见复杂指针声明的解析(很详细)
  • 原文地址:https://www.cnblogs.com/ye-ming/p/7942713.html
Copyright © 2020-2023  润新知