古詩詞大全網 - 個性簽名 - iOS使用openSSL加密應該怎麽做

iOS使用openSSL加密應該怎麽做

最近幾天折騰了壹下如何在iOS上使用RSA來加密。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

//

// RSA.h

//

#import Foundation.h>

@interface RSA : NSObject {

SecKeyRef publicKey;

SecCertificateRef certificate;

SecPolicyRef policy;

SecTrustRef trust;

size_t maxPlainLen;

}

- (NSData *) encryptWithData:(NSData *)content;

- (NSData *) encryptWithString:(NSString *)content;

@end

RSA.m

//

// RSA.m

//

#import "RSA.h"

@implementation RSA

- (id)init {

self = [super init];

NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@"public_key"

ofType:@"der"];

if (publicKeyPath == nil) {

NSLog(@"Can not find pub.der");

return nil;

}

NSDate *publicKeyFileContent = [NSData dataWithContentsOfFile:publicKeyPath];

if (publicKeyFileContent == nil) {

NSLog(@"Can not read from pub.der");

return nil;

}

certificate = SecCertificateCreateWithData(kCFAllocatorDefault, ( __bridge CFDataRef)publicKeyFileContent);

if (certificate == nil) {

NSLog(@"Can not read certificate from pub.der");

return nil;

}

policy = SecPolicyCreateBasicX509();

OSStatus returnCode = SecTrustCreateWithCertificates(certificate, policy, &trust);

if (returnCode != 0) {

NSLog(@"SecTrustCreateWithCertificates fail. Error Code: %ld", returnCode);

return nil;

}

SecTrustResultType trustResultType;

returnCode = SecTrustEvaluate(trust, &trustResultType);

if (returnCode != 0) {

NSLog(@"SecTrustEvaluate fail. Error Code: %ld", returnCode);

return nil;

}

publicKey = SecTrustCopyPublicKey(trust);

if (publicKey == nil) {

NSLog(@"SecTrustCopyPublicKey fail");

return nil;

}

maxPlainLen = SecKeyGetBlockSize(publicKey) - 12;

return self;

}

- (NSData *) encryptWithData:(NSData *)content {

size_t plainLen = [content length];

if (plainLen > maxPlainLen) {

NSLog(@"content(%ld) is too long, must < %ld", plainLen, maxPlainLen);

return nil;

}

void *plain = malloc(plainLen);

[content getBytes:plain

length:plainLen];

size_t cipherLen = 128; // 當前RSA的密鑰長度是128字節

void *cipher = malloc(cipherLen);

OSStatus returnCode = SecKeyEncrypt(publicKey, kSecPaddingPKCS1, plain,

plainLen, cipher, &cipherLen);

NSData *result = nil;

if (returnCode != 0) {

NSLog(@"SecKeyEncrypt fail. Error Code: %ld", returnCode);

}

else {

result = [NSData dataWithBytes:cipher

length:cipherLen];

}

free(plain);

free(cipher);

return result;

}

- (NSData *) encryptWithString:(NSString *)content {

return [self encryptWithData:[content dataUsingEncoding:NSUTF8StringEncoding]];

}

- (void)dealloc{

CFRelease(certificate);

CFRelease(trust);

CFRelease(policy);

CFRelease(publicKey);

}

@end

使用方法:

RSA *rsa = [[RSA alloc] init];

if (rsa != nil) {

NSLog(@"%@",[rsa encryptWithString:@"test"]);

}

else {

NSLog(@"init rsa error");

}