首先最近我们在做一个APP 但是我们数据交互都是明文的=- = 这咋办勒,傻子也知道加密一下咯。可是加密也有问题 对称加密的话,人家破解你的应用就能知道了。所以用到了非对称加密并且每个APP生成不同的RSA密钥对。
实现再iOS上面实现RSA加密并不难,因为iOS中有openssl 和 系统自带的 security.framework。我这里选择了openSSL 因为我比较懒 =- = 发现别人已经写好了 直接就用了呗。security.framework其实也不错的,就是我还不知道咋用。
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了一下,没错,这里确实没错。
我起初再这里还绕弯了 我以为是key错误了。其实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 可以看我的个人博客,当然我也会更新到这里来~
新闻热点
疑难解答