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. redis 主从复制(一主两从)

    一.环境基本信息 系统 centos7 版本 redis 5.0.7 只用了一台机器,ip:192.168.64.123 master端口 6379,从机 端口 6380.6381 二.redis目录 ...

  2. centos7安装docker、docker-compose、es7.3.0、kibana7.3.0

    一.安装docker 1.更新yum包 sudo yum update 2.卸载旧版本(如果安装过旧版本的话) sudo yum remove docker docker-common docker- ...

  3. pyinstaller打包shotgun有关的程序

    By 鬼猫猫 http://www.cnblogs.com/muyr/ 背景 使用pyinstaller打包跟shotgun有关的程序后,在自己电脑上运行都OK,但是编译好的exe在其他人的电脑上运行 ...

  4. html简单基础

    标签语法 标签的语法: <标签名 属性1="属性值1" 属性2="属性值2"-->内容部分</标签名> <标签名 属性1=&quo ...

  5. 理解js闭包9大使用场景

    1.返回值(最常用) //1.返回值 最常用的 function fn(){ var name="hello"; return function(){ return name; } ...

  6. Redis 核心篇:唯快不破的秘密

    天下武功,无坚不摧,唯快不破! 学习一个技术,通常只接触了零散的技术点,没有在脑海里建立一个完整的知识框架和架构体系,没有系统观.这样会很吃力,而且会出现一看好像自己会,过后就忘记,一脸懵逼. 跟着「 ...

  7. 提取当前文件夹下的所有文件名.bat(Windows批处理文件)

    @echo off dir /s/b *.* > 文件名.txt exit

  8. 🙈 如何隐藏你的热更新 bundle 文件?

    如果你喜欢我写的文章,可以把我的公众号设为星标 ,这样每次有更新就可以及时推送给你啦. 前段时间我们公司的一个大佬从一些渠道得知了一些小道消息,某国民级 APP 因为 Apple App Store ...

  9. linux系统层面调优

    linux系统层面调优和常见的面试题 - 云+社区 - 腾讯云 https://cloud.tencent.com/developer/article/1664287

  10. 本地MarkDown优雅发表

    本地MarkDown优雅发表 前言 身为一名程序员,记录笔记.发表博客首选便是MarkDown,现在网上有好多发表博客的地方:CSDN.博客园.简书,甚至一些大佬都有自己专属博客,但自己最喜欢的还是博 ...