iOS下的RSA加密方法

来源:互联网 发布:linux dns ipv6 ipv4 编辑:程序博客网 时间:2024/04/28 19:10

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

01//
02//  RSA.h
03//
04#import <Foundation/Foundation.h>
05
06@interface RSA : NSObject {
07    SecKeyRef publicKey;
08    SecCertificateRef certificate;
09    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

01//
02//  RSA.m
03//
04#import "RSA.h"
05
06@implementation RSA
07
08- (id)init {
09    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    void *plain = malloc(plainLen);
63    [content getBytes:plain
64               length:plainLen];
65     
66    size_t cipherLen = 128; // 当前RSA的密钥长度是128字节
67    void *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

使用方法:

1RSA *rsa = [[RSA alloc] init];
2if (rsa != nil) {
3    NSLog(@"%@",[rsa encryptWithString:@"test"]);
4}
5else {
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 0
原创粉丝点击