http://www.dtmao.cc/news_show_692109.shtml

本文不讨论RSA加密解密本身,只记录使用方法及遇到的坑,RSA原理及注意事项可在网上查找。

背景:公司的一个需求,要求对接客户的一个平台,通信方式为MQTT,数据包含Token及json内容,在通信过程中发送的MQTT信息必须带上Token,这个Token是要从客户平台获取,通过http协议,POST方法。

然后POST方法的body信息需要进行RSA加密(提供了公钥和私钥,公钥加密私钥解密),然后再Base64加密。Base64公司代码里已经有了,但RSA加密却没有,只能自己网上搜索。在使用RSA加密过程中遇到了以下几个问题:

1,用RSA加密时,如果密文长度是1024位(128字节)的话,其要加密的明文只能是117字节长度。我的POST方法数据不止117字节,无法满足我目前的需求。

2,Base64编码问题

3,公钥及私钥是客户提供的,但不是标准格式。

关于问题1、问题2:

找了很多网上的例子,实现的都是简单的几个字符的加密及解密,那些长串字符加密的直接拿过来又无法通过编译。最后找到一些拿过来修修改改,终于可以用,记录如下:

/**
** @brief 用公钥进行加密,明文长于117字节时需要进行分段处理
*/
std::string CRSAEnCrypt::rsaPublicKeyEncryptSplit(const std::string &clearText)
{
std::string result;
std::string input;
result.clear(); for(int i = 0 ; i< clearText.length() / SPLIT_LEN; i++)
{
input.clear();
input.assign(clearText.begin() + i * SPLIT_LEN, clearText.begin() + i * SPLIT_LEN + SPLIT_LEN);
result = result + rsaPublicKeyEncrypt(input);
} if(clearText.length() % SPLIT_LEN != 0)
{
int32_t tmp = clearText.length() / SPLIT_LEN * SPLIT_LEN;
input.clear();
input.assign(clearText.begin() + tmp, clearText.end());
result = result + rsaPublicKeyEncrypt(input);
} printf("before base64 len: %lu\n", result.length());
std::string encode_str = base64Encode((uint8_t*)result.c_str(), result.length());
printf("after base64 len: %lu\n", encode_str.length());
return encode_str;
}

网上有些说,分段RSA加密后即进行Base64编码,但我这里是RSA加密完成后再整体进行Base64编码,在进行RSA解码时先Base64解码。

/**
** @brief 用私钥进行解密,分段处理
*/
std::string CRSAEnCrypt::rsaPrivateKeyDecryptSplit(const std::string &Text)
{
printf("before base64Decode len: %lu\n", Text.length());
std::string clearText = base64Decode(Text);
printf("after base64Decode len: %lu\n", clearText.length()); //printf("BaseDecode len: %lu\n", clearText.length());
std::string result;
std::string input;
result.clear();
for(int i = 0 ; i< clearText.length() / 128; i++)
{
input.clear();
input.assign(clearText.begin() + i * 128, clearText.begin() + i * 128 + 128);
result = result + rsaPrivateKeyDecrypt(input);
} if(clearText.length() % 128 != 0)
{
int tem1 = clearText.length()/128 * 128;
input.clear();
input.assign(clearText.begin()+ tem1, clearText.end());
result = result + rsaPrivateKeyDecrypt(input);
} return result;
}

使用例子:


int main()
{
Json::Value postMsg;
postMsg["userName"] = "zgdxgzt";
postMsg["password"] = "xcq123456";
postMsg["tenantId"] = "5fca019cb091f5b7e44c0eec";
postMsg["client_id"] = "5cf600563f4c000053007383";
postMsg["client_secret"] = "U2FsdGVkX1+oesjvWS3Z8q7ziFCu+p4tU7OQjl+5m21l7XMbBBJtof4fAL1S8/tJNrGpqIAqtTwXOeiZJFFtHw==";
postMsg["scope"] = "read"; //固定值
postMsg["grant_type"] = "password"; //固定值 CRSAEnCrypt::getInstance()->initkey(privateKey, publicKey);
std::string sourceStr = jsonToString(postMsg);
printf("string of json: %s\n", sourceStr.c_str()); //单独测试base64加密、解密
// std::string encodeStr = base64Encode((uint8_t *)sourceStr.c_str(), sourceStr.length());
// printf("decodeStr len: %lu\n", encodeStr.length());
// std::string decodeStr = base64Decode(encodeStr);
// printf("decodeStr len: %lu, %s\n", decodeStr.length(), decodeStr.c_str()); //公钥加密
std::string rsaEncryptStr = CRSAEnCrypt::getInstance()->rsaPublicKeyEncryptSplit(sourceStr);
printf("after rsaEncryptStr len: %lu\n", rsaEncryptStr.length()); //私钥解密
std::string rsaDecryptStr = CRSAEnCrypt::getInstance()->rsaPrivateKeyDecryptSplit(rsaEncryptStr);
printf("after rsaDecryptStr: %lu, %s\n", rsaDecryptStr.length(), rsaDecryptStr.c_str()); return 0;
}

关于第3个问题,公钥和私钥有固定格式,要注意,因客户只提供两个字符串,里面并没有包含固定的头和尾字符,这样可能会导致RSA 读取密钥时出错。正确格式如下:

不同的头尾标识,调用的openssl的库函数可能不同,可自行baidu。

最后一点网上一些例子只贴出部分代码,很多时候下载后根本不能直接用,这不是要流氓吗。。。。

源码下载:

git clone git@github.com:tianyexing2008/c_cpp.git

