首页
社区
课程
招聘
[已解决] [悬赏]一个RSA的c++和Java版本不能互通,头发都白了 100.00雪花
发表于: 2017-8-31 14:31 5556

[已解决] [悬赏]一个RSA的c++和Java版本不能互通,头发都白了 100.00雪花

2017-8-31 14:31
5556

这是客户端代码,公钥加密,私钥解密。公钥由服务器端提供,加密后数据用Base64编码发送出去。用Java代码是没有问题的,用C++版本对方就解密失败了。
C++平台使用的是OPenSSL库。都使用PKCS1填充模式。
找了几天没找出问题,什么大端,填充都看了,貌似都不是这些问题,确实找不出原因了

Java平台的代码如下(只贴核心代码,或者称为伪代码)

      //这是公钥
      byte[] arrayOfBytePublic = Base64.decode("
      MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw+D4pTERUemPtGIsteri\r
      eWoTbRTNHgZ0DN9Z4qfrS03eWP339/JBkGyKwlBykCzYDt8L0YMW/1Xg1appYGvf\r
      o4mnVvxzIbc1tuanH1Z+wnXbrHqgW5ndlMjZ328mDyDIRHPmzA8FMYSvPGJtnrv4\r
      H9Tc+CeKrmiWskbzxBg4T/MUxYsk/+WWg6y5dUU61rwr19HyBZKq93xH8IOctgeR\r
      xsf6oItQJ1y1Nd55XVEul2Lh5KtTZzZMWAwreIq/EhZJH0XdbOeHhy78/fMmQtkK\r
      pJqLpRMTas1ZBWmVnqHxgBQcvheOu6cNGJYbadisJDk7Yo6MW3M7kRbybeU7C9yf\r
      7QIDAQAB", 0);

      X509EncodedKeySpec localX509EncodedKeySpec = new X509EncodedKeySpec(arrayOfBytePublic);
      PublicKey PublicKey = KeyFactory.getInstance("RSA").generatePublic(localX509EncodedKeySpec);
      Cipher localCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
      localCipher.init(1, PublicKey);
      Object localObject = arraymingwen.length;//明文
      ByteArrayOutputStream localByteArrayOutputStream = new ByteArrayOutputStream();
      //下面的是分段加密,2048bit的。最大长度是256
      int m = 0;
      if (localObject - n > 0)
      {
        if (localObject - n > (256-11));
        int i3;
        for (localObject1 = localCipher.doFinal(arrayOfByte1, n, (256-11)); ; localObject1 = localCipher.doFinal(arrayOfByte1, localObject1, i3))
        {
          int n = localObject1.length;
          localByteArrayOutputStream.write(localObject1, 0, n);
          int i1 = m + 1;
          Object localObject3 = i1 * (256-11);
          int i2 = i1;
          localObject1 = localObject3;
          m = i2;
          break;
          i3 = localObject - localObject1;
        }
      }
       localObject1 = localByteArrayOutputStream.toByteArray();
      localByteArrayOutputStream.close();
     //返回Base64的字符串
      return Base64.encodeToString(localObject1, 2);

windwos7平台的c++版本,Intel处理器,加密后用Base64编码,代码如下

int RsaEncrypt(CString str,char* encrypted)
{
CString key="-----BEGIN PUBLIC KEY-----\n" \
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw+D4pTERUemPtGIsteri\n" \
"eWoTbRTNHgZ0DN9Z4qfrS03eWP339/JBkGyKwlBykCzYDt8L0YMW/1Xg1appYGvf\n" \
"o4mnVvxzIbc1tuanH1Z+wnXbrHqgW5ndlMjZ328mDyDIRHPmzA8FMYSvPGJtnrv4\n" \
"H9Tc+CeKrmiWskbzxBg4T/MUxYsk/+WWg6y5dUU61rwr19HyBZKq93xH8IOctgeR\n" \
"xsf6oItQJ1y1Nd55XVEul2Lh5KtTZzZMWAwreIq/EhZJH0XdbOeHhy78/fMmQtkK\n" \
"pJqLpRMTas1ZBWmVnqHxgBQcvheOu6cNGJYbadisJDk7Yo6MW3M7kRbybeU7C9yf\n" \
"7QIDAQAB\n" \
"-----END PUBLIC KEY-----\n"; 


int padding = RSA_PKCS1_PADDING;
RSA * rsa = createRSA((unsigned char *)key.GetBuffer(0), 1);  

//分段加密
int inputLen=str.GetLength();
char* pSource=str.GetBuffer(0);
str.ReleaseBuffer();

int offSet = 0;
int i = 0; 
int result=0;
     
while (inputLen - offSet > 0)
{
if (inputLen - offSet > (256-11))
{
int retLen = RSA_public_encrypt(245, (const unsigned char*)(pSource+offSet),(unsigned char*) encrypted, rsa, padding);
encrypted=encrypted+retLen;
result+=retLen;
}
else
{
int retLen = RSA_public_encrypt(inputLen - offSet, (const unsigned char*)(pSource+offSet),(unsigned char*) encrypted, rsa, padding);
encrypted=encrypted+retLen;
result+=retLen;
}

i++;  
offSet = i * (256-11);  
}

return result;
}
//下面的代码用base64编码加密后的数据
CBase64 base;
string strbase= base.Encode((const unsigned char*)encoded,nLen);


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (12)
雪    币: 187
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2

填充问题,两边选择不自动填充。
自己填充。

注意,不填充少的部分你要自己补全的(用0补全也好)
不能互通一般就是这个问题。

2017-8-31 15:24
0
雪    币: 3710
活跃值: (2669)
能力值: ( LV7,RANK:105 )
在线值:
发帖
回帖
粉丝
3
你上面的公钥证书解码出来的公钥和公钥指数是下面这个值,能不能把待加密的数据和加密出来的结果发出来,我调试下C++版本的代码给你
pubkey=  C3E0F8A5311151E98FB4622CB5EAE2796A136D14CD1E06740CDF59E2A7EB4B4DDE58FDF7F7F241906C8AC25072902CD80EDF0BD18316FF55E0D5AA69606BDFA389A756FC7321B735B6E6A71F567EC275DBAC7AA05B99DD94C8D9DF6F260F20C84473E6CC0F053184AF3C626D9EBBF81FD4DCF8278AAE6896B246F3C418384FF314C58B24FFE59683ACB975453AD6BC2BD7D1F20592AAF77C47F0839CB60791C6C7FAA08B50275CB535DE795D512E9762E1E4AB5367364C580C2B788ABF1216491F45DD6CE787872EFCFDF32642D90AA49A8BA513136ACD590569959EA1F180141CBE178EBBA70D18961B69D8AC24393B628E8C5B733B9116F26DE53B0BDC9FED
pubExponent=010001
2017-8-31 15:28
0
雪    币: 43
活跃值: (388)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
4
遇到过类似的坑,是填充问题。某些情况下(记不清了)c++解密后的明文是在缓冲区尾部的~~  一不注意看到的就是一堆乱码~
2017-8-31 15:32
0
雪    币: 1981
活跃值: (771)
能力值: ( LV13,RANK:420 )
在线值:
发帖
回帖
粉丝
5
做过C++和PHP的通信,是因为填充的方法不一样,要选择自己填充
验证方法:
        两边都选择不填充(RSA_NO_PADDING),然后加密一个256字节数据(因为你的密钥是2048bit的,256字节不需要填充,否则要自己填充到256),看能否正常解密
如果能正常解密就说明是填充问题了

最后就是要自己实现填充
2017-8-31 15:45
0
雪    币: 878
活跃值: (496)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
malokch 遇到过类似的坑,是填充问题。某些情况下(记不清了)c++解密后的明文是在缓冲区尾部的~~ 一不注意看到的就是一堆乱码~
是的,  比如js的RSA套件NoPadding的情况下就会颠倒,  填充字节在缓冲区开始
2017-8-31 16:19
0
雪    币: 1787
活跃值: (340)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
7
rrrfff 是的, 比如js的RSA套件NoPadding的情况下就会颠倒, 填充字节在缓冲区开始
大部分大数存储,都是大端。
2017-8-31 16:58
0
雪    币: 878
活跃值: (496)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
yezhulove 大部分大数存储,都是大端。
我说的这个似乎牵扯不到大数问题,  它是在padding时故意这么做的,  另一种OHDave就没颠倒
2017-8-31 17:37
0
雪    币: 364
活跃值: (61)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
9

RSA跨平台有2个注意:一个padding方式(如nopadding,pkcs8);另外一个是加密模式(ECB,CBC等)。两者一致了肯定可以通。

2017-8-31 18:08
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
10
java里用jni方式使用openssl库就好了,当年我也遇到了,我选择了jni调用openssl放弃java那套莫名其妙的玩意。

2017-8-31 18:57
0
雪    币: 180
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
已经解决,加密没有问题的,是因为base64编码的时候,出现了\r\n字符导致的。请问怎么结款,见者有份哦
2017-9-1 11:28
0
雪    币: 1787
活跃值: (340)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
mastercom 已经解决,加密没有问题的,是因为base64编码的时候,出现了\r\n字符导致的。请问怎么结款,见者有份哦
啊哈,估计只能给一个人。
2017-9-1 11:29
0
雪    币: 45
活跃值: (23)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
感觉错过几百亿~~
2017-9-12 09:36
0
游客
登录 | 注册 方可回帖
返回
//