• [C++]实现base64加密算法和解密算法


      大家好,今天带来的是用C++程序设计语言来实现base64加密算法.在密码学的学习过程中,可能会涉及到base64加密算法.base64加密算法是一种一种基于64个可打印字符来表示二进制数据的表示方法.

      这是一种用6位二进制数来表示一个可打印字符的方法.由于2的6次方等于64,所以每6个位为一个单元,对应某个可打印字符。三个字节(每个字节8位)有24个位,对应于4个Base64字符,即3个字节需要用4个可打印字符来表示。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9,这样共有62个字符,此外两个可打印符号在不同的系统中而不同,这里使用字符'+'和'/'.

      base64的对应序列为"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".在剩余的不足24位的二进制数中,若剩余位数整除16(2个字节),则打印一个等号,若整除8(一个字节),则打印两个等号.

      

     可得,加密后的字符串长度是原来的4/3倍.

      我使用的算法是将输入的ASCII码字符串全部转换为二进制字符串,每个ASCII字符对应8位二进制数.然后每6位二进制数提取出来,按2为权展开,得到在base64中的序列下标,从而得到相应字符.这种方法肯定不是最简单,最巧妙的,但是应该是比较好理解的.

      在代码实现上,有两个关键的,就是转换成二进制的函数和加密函数.

      ASCII码转换为二进制函数

     1 string deciToBin(int deci)                                //10进制转2进制函数
     2 {
     3 
     4     string hexStr(8, ' ' );
     5     int Value = 0;
     6     int i = 0;
     7 
     8     for (; deci != 0; ++i, deci /= 2)
     9     {
    10         Value = deci % 2;
    11         hexStr.at(i) =  Value + '0';
    12     }
    13 
    14     hexStr = hexStr.substr(0, i);
    15 
    16     reverse(hexStr.begin(), hexStr.end());
    17 
    18     if (hexStr.length() < 8)
    19     {
    20         string add( 8 - hexStr.length(), '0');
    21         hexStr = add + hexStr;
    22     }
    23 
    24     return hexStr;
    25 }

      这个函数与前面写过的进制转换器中的十进制转二进制函数基本一致,只是当二进制位数不足8位时要在前面补0来补足8位,使得对应准确.

      接下来是加密函数:

     1 string base64_encryption(const string in)                //加密函数
     2 {
     3     int i = 0;                            //总的控制变量
     4     int k = 0;                          //24位(4个6位)控制变量
     5     const int n = in.length();     //二进制序列长度
     6     string subs;                        //要对应输出的子串
     7     string out;                        //输出结果字符串
     8     string value("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");       //对应字符
     9 
    10     while (n - i >= 24)            //处理完整的三个字节
    11     {
    12         for (k = 0; k < 4; ++k)
    13         {
    14             subs = in.substr( i + k * 6, 6);            //取出6位
    15 
    16             int sum = 0;
    17             int j = 0;
    18 
    19             for (auto & x : subs)
    20             {
    21                 sum += (x - '0') * pow(2, 5 - j);
    22                 ++j;
    23             }                                                                            //得到下标
    24 
    25             out +=  value.at(sum);                                          //输出对应字符
    26         }
    27 
    28         i += 24;                                                                    //前进24位
    29 
    30         if ( i % 76 == 0)
    31             cout << endl;
    32     }
    33 
    34     if ( i != n)                                                                       //处理剩下的不足24位部分
    35     {
    36         int charlen;                                              //剩下的长度
    37 
    38         if ((n - i) % 6 == 0)
    39             charlen = (n - i) / 6;
    40         else
    41             charlen = (n - i) / 6 + 1;
    42 
    43         for (k = 0; k < charlen; ++k)
    44         {
    45             subs = in.substr( i + k * 6, i + (k + 1) * 6 - 1);            //取出6位
    46 
    47             int sum = 0;
    48             int j = 0;
    49 
    50             for (auto & x : subs)
    51             {
    52                 sum += (x - '0') * pow(2, 5 - j);
    53                 ++j;
    54             }                                                                            //得到下标
    55 
    56             out +=  value.at(sum);                                            //输出对应字符
    57         }
    58 
    59         if ((n - i) % 16 == 0)
    60             out += "=";
    61 
    62         else
    63             out += "==";
    64 
    65     }
    66 
    67     return out;
    68 }

      这个函数思想也比较简单,接受前面的二进制序列作为实参,每次提取出6位,按2的权展开,在base64字符序列中对应字符连接到输出字符串中.再根据情况,添加等号.

      至于解密算法,就可以看作加密算法的逆过程.排除等号,将字符在base64中出现的位置数转换为6位二进制,在8位一个组合,按权展开,得到ASCII码,就完成了.

    解密函数:

     1 string base64_decryption(const string in)
     2 {
     3     string value("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
     4     string out0;
     5     string out1;
     6     string deciToBin_6bit(int);
     7 
     8     for( auto x = in.cbegin(); (*x) != '=' && x != in.cend(); ++x)    //排除等号
     9         out0 += deciToBin_6bit(value.find(*x));
    10 
    11     const int n = out0.length();
    12 
    13     for(int i = 0; i < n; i += 8)           //每8位提取一次
    14     {
    15         string subs = out0.substr(i, 8);    //提取8位
    16         int j = 0;
    17         int sum = 0;
    18 
    19         for(auto &x : subs)
    20         {
    21             sum += (x - '0') * pow(2, 7 - j);
    22             ++j;
    23         }                                   //按权展开,得到ASCII码
    24 
    25         out1 += static_cast<char>(sum);     //转换为相应字符
    26     }
    27 
    28     return out1;
    29 
    30 }

      十进制转换为二进制的6位版本:

     1 string deciToBin_6bit(int deci)                                //10进制转2进制函数
     2 {
     3 
     4     string hexStr(6, ' ' );
     5     int Value = 0;
     6     int i = 0;
     7 
     8     for (; deci != 0; ++i, deci /= 2)
     9     {
    10         Value = deci % 2;
    11         hexStr.at(i) =  Value + '0';
    12     }
    13 
    14     hexStr = hexStr.substr(0, i);
    15 
    16     reverse(hexStr.begin(), hexStr.end());
    17 
    18     if (hexStr.length() < 6)
    19     {
    20         string add( 6 - hexStr.length(), '0');
    21         hexStr = add + hexStr;
    22     }
    23 
    24     return hexStr;
    25 }

      也可以与8位的版本写成重载函数.

      函数实现后,主函数就可以写的比较简洁了:

     1 int main()
     2 {
     3 
     4     string input0;                                                          //存放输入的字符
     5     string input1;                                                          //存放二进制序列
     6     string deciToBin_8bit(int);                                    //十进制到二进制函数原型
     7     string base64_encryption(const string);                                //加密函数原型
     8     string base64_decryption(const string);
     9     cout << "Input:" << endl;
    10     cin >> input0;                                    //输入的ASCII码字符串
    11     cout << endl;
    12 
    13     for ( auto &x : input0)
    14         input1 += deciToBin_8bit(static_cast<int>(x));                       //得到二进制序列
    15 
    16     string out0 = base64_encryption(input1);
    17 
    18     cout << out0 << endl;
    19 
    20     cout<<endl;
    21 
    22     string out1 = base64_decryption(out0);
    23 
    24     cout << out1 << endl;
    25 
    26     return 0;
    27 }

    用到的头文件:

    1 #include <iostream>
    2 #include <cstdlib>
    3 #include <cmath>
    4 #include <algorithm>
    5 #include <cctype>

      编码运行,Ok.

      本人原创,谢谢大家!转载请注明出处,谢谢合作!

  • 相关阅读:
    [leetcode] 17. 电话号码的字母组合
    C++17 Fold Expressions
    多线程----NSOperation
    CGD---1--开辟并发新线程
    彻底解决_OBJC_CLASS_$_某文件名", referenced from:问题(转)
    ios 内存使用陷阱 和imageNamed 、imageWithContentsOfFile:(转)
    (转)unbalanced calls to begin/end appearance transitions for uiviewcontroller的解决方法
    ios开发种证书
    使用CAShapeLayer与UIBezierPath画出想要的图形
    定位子字符串的位置
  • 原文地址:https://www.cnblogs.com/Agent-YRBlogs/p/6059715.html
Copyright © 2020-2023  润新知