在 iOS 上, 加密被和安全性进行了强绑定, 所以, 你不能只做加密(至少公开文档不告诉你如何只做加密). 但事实上, 很多时候我们加密, 并不是要求 100% 的安全, 只是希望能得到加密本身所带来的安全, 既不考虑数据重放, 也不考虑第三者攻击, 也不考虑身份伪装. 我们仅仅是需要RSA加密。
下面介绍三种方法:
- iOS通常的RSA加密方法--Security.framework
- openssl库编译到iOS工程中,详见:https://github.com/x2on/OpenSSL-for-iPhone
- IOS RSA API,这个是专用于IOS的RSA算法API,使用简单效率高效,但不是免费地。有需要可联系:QQ1561724180 手机:13803113171
===================
iOS通常的RSA加密方法--Security.framework
===================
通常,iOS上并没有直接的RSA加密API。但是iOS提供了x509的API,而x509是支持RSA加密的。因此,我们可以通过制作自签名的x509证书 (由于对安全性要求不高,我们并不需要使用CA认证的证书),再调用x509的相关API来进行加密。
整个流程:
第一步,制作自签名的证书
1.最简单快捷的方法,打开Terminal,使用openssl(Mac OS X自带)生成私钥和自签名的x509证书。
openssl req -x509 -out public_key.der -outform der -new -newkey rsa:1024 -keyout private_key.pem -days 3650
按照命令行的提示输入内容就行了。
几个说明:
public_key.der是输出的自签名的x509证书,即我们要用的。
private_key.pem是输出的私钥,用来解密的,请妥善保管。
rsa:1024这里的1024是密钥长度,1024是比较安全的,如果需要更安全的话,可以用2048,但是加解密代价也会增加。
-days:证书过期时间,一定要加上这个参数,默认的证书过期时间是30天,一般我们不希望证书这么短就过期,所以写上比较合适的天数,例如这里的3650(10年)。
事实上,这一行命令包含了好几个步骤(我研究下面这些步骤的原因是我手头已经由一个private_key.pem私钥了,想直接用这个来生成x509证书,也就是用到了下面的2-3)
1)创建私钥
openssl genrsa -out private_key.pem 1024
2)创建证书请求(按照提示输入信息)
openssl req -new -out cert.csr -key private_key.pem
3)自签署根证书
openssl x509 -req -in cert.csr -out public_key.der -outform der -signkey private_key.pem -days 3650
2.验证证书。把public_key.der拖到xcode中,如果文件没有问题的话,那么就可以直接在xcode中打开,看到证书的各种信息。如下图所示:
第二步,使用public_key.der来进行加密。
1.导入Security.framework。
2.把public_key.der放到mainBundle中(一般直接拖到Xcode就行啦)。
3.从public_key.der读取公钥。
4.加密。
下面是参考代码(只能用于加密长度小于等于116字节的内容,适合于对密码进行加密。使用了ARC,不过还是要注意部分资源需要使用CFRealse来释放)
RSA.h
04 |
#import <Foundation/Foundation.h> |
06 |
@interface RSA : NSObject { |
08 |
SecCertificateRef certificate; |
14 |
- (NSData *) encryptWithData:(NSData *)content; |
15 |
- (NSData *) encryptWithString:(NSString *)content; |
RSA.m
11 |
NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@ "public_key" |
13 |
if (publicKeyPath == nil) { |
14 |
NSLog(@ "Can not find pub.der" ); |
18 |
NSDate *publicKeyFileContent = [NSData dataWithContentsOfFile:publicKeyPath]; |
19 |
if (publicKeyFileContent == nil) { |
20 |
NSLog(@ "Can not read from pub.der" ); |
24 |
certificate = SecCertificateCreateWithData(kCFAllocatorDefault, ( __bridge CFDataRef)publicKeyFileContent); |
25 |
if (certificate == nil) { |
26 |
NSLog(@ "Can not read certificate from pub.der" ); |
30 |
policy = SecPolicyCreateBasicX509(); |
31 |
OSStatus returnCode = SecTrustCreateWithCertificates(certificate, policy, &trust); |
32 |
if (returnCode != 0) { |
33 |
NSLog(@ "SecTrustCreateWithCertificates fail. Error Code: %ld" , returnCode); |
37 |
SecTrustResultType trustResultType; |
38 |
returnCode = SecTrustEvaluate(trust, &trustResultType); |
39 |
if (returnCode != 0) { |
40 |
NSLog(@ "SecTrustEvaluate fail. Error Code: %ld" , returnCode); |
44 |
publicKey = SecTrustCopyPublicKey(trust); |
45 |
if (publicKey == nil) { |
46 |
NSLog(@ "SecTrustCopyPublicKey fail" ); |
50 |
maxPlainLen = SecKeyGetBlockSize(publicKey) - 12; |
54 |
- (NSData *) encryptWithData:(NSData *)content { |
56 |
size_t plainLen = [content length]; |
57 |
if (plainLen > maxPlainLen) { |
58 |
NSLog(@ "content(%ld) is too long, must < %ld" , plainLen, maxPlainLen); |
62 |
void *plain = malloc (plainLen); |
63 |
[content getBytes:plain |
66 |
size_t cipherLen = 128; |
67 |
void *cipher = malloc (cipherLen); |
69 |
OSStatus returnCode = SecKeyEncrypt(publicKey, kSecPaddingPKCS1, plain, |
70 |
plainLen, cipher, &cipherLen); |
73 |
if (returnCode != 0) { |
74 |
NSLog(@ "SecKeyEncrypt fail. Error Code: %ld" , returnCode); |
77 |
result = [NSData dataWithBytes:cipher |
87 |
- (NSData *) encryptWithString:(NSString *)content { |
88 |
return [self encryptWithData:[content dataUsingEncoding:NSUTF8StringEncoding]]; |
92 |
CFRelease(certificate); |
使用方法:
1 |
RSA *rsa = [[RSA alloc] init]; |
3 |
NSLog(@ "%@" ,[rsa encryptWithString:@ "test" ]); |
6 |
NSLog(@ "init rsa error" ); |