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. iptables原理及防火墙规则语法基础

     Iptables 防火墙 学习总结: 三张表介绍: filter负责过滤数据包,包括的规则链有,input(进),output(出)和forward(转发); nat则涉及到网络地址转换,包括的规则 ...

  2. Trino总结

    文章目录 1.Trino与Spark SQL的区别分析 2.Trino与Spark SQL解析过程对比 3.Trino基本概念 4.Trino架构 5.Trino SQL执行流程 6.Trino Ta ...

  3. 用动图讲解分布式 Raft

    一.Raft 概述 Raft 算法是分布式系统开发首选的共识算法.比如现在流行 Etcd.Consul. 如果掌握了这个算法,就可以较容易地处理绝大部分场景的容错和一致性需求.比如分布式配置系统.分布 ...

  4. WIFI 国家码和信道划分

    前言 网上百度了很多资料,都没有找到国家码对应支持哪些信道的资料,无奈只能qiang到谷歌,分享给大家完整的WIFI 国家码和信道划分. 安卓WIFI国家码的影响 android中设置wifi国家码的 ...

  5. 内存空间有限情况下的词频统计 Trie树 前缀树

    数据结构与算法专题--第十二题 Trie树 https://mp.weixin.qq.com/s/nndr2AcECuUatXrxd3MgCg

  6. apache httpclient 4 范例

    下面是一个通过apache httpclient 4 实现http/https的普通访问和BasicAuth认证访问的例子.依赖的第三方库为: 下面是具体实现: package test; impor ...

  7. 你应该了解的25个JS技巧

    目录 1. 类型检查小工具 2. 检查是否为空 3. 获取列表最后一项 4. 带有范围的随机数生成器 5. 随机 ID 生成器 6. 创建一个范围内的数字 7. 格式化 JSON 字符串,string ...

  8. (五)SpringBoot面试题

    SpringBoot面试题 1.Spring Boot 的自动配置是如何实现的? 2.shiro和oauth还有cas他们之间的关系是什么?问下您公司权限是如何设计,还有就是这几个概念的区别. 2.1 ...

  9. Django(命名空间)

    命名空间 命名空间(英语:Namespace)是表示标识符的可见范围.一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的.这样,在一个新的命名空间中可定义任何标识符,它们不会与任何 ...

  10. CentOS 安装TFTP

    1.当然是使用yum安装最直接,一共会安装3个东东tftp.i386tftp-server.i386xinetd.i386[root@localhost CentOS]# yum -y install ...