接口开发#3:Base64解码及使用OpenSSL库进行RSA分组解密

四、对解压结果进行Base64解码

解码函数:[ref]

// Base64解码
std::string Base64decode(const char* Data, int DataByte, int& OutByte)
{
    //解码表
    const char DecodeTable[] =
    {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        62, // '+'
        0, 0, 0,
        63, // '/'
        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'
        0, 0, 0, 0, 0, 0, 0,
        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, // 'A'-'Z'
        0, 0, 0, 0, 0, 0,
        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, // 'a'-'z'
    };
    std::string strDecode;
    int nValue;
    int i = 0;
    while (i < DataByte)
    {
        if (*Data != '\r' && *Data != '\n')
        {
            nValue = DecodeTable[*Data++] << 18;
            nValue += DecodeTable[*Data++] << 12;
            strDecode += (nValue & 0x00FF0000) >> 16;
            OutByte++;
            if (*Data != '=')
            {
                nValue += DecodeTable[*Data++] << 6;
                strDecode += (nValue & 0x0000FF00) >> 8;
                OutByte++;
                if (*Data != '=')
                {
                    nValue += DecodeTable[*Data++];
                    strDecode += nValue & 0x000000FF;
                    OutByte++;
                }
            }
            i += 4;
        }
        else
        {
            Data++;
            i++;
        }
    }
    return strDecode;
}

Base64原理:简单来说就是把原本的数据每三个字符(3*8bit)按6bit一组拆分为4组(4*6bit),拆分后每组高位补两个零(4*8)对应64个字符,这64个字符就是"a-z""A-Z""0-9"以及"+""/"和结尾用于补位的"="。

五、使用OpenSSL库进行RSA解密

解密函数:

// RSA解密
bool RSA_decrypt(const std::string &in, std::string &out, const std::string &privatekey, int padding)
{
    int lenRSA = 0, lenOut = 0;
    std::string tmpfrom;
    char tmpto[100];
    RSA *rsa = RSA_new();
    BIO *keyBIO = NULL;
    // 从内存读取私钥
    char *chPKey = const_cast<char *>(privatekey.c_str());
    if ((keyBIO = BIO_new_mem_buf(chPKey, -1)) == NULL)
    {
        BIO_free(keyBIO);
        return false;
    }
    if ((rsa = PEM_read_bio_RSAPrivateKey(keyBIO, &rsa, NULL, NULL)) == NULL)
    {
        BIO_free(keyBIO);
        return false;
    }
    BIO_free(keyBIO);
    // 按私钥长度分组解密
    lenRSA = RSA_size(rsa);
    for (int index = 0; index < in.length(); index += (lenRSA))
    {
        tmpfrom = in.substr(index, lenRSA);
        if ((lenOut = RSA_private_decrypt((lenRSA), (const unsigned char*)tmpfrom.c_str(), (unsigned char*)tmpto, rsa, padding)) < 0)
        {
            return false;
        }
        out.append(tmpto, 100);
        memset(tmpto, 0, sizeof(tmpto));
    }
    RSA_free(rsa);
    return true;
}

padding使用PKCS#1,对密码学没有了解,一开始不知道分组解密,查阅了PKCS#1的规范意识到密文长度远远超过了私钥长度怪不得无法解密,后来又不晓得分组长度是怎么定的,浪费了不少时间,实际情况是需要对密文按照私钥长度进行分组,然后才能分别对每组密文正确解密,最后拼接成完整的明文数据。


需要提高的地方:
0.内存管理要慎之又慎;
1.注意sizeof的参数是指针时返回的是指针类型所占空间,数组和指针还是有所不同的!——sizeof是运算符,其值在编译时即计算好了,参数可以是数组、指针、类型、对象、函数等。它的功能是:获得保证能容纳实现所建立的最大对象的字节大小。由于在编译时计算,因此sizeof不能用来返回动态分配的内存空间的大小;[sizeof()、strlen()、string中length()和size()]
2.还有就是在使用指针作为参数传递时,尽量加上长度参数限制以防内存越界;
3.对于复杂类型需要慎用memset;[老生常谈,正确使用memset]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1 基础 1.1 对称算法 描述:对称加密是指加密过程和解密过程使用相同的密码。主要分:分组加密、序列加密。 原理...
    御浅永夜阅读 2,517评论 1 4
  • 首先罗列一些知识点: 1.加密算法通常分为对称性加密算法和非对称性加密算法:对于对称性加密算法,信息接收双方都需事...
    JonesCxy阅读 1,438评论 2 4
  • 车祸车车
    秋山一茶阅读 488评论 0 0
  • 8c239f1a8ca6阅读 187评论 2 1
  • 那时候每个人都不用为了一个目的或者为了一个什么一定要完成的事情去奔忙或者是锻炼自己,而是一切都是生活的一部分,自然...
    余大宝萌萌哒阅读 142评论 0 0