背景
首先最近我们在做一个APP 但是我们数据交互都是明文的=- = 这咋办勒,傻子也知道加密一下咯。可是加密也有问题 对称加密的话,人家破解你的应用就能知道了。所以用到了非对称加密并且每个APP生成不同的RSA密钥对。
初步实现
实现再iOS上面实现RSA加密并不难,因为iOS中有openssl 和 系统自带的 security.framework。我这里选择了openSSL 因为我比较懒 =- = 发现别人已经写好了 直接就用了呗。security.framework其实也不错的,就是我还不知道咋用。
初试OpenSSL RSA
Demo地址
这个是GitHub上面一个人写好的,实现了OpenSSL 的RSA加密
问题
1.在iOS上 使用OpenSSL 生成的公钥私钥编码是X509的,而我们服务器使用的是.NET的(.NET的编码是PKCS#8) PS:(←。 ←)我也不知道对不对,这几天百度的结果是酱紫的,
.NET与JAVA(android)RSA通信 可以参考这个地址,我个人总结的是,JAVA支持集中不同的编码格式,所以JAVA通信问题不大
2.如何转换不同的证书
过程
1.先找了如何让两个生成的密文一样,但是发现有paddingPKCS1这种东西肯定不行(宣告失败)
2.想办法生成一个PKCS#8的密钥对(我试了一些openssl的命令行,可是最终密钥对要app生成的,所以没继续,也宣告失败了)
3..NET服务端使用openssl解决该问题(可是如果这样的话 ,android又需要修改,所以宣布放弃了)
4.转换密钥对编码(其实其中我还找了 iOS与Java通信之类的,这里我就不一一阐述了)
这个弯路其实挺长的,我总结了一下是这么几点,但是历史一天时间了。。。
主要我就来讲一下最后一点吧。肯定会有朋友问我是这么发现这两个密钥对的区别的。
不要着急,我们广告之后继续。
解决问题
首先我建议各位下载一下那个github里面的代码,这样容易理解。
当你运行完一次程序,你会发现你的iPhone模拟器目录下面会有 publicKey.pem 和 privateKey.pem
我们需要把publicKey交给服务端,这样他加密的东西,只有我这个privateKey可以解,这些原理我就不多做说明了。
然后我们打开publicKey会是一下
/*
This return value based on the key that generated by openssl.
—–BEGIN RSA PUBLIC KEY—–
MIGHAoGBAOp5TLclpWCaNDzHYPfB26SLmS8vlSXH4PyKopz5OS5Vx994FBQQLwv9
2pIJQsBk09egrL0gbASK1VCwDt0MmaiyrNFl/xaEzB/VOvjoojBUzMMIca9fKmx5
GAzSbSP7we64dhvrziuuNVTuM/e2XSa2skKFHMI0bCq4+pNYhvRhAgED
—–END RSA PUBLIC KEY—–
*/
然后我们看一下源代码
- (NSString)publicKeyBase64{
NSFileManager fm = [NSFileManager defaultManager];
if ([fm fileExistsAtPath:OpenSSLRSAPublicKeyFile]) {
NSString str = [NSString stringWithContentsOfFile:OpenSSLRSAPublicKeyFile encoding:NSUTF8StringEncoding error:nil];
NSData data = [self publicKeyBitsWithString:[[str componentsSeparatedByString:@”—–”] objectAtIndex:2]];
return [data base64EncodedString];
}
return nil;
}
这里我们看到OpenSSL将整个证书文件Base64了一下,没错,这里确实没错。
我起初再这里还绕弯了 我以为错误了。其实OpenSSL 正确的publicKey转NSData后 大小一定是162,如果你只是其中那一段(没有—-**—-这两行的话)就是140了。
我同事再查看OpenSSL.NET的源代码的时候发现了一段转换过程,然后我看了一下.NET端的代码,代码如下
看得懂.net的或者看不懂.NET的应该都可以看的懂很简单的代码。
so 我饶了这么大的弯子,你们应该一看就知道了接下来就是处理了,这么让publicKey变成128-》PKCS#8标准的编码呢,按照.NET的OpenSSL代码翻译下一下
if((unsigned long)[NSData dataWithBase64EncodedString:wrapper.publicKeyBase64].length<162)
{
NSLog(@”公钥格式不正确!”);
return;
}
else
{
//取出.NET可以使用的 PubKey
NSData keyData=[NSData dataWithBase64EncodedString:wrapper.publicKeyBase64];
NSData newKeyData =[keyData subdataWithRange:NSMakeRange(29, 128)];
NSLog(@”NewPubKey:%@”,[newKeyData base64EncodedString]);
}
小结
上面这个就是我的处理过程 =- = 这次的这个RSA的坑是真坑啊,我要是没看服务端代码 肯定搞不出来,因为本地加解密都是OK的,唉,所以这件事情告诉我们,看问题必须得从多个方面看,而且不能只是看自己手头上的可以从多个方面入手寻找资料。不过这次也是因为我会.NET所以我会想到去看一下。
这个坑记录一下 希望可以帮到大家
然后我又要开始坑AES了 =- = 祝我好运吧