iOS下的RSA加密方法

最近几天折腾了一下如何在iOS上使用RSA来加密。iOS上并没有直接的RSA加密API。但是iOS提供了x509的API,而x509是支持RSA加密的。因此,我们可以通过制作自签名的x509证书(由于对安全性要求不高,我们并不需要使用CA认证的证书),再调用x509的相关API来进行加密。接下来记录一下整个流程。

第一步,制作自签名的证书

1.最简单快捷的方法,打开Terminal,使用openssl(Mac OS X自带)生成私钥和自签名的x509证书。

  1. 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)创建私钥

  1. openssl genrsa -out private_key.pem 1024  
2)创建证书请求(按照提示输入信息)

  1. openssl req -new -out cert.csr -key private_key.pem  
3)自签署根证书

  1. 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


  1. //  
  2. //  RSA.h  
  3. //  
  4. #import <Foundation/Foundation.h>  
  5.   
  6. @interface RSA : NSObject {  
  7.     SecKeyRef publicKey;  
  8.     SecCertificateRef certificate;  
  9.     SecPolicyRef policy;  
  10.     SecTrustRef trust;  
  11.     size_t maxPlainLen;  
  12. }  
  13.   
  14. - (NSData *) encryptWithData:(NSData *)content;  
  15. - (NSData *) encryptWithString:(NSString *)content;  
  16.   
  17. @end  
RSA.m

  1. //  
  2. //  RSA.m  
  3. //  
  4. #import "RSA.h"  
  5.   
  6. @implementation RSA  
  7.   
  8. - (id)init {  
  9.     self = [super init];  
  10.       
  11.     NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@"public_key"  
  12.                                                      ofType:@"der"];  
  13.     if (publicKeyPath == nil) {  
  14.         NSLog(@"Can not find pub.der");  
  15.         return nil;  
  16.     }  
  17.       
  18.     NSDate *publicKeyFileContent = [NSData dataWithContentsOfFile:publicKeyPath];  
  19.     if (publicKeyFileContent == nil) {  
  20.         NSLog(@"Can not read from pub.der");  
  21.         return nil;  
  22.     }  
  23.       
  24.     certificate = SecCertificateCreateWithData(kCFAllocatorDefault, ( __bridge CFDataRef)publicKeyFileContent);  
  25.     if (certificate == nil) {  
  26.         NSLog(@"Can not read certificate from pub.der");  
  27.         return nil;  
  28.     }  
  29.       
  30.     policy = SecPolicyCreateBasicX509();  
  31.     OSStatus returnCode = SecTrustCreateWithCertificates(certificate, policy, &trust);  
  32.     if (returnCode != 0) {  
  33.         NSLog(@"SecTrustCreateWithCertificates fail. Error Code: %ld", returnCode);  
  34.         return nil;  
  35.     }  
  36.       
  37.     SecTrustResultType trustResultType;  
  38.     returnCode = SecTrustEvaluate(trust, &trustResultType);  
  39.     if (returnCode != 0) {  
  40.         NSLog(@"SecTrustEvaluate fail. Error Code: %ld", returnCode);  
  41.         return nil;  
  42.     }  
  43.       
  44.     publicKey = SecTrustCopyPublicKey(trust);  
  45.     if (publicKey == nil) {  
  46.         NSLog(@"SecTrustCopyPublicKey fail");  
  47.         return nil;  
  48.     }  
  49.       
  50.     maxPlainLen = SecKeyGetBlockSize(publicKey) - 12;  
  51.     return self;  
  52. }  
  53.   
  54. - (NSData *) encryptWithData:(NSData *)content {  
  55.       
  56.     size_t plainLen = [content length];  
  57.     if (plainLen > maxPlainLen) {  
  58.         NSLog(@"content(%ld) is too long, must < %ld", plainLen, maxPlainLen);  
  59.         return nil;  
  60.     }  
  61.       
  62.     voidvoid *plain = malloc(plainLen);  
  63.     [content getBytes:plain   
  64.                length:plainLen];  
  65.       
  66.     size_t cipherLen = 128// 当前RSA的密钥长度是128字节  
  67.     voidvoid *cipher = malloc(cipherLen);  
  68.       
  69.     OSStatus returnCode = SecKeyEncrypt(publicKey, kSecPaddingPKCS1, plain,   
  70.                                         plainLen, cipher, &cipherLen);  
  71.       
  72.     NSData *result = nil;  
  73.     if (returnCode != 0) {  
  74.         NSLog(@"SecKeyEncrypt fail. Error Code: %ld", returnCode);  
  75.     }  
  76.     else {  
  77.         result = [NSData dataWithBytes:cipher   
  78.                                 length:cipherLen];  
  79.     }  
  80.       
  81.     free(plain);  
  82.     free(cipher);  
  83.       
  84.     return result;  
  85. }  
  86.   
  87. - (NSData *) encryptWithString:(NSString *)content {  
  88.     return [self encryptWithData:[content dataUsingEncoding:NSUTF8StringEncoding]];  
  89. }  
  90.   
  91. - (void)dealloc{  
  92.     CFRelease(certificate);  
  93.     CFRelease(trust);  
  94.     CFRelease(policy);  
  95.     CFRelease(publicKey);  
  96. }  
  97.   
  98. @end  
使用方法:

  1. RSA *rsa = [[RSA alloc] init];  
  2. if (rsa != nil) {  
  3.     NSLog(@"%@",[rsa encryptWithString:@"test"]);  
  4. }  
  5. else {  
  6.     NSLog(@"init rsa error");  
  7. }  

参考:

1. (原创)如何生成以及导入X.509证书

http://hi.baidu.com/five00/blog/item/43bf1fd77df2d8d9a044df39.html

2. ios下使用rsa算法与php进行加解密通讯

http://blog.yorkgu.me/2011/10/27/rsa-in-ios-using-publick-key-generated-by-openssl/

3. Certificate, Key, and Trust Services Reference

http://developer.apple.com/library/mac/#documentation/security/Reference/certifkeytrustservices/Reference/reference.html

4. X509

http://baike.baidu.com/view/2841580.htm

5. RSA

http://zh.wikipedia.org/zh/RSA%E5%8A%A0%E5%AF%86%E6%BC%94%E7%AE%97%E6%B3%95


转自:

http://blog.iamzsx.me/show.html?id=155002

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值