下载后cd encrypt 目录下make 即可。因代码中用到的json,如果你电脑上已经有json库,可能可以直接编译过,如果没有,这个git里也有json源码,目录json,可cd json后进行make编译libjson.a库,再修改encrypt里的Makefile里指定的头文件目录

及json库目录即可。

RSA 加密解密使用实例的更多相关文章

  1. 微信小程序(17)-- RSA加密 解密 加签 验签

    RSA加密 解密 加签 验签 /** * 注:区分RSA私钥的类型,有pkcs1和pkcs8.pkcs8格式的私钥主要用于Java中 pkcs1格式: -----BEGIN RSA PRIVATE K ...

  2. 兼容javascript和C#的RSA加密解密算法,对web提交的数据进行加密传输

    Web应用中往往涉及到敏感的数据,由于HTTP协议以明文的形式与服务器进行交互,因此可以通过截获请求的数据包进行分析来盗取有用的信息.虽然https可以对传输的数据进行加密,但是必须要申请证书(一般都 ...

  3. iOS使用Security.framework进行RSA 加密解密签名和验证签名

    iOS 上 Security.framework为我们提供了安全方面相关的api: Security框架提供的RSA在iOS上使用的一些小结 支持的RSA keySize 大小有:512,768,10 ...

  4. openssl evp RSA 加密解密

    openssl evp RSA 加密解密 可以直接使用RSA.h 提供的接口 如下测试使用EVP提供的RSA接口 1. EVP提供的RSA 加密解密 主要接口: int EVP_PKEY_encryp ...

  5. C# 与JAVA 的RSA 加密解密交互,互通,C#使用BouncyCastle来实现私钥加密,公钥解密的方法

    因为C#的RSA加密解密只有公钥加密,私钥解密,没有私钥加密,公钥解密.在网上查了很久也没有很好的实现.BouncyCastle的文档少之又少.很多人可能会说,C#也是可以的,通过Biginteger ...

  6. Cryptopp iOS 使用 RSA加密解密和签名验证签名

    Cryptopp 是一个c++写的功能完善的密码学工具,类似于openssl 官网:https://www.cryptopp.com 以下主要演示Cryptopp 在iOS上的RSA加密解密签名与验证 ...

  7. C# Java间进行RSA加密解密交互

    原文:C# Java间进行RSA加密解密交互 这里,讲一下RSA算法加解密在C#和Java之间交互的问题,这两天纠结了很久,也看了很多其他人写的文章,颇受裨益,但没能解决我的实际问题,终于,还是被我捣 ...

  8. C# Java间进行RSA加密解密交互(二)

    原文:C# Java间进行RSA加密解密交互(二) 接着前面一篇文章C# Java间进行RSA加密解密交互,继续探讨这个问题. 在前面,虽然已经实现了C# Java间进行RSA加密解密交互,但是还是与 ...

  9. C# Java间进行RSA加密解密交互(三)

    原文:C# Java间进行RSA加密解密交互(三) 接着前面一篇C# Java间进行RSA加密解密交互(二)说吧,在上篇中为了实现 /** * RSA加密 * @param text--待加密的明文 ...

随机推荐

  1. LeetCode671. 二叉树中第二小的节点

    题目 纯暴力 1 class Solution { 2 public: 3 vector<int>ans; 4 int findSecondMinimumValue(TreeNode* r ...

  2. Upload - Labs (下)

    Pass - 11: 1.查看源代码,发现进行了一次对后缀名替换成空格,因此考虑双写绕过, 2.上传成功, 关键代码: $is_upload = false; $msg = null; if (iss ...

  3. ctfhub技能树—文件上传—双写后缀

    双写后缀绕过 用于只将文件后缀名,例如"php"字符串过滤的场合: 例如:上传时将Burpsuite截获的数据包中文件名[evil.php]改为[evil.pphphp],那么过滤 ...

  4. +load和+initialize方法调用时机

    一.+load方法什么时候调用 +load方法会在runtime加载类.分类时调用(程序运行起来会先去加载调用+load 跟你引用没有引用其头文件没有关系).每个类.分类的+load,在程序运行过程中 ...

  5. the7主题 一个强大的wordpress 主题 html5拖拽式建站系统

    演示地址 http://the7.net The7汉化主题.可视化编辑器和终极交互式模块插件完全无缝集成,可以让你完全自由的布局或者创意实现你的网站,真正的建站仿站利器. The7的750+个主题设置 ...

  6. [Poi2005]Piggy Banks小猪存钱罐

    题目描述 Byteazar有 N 个小猪存钱罐. 每个存钱罐只能用钥匙打开或者砸开. Byteazar已经把每个存钱罐的钥匙放到了某些存钱罐里. Byteazar 现在想买一台汽车于是要把所有的钱都取 ...

  7. 使用 .NETCore自带框架快速实现依赖注入

    Startup 在Startup的ConfigureServices()中配置DI的接口与其实现 public void ConfigureServices(IServiceCollection se ...

  8. JAVA SSM整合流程以及注意点

    1.搭建整合环境 整合说明:SSM整合可以使用多种方式,咱们会选择XML + 注解的方式 先搭建整合的环境 先把Spring的配置搭建完成 再使用Spring整合SpringMVC框架 最后使用Spr ...

  9. MySQL高可用HA——keepalived配置

    0. Keepalived介绍   Keepalived是基于VRRP(Virtual Router Redundancy Protocol,虚拟路由器冗余协议)协议的一款高可用软件.Keepaili ...

  10. CPU处理器架构和工作原理浅析

    CPU处理器架构和工作原理浅析 http://c.biancheng.net/view/3456.html 汇编语言是学习计算机如何工作的很好的工具,它需要我们具备计算机硬件的工作知识. 基本微机设计 ...