您的位置:首页 > 运维架构

基于OpenSLL的RSA加密应用

2017-04-07 17:42 211 查看
转载:http://blog.csdn.net/hou3035/article/details/51437938

一、RSA加密工具类(der和p12)~

本加密工具适用于DES,AES,RSA加密~下面是代码,不做讲解~因为核心算法的代码不是本人写的~笔者只做了整理和封装~

CryptorTools.h

//

// CryptorTools.h

// 加密/解密工具

//

// Created by Erma on 15/4/26.

// Copyright (c) 2015年 Erma. All rights reserved.

//

import

/// 加密工具类

/// 提供RSA & AES & DES加密方法

@interface CryptorTools : NSObject

pragma mark - DES 加密/解密

/// DES 加密

///

/// @param data 要加密的二进制数据

/// @param keyString 加密密钥

/// @param iv IV向量

///

/// @return 加密后的二进制数据

+ (NSData *)DESEncryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSData *)iv;

/// DES 加密字符串

///

/// @param string 要加密的字符串

/// @param keyString 加密密钥

/// @param iv IV向量

///

/// @return 加密后的 BASE64 编码字符串

+ (NSString *)DESEncryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv;

/// DES 解密

///

/// @param data 要解密的二进制数据

/// @param keyString 解密密钥

/// @param iv IV向量

///

/// @return 解密后的二进制数据

+ (NSData *)DESDecryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSData *)iv;

/// DES 解密

///

/// @param string 要解密的 BASE64 编码字符串

/// @param keyString 解密密钥

/// @param iv IV向量

///

/// @return 解密后的二进制数据

+ (NSString *)DESDecryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv;

pragma mark - AES 加密/解密

/// AES 加密

///

/// @param data 要加密的二进制数据

/// @param keyString 加密密钥

/// @param iv IV向量

///

/// @return 加密后的二进制数据

+ (NSData *)AESEncryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSData *)iv;

/// AES 加密字符串

///

/// @param string 要加密的字符串

/// @param keyString 加密密钥

/// @param iv IV向量

///

/// @return 加密后的 BASE64 编码字符串

+ (NSString *)AESEncryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv;

/// AES 解密

///

/// @param data 要解密的二进制数据

/// @param keyString 解密密钥

/// @param iv IV向量

///

/// @return 解密后的二进制数据

+ (NSData *)AESDecryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSData *)iv;

/// AES 解密

///

/// @param string 要解密的 BASE64 编码字符串

/// @param keyString 解密密钥

/// @param iv IV向量

///

/// @return 解密后的二进制数据

+ (NSString *)AESDecryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv;

pragma mark - RSA 加密/解密算法

/// 加载公钥

///

/// @param filePath DER 公钥文件路径

- (void)loadPublicKeyWithFilePath:(NSString *)filePath;

/// 加载私钥

///

/// @param filePath P12 私钥文件路径

/// @param password P12 密码

- (void)loadPrivateKey:(NSString *)filePath password:(NSString *)password;

/// RSA 加密数据

///

/// @param data 要加密的数据

///

/// @return 加密后的二进制数据

- (NSData *)RSAEncryptData:(NSData *)data;

/// RSA 加密字符串

///

/// @param string 要加密的字符串

///

/// @return 加密后的 BASE64 编码字符串

- (NSString *)RSAEncryptString:(NSString *)string;

/// RSA 解密数据

///

/// @param data 要解密的数据

///

/// @return 解密后的二进制数据

- (NSData *)RSADecryptData:(NSData *)data;

/// RSA 解密字符串

///

/// @param string 要解密的 BASE64 编码字符串

///

/// @return 解密后的字符串

- (NSString *)RSADecryptString:(NSString *)string;

@end

CryptorTools.m

//

// CryptorTools.m

// 加密/解密工具

//

// Created by Erma on 15/4/26.

// Copyright (c) 2015年 Erma. All rights reserved.

//

import "CryptorTools.h"

import

// 填充模式

define kTypeOfWrapPadding kSecPaddingPKCS1

@interface CryptorTools() {

SecKeyRef _publicKeyRef; // 公钥引用

SecKeyRef _privateKeyRef; // 私钥引用

}

@end

@implementation CryptorTools

pragma mark - DES 加密/解密

pragma mark 加密

(NSData *)DESEncryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSData *)iv {

return [self CCCryptData:data algorithm:kCCAlgorithmDES operation:kCCEncrypt keyString:keyString iv:iv];

}

(NSString *)DESEncryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv {

NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];

NSData *result = [self DESEncryptData:data keyString:keyString iv:iv];

// BASE 64 编码

return [result base64EncodedStringWithOptions:0];

}

pragma mark 解密

(NSData *)DESDecryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSData *)iv {

return [self CCCryptData:data algorithm:kCCAlgorithmDES operation:kCCDecrypt keyString:keyString iv:iv];

}

(NSString *)DESDecryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv {

// BASE 64 解码

NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:0];

NSData *result = [self DESDecryptData:data keyString:keyString iv:iv];

return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];

}

pragma mark - AES 加密/解密

pragma mark 加密

(NSData *)AESEncryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSData *)iv {

return [self CCCryptData:data algorithm:kCCAlgorithmAES operation:kCCEncrypt keyString:keyString iv:iv];

}

(NSString *)AESEncryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv {

NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];

NSData *result = [self AESEncryptData:data keyString:keyString iv:iv];

// BASE 64 编码

return [result base64EncodedStringWithOptions:0];

}

pragma mark 解密

(NSData *)AESDecryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSData *)iv {

return [self CCCryptData:data algorithm:kCCAlgorithmAES operation:kCCDecrypt keyString:keyString iv:iv];

}

(NSString *)AESDecryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv {

// BASE 64 解码

NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:0];

NSData *result = [self AESDecryptData:data keyString:keyString iv:iv];

return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];

}

pragma mark 对称加密&解密核心方法

/// 对称加密&解密核心方法

///

/// @param data 加密/解密的二进制数据

/// @param algorithm 加密算法

/// @param operation 加密/解密操作

/// @param keyString 密钥字符串

/// @param iv IV 向量

///

/// @return 加密/解密结果

+ (NSData *)CCCryptData:(NSData *)data algorithm:(CCAlgorithm)algorithm operation:(CCOperation)operation keyString:(NSString *)keyString iv:(NSData *)iv {

int keySize = (algorithm == kCCAlgorithmAES) ? kCCKeySizeAES128 : kCCKeySizeDES;

int blockSize = (algorithm == kCCAlgorithmAES) ? kCCBlockSizeAES128: kCCBlockSizeDES;

// 设置密钥

NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];

uint8_t cKey[keySize];

bzero(cKey, sizeof(cKey));

[keyData getBytes:cKey length:keySize];

// 设置 IV 向量

uint8_t cIv[blockSize];

bzero(cIv, blockSize);

int option = kCCOptionPKCS7Padding | kCCOptionECBMode;

if (iv) {

[iv getBytes:cIv length:blockSize];

option = kCCOptionPKCS7Padding;

}

// 设置输出缓冲区

size_t bufferSize = [data length] + blockSize;

void *buffer = malloc(bufferSize);

// 加密或解密

size_t cryptorSize = 0;

CCCryptorStatus cryptStatus = CCCrypt(operation,

algorithm,

option,

cKey,

keySize,

cIv,

[data bytes],

[data length],

buffer,

bufferSize,

&cryptorSize);

NSData *result = nil;

if (cryptStatus == kCCSuccess) {

result = [NSData dataWithBytesNoCopy:buffer length:cryptorSize];

} else {

free(buffer);

NSLog(@"[错误] 加密或解密失败 | 状态编码: %d", cryptStatus);

}

return result;

}

pragma mark - RSA 加密/解密算法

(void)loadPublicKeyWithFilePath:(NSString *)filePath; {

NSAssert(filePath.length != 0, @"公钥路径为空");

// 删除当前公钥

if (_publicKeyRef) CFRelease(_publicKeyRef);

// 从一个 DER 表示的证书创建一个证书对象

NSData *certificateData = [NSData dataWithContentsOfFile:filePath];

SecCertificateRef certificateRef = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certificateData);

NSAssert(certificateRef != NULL, @"公钥文件错误");

// 返回一个默认 X509 策略的公钥对象,使用之后需要调用 CFRelease 释放

SecPolicyRef policyRef = SecPolicyCreateBasicX509();

// 包含信任管理信息的结构体

SecTrustRef trustRef;

// 基于证书和策略创建一个信任管理对象

OSStatus status = SecTrustCreateWithCertificates(certificateRef, policyRef, &trustRef);

NSAssert(status == errSecSuccess, @"创建信任管理对象失败");

// 信任结果

SecTrustResultType trustResult;

// 评估指定证书和策略的信任管理是否有效

status = SecTrustEvaluate(trustRef, &trustResult);

NSAssert(status == errSecSuccess, @"信任评估失败");

// 评估之后返回公钥子证书

_publicKeyRef = SecTrustCopyPublicKey(trustRef);

NSAssert(_publicKeyRef != NULL, @"公钥创建失败");

if (certificateRef) CFRelease(certificateRef);

if (policyRef) CFRelease(policyRef);

if (trustRef) CFRelease(trustRef);

}

(void)loadPrivateKey:(NSString *)filePath password:(NSString *)password {

NSAssert(filePath.length != 0, @"私钥路径为空");

// 删除当前私钥

if (_privateKeyRef) CFRelease(_privateKeyRef);

NSData *PKCS12Data = [NSData dataWithContentsOfFile:filePath];

CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;

CFStringRef passwordRef = (__bridge CFStringRef)password;

// 从 PKCS #12 证书中提取标示和证书

SecIdentityRef myIdentity;

SecTrustRef myTrust;

const void *keys[] = {kSecImportExportPassphrase};

const void *values[] = {passwordRef};

CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);

CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);

// 返回 PKCS #12 格式数据中的标示和证书

OSStatus status = SecPKCS12Import(inPKCS12Data, optionsDictionary, &items);

if (status == noErr) {

CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);

myIdentity = (SecIdentityRef)CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);

myTrust = (SecTrustRef)CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemTrust);

}

if (optionsDictionary) CFRelease(optionsDictionary);

NSAssert(status == noErr, @"提取身份和信任失败");

SecTrustResultType trustResult;

// 评估指定证书和策略的信任管理是否有效

status = SecTrustEvaluate(myTrust, &trustResult);

NSAssert(status == errSecSuccess, @"信任评估失败");

// 提取私钥

status = SecIdentityCopyPrivateKey(myIdentity, &_privateKeyRef);

NSAssert(status == errSecSuccess, @"私钥创建失败");

CFRelease(items);

}

(NSString *)RSAEncryptString:(NSString *)string {

NSData *cipher = [self RSAEncryptData:[string dataUsingEncoding:NSUTF8StringEncoding]];

return [cipher base64EncodedStringWithOptions:0];

}

(NSData *)RSAEncryptData:(NSData *)data {

OSStatus sanityCheck = noErr;

size_t cipherBufferSize = 0;

size_t keyBufferSize = 0;

NSAssert(data, @"明文数据为空");

NSAssert(_publicKeyRef, @"公钥为空");

NSData *cipher = nil;

uint8_t *cipherBuffer = NULL;

// 计算缓冲区大小

cipherBufferSize = SecKeyGetBlockSize(_publicKeyRef);

keyBufferSize = data.length;

if (kTypeOfWrapPadding == kSecPaddingNone) {

NSAssert(keyBufferSize <= cipherBufferSize, @"加密内容太大");

} else {

NSAssert(keyBufferSize <= (cipherBufferSize - 11), @"加密内容太大");

}

// 分配缓冲区

cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));

memset((void *)cipherBuffer, 0x0, cipherBufferSize);

// 使用公钥加密

sanityCheck = SecKeyEncrypt(_publicKeyRef,

kTypeOfWrapPadding,

(const uint8_t *)data.bytes,

keyBufferSize,

cipherBuffer,

&cipherBufferSize

);

NSAssert(sanityCheck == noErr, @"加密错误,OSStatus == %d", sanityCheck);

// 生成密文数据

cipher = [NSData dataWithBytes:(const void *)cipherBuffer length:(NSUInteger)cipherBufferSize];

if (cipherBuffer) free(cipherBuffer);

return cipher;

}

(NSString *)RSADecryptString:(NSString *)string {

NSData *keyData = [self RSADecryptData:[[NSData alloc] initWithBase64EncodedString:string options:0]];

return [[NSString alloc] initWithData:keyData encoding:NSUTF8StringEncoding];

}

(NSData *)RSADecryptData:(NSData *)data {

OSStatus sanityCheck = noErr;

size_t cipherBufferSize = 0;

size_t keyBufferSize = 0;

NSData *key = nil;

uint8_t *keyBuffer = NULL;

SecKeyRef privateKey = _privateKeyRef;

NSAssert(privateKey != NULL, @"私钥不存在");

// 计算缓冲区大小

cipherBufferSize = SecKeyGetBlockSize(privateKey);

keyBufferSize = data.length;

NSAssert(keyBufferSize <= cipherBufferSize, @"解密内容太大");

// 分配缓冲区

keyBuffer = malloc(keyBufferSize * sizeof(uint8_t));

memset((void *)keyBuffer, 0x0, keyBufferSize);

// 使用私钥解密

sanityCheck = SecKeyDecrypt(privateKey,

kTypeOfWrapPadding,

(const uint8_t *)data.bytes,

cipherBufferSize,

keyBuffer,

&keyBufferSize

);

NSAssert1(sanityCheck == noErr, @"解密错误,OSStatus == %d", sanityCheck);

// 生成明文数据

key = [NSData dataWithBytes:(const void *)keyBuffer length:(NSUInteger)keyBufferSize];

if (keyBuffer) free(keyBuffer);

return key;

}

@end

二、OpenSSL 生成密钥示例~

生成强度是 1024 的 RSA 私钥

$ openssl genrsa -out private.pem 1024

执行以代码生成一个私钥,Pem文件,其实Pem文件就是一般的文本格式~看下图~

这是文件:

选择一个文本编辑器打开次文件可以看到其就是一个普通的文本:

-----BEGIN RSA PRIVATE KEY-----

MIICXAIBAAKBgQCfwtWJLpe9QQiBOA/kDVdYGDYko6ieGfaIHiqiHd7Ul13k4gI+

1NgL6SfO/UAhKL6rAwTk9t8/V0bIrbCTBL6hMLc4yJkBFbDK7eLoJNnxaUwl2pLL

BSiTZQQ8vsBC6myUiZDFdCfl2PWvfEMzMYNsCob2Mw4MYWJwNub+MYe7PwIDAQAB

AoGAc8jXy5FKBa5BRK1lzujgWYdKjilSRisY4jPCwDWXzklZkk0+RV0qqw8ye7BN

LvsBnJ0Wif5lc9mEAmLnKtXwdWrHKEi70s69mZZH+ssaP3SGAEug3tY2ojSYixmB

+dWyslVb3dVzxr56fMJLfCBGAhqhmXgy79ruIbnKrDqo6kkCQQDPYCIZRlI0tREa

4y+E2YUqx/x6XPohlJUQoZBJQ3Zt0RQ+afljNxlSOiL4pw9GLwoDhatxzjlMUMnb

b36mP1plAkEAxTib34YEp5nkwpbZ5roAfKRmKgUnezULVCDKS/KiamXURwAUwGGU

aVy9o1akS48C42gsF+NtOe9yq1z9sj6y0wJBAICLZpekL3DcjC3OhbYj35gVPzva

RnJqV7xnabkASHjqEVJe/mexz9BYmTTo2V736Y0lXpC89GeJ7JZJFoiW3MECQDyM

4cZhpiIy7HoVyHa/GpEqBDfYd0OriHveyV1B9D2IYAEgdD6QdvlWQN7aJf0Q vklF

XWxEJe/IpUMZfMZx24MCQDu19hNYYg8863mvGbc7jWAY1Apjx1i/KTXe/6rBjmoS

bxoSEpKNHpW6dgL/6S6WQuB8j3tNUUNj5O99cU6DLsM=

-----END RSA PRIVATE KEY-----

接着跟着笔者一起执行下面的操作吧~

创建证书请求

$ openssl req -new -key private.pem -out rsacert.csr

这时候控制条要求输入以下一些个人信息~那就跟着提示来吧~

Country Name (2 letter code) [AU]:CN

State or Province Name (full name) [Some-State]:beijing

Locality Name (eg, city) []:beijing

Organization Name (eg, company) [Internet Widgits Pty Ltd]:Erma

Organizational Unit Name (eg, section) []:com

Common Name (e.g. server FQDN or YOUR name) []:Erma

Email Address []:mr_wangyaojie@163.com

Please enter the following 'extra' attributes

to be sent with your certificate request

A challenge password []:

An optional company name []:

这时候生成了一个csr文件

生成证书并且签名,有效期10年

转换格式将格式文件转换成格式openssl x509 -outform der -in rsacert.crt -out rsacert.der

导出P12文件

$ openssl pkcs12 -export -out p.p12 -inkey private.pem -in rsacert.crt

最后生成了两个我们要用的文件,一个p12文件和一个der文件,der文件是公钥,p12文件是私钥。我们把这两个文件拖入我们的Demo中来使用吧~下面是demo~

三、der和p12加密解密Demo

通过这个Demo主要讲解上面提到的工具类的使用~

示例化工具类Tool

CryptorTools *tool = [[CryptorTools alloc] init];

1、加载公钥

NSString *pubPath = [[NSBundle mainBundle] pathForResource:@"rsacert.der" ofType:nil];

[tool loadPublicKeyWithFilePath:pubPath];

2、使用公钥加密

NSString *result = [tool RSAEncryptString:@"xiaoer"];

NSLog(@"%@",result);

3、加载私钥 - 密码是导出P12的密码

NSString *privatePath = [[NSBundle mainBundle] pathForResource:@"p.p12" ofType:nil];

[tool loadPrivateKey:privatePath password:@"xyz147896321"];

4、使用私钥解密

NSLog(@"%@", [tool RSADecryptString:result]);

OK~上面是通过der和p12加密的应用过程~下面再来看看字符串公钥加密的使用方法~

四、公钥字符串加密工具类~

RSA.h

//

// RSA.h

//

// Created by Erma on 15-2-3.

// Copyright (c) 2015年 Erma. All rights reserved.

//

import

@interface RSA : NSObject

(NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey;

(NSString *)encryptData:(NSData *)data publicKey:(NSString *)pubKey;

@end

RSA.m

import "RSA.h"

import

@implementation RSA

/*

static NSString *base64_encode(NSStringstr){

NSDatadata = [str dataUsingEncoding:NSUTF8StringEncoding];

if(!data){

return nil;

}

return base64_encode_data(data);

}

*/

static NSString *base64_encode_data(NSData *data){

data = [data base64EncodedDataWithOptions:0];

NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

return ret;

}

static NSData *base64_decode(NSString *str){

NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];

return data;

}

(NSData *)stripPublicKeyHeader:(NSData *)d_key{

// Skip ASN.1 public key header

if (d_key == nil) return(nil);

unsigned long len = [d_key length];

if (!len) return(nil);

unsigned char *c_key = (unsigned char *)[d_key bytes];

unsigned int idx = 0;

if (c_key[idx++] != 0x30) return(nil);

if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;

else idx++;

// PKCS #1 rsaEncryption szOID_RSA_RSA

static unsigned char seqiod[] =

{ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,

0x01, 0x05, 0x00 };

if (memcmp(&c_key[idx], seqiod, 15)) return(nil);

idx += 15;

if (c_key[idx++] != 0x03) return(nil);

if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;

else idx++;

if (c_key[idx++] != '') return(nil);

// Now make a new NSData from this buffer

return([NSData dataWithBytes:&c_key[idx] length:len - idx]);

}

//credit:http://hg.mozilla.org/services/fx-home/file/tip/Sources/NetworkAndStorage/CryptoUtils.m#l1036

+ (NSData *)stripPrivateKeyHeader:(NSData *)d_key{

// Skip ASN.1 private key header

if (d_key == nil) return(nil);

unsigned long len = [d_key length];

if (!len) return(nil);

unsigned char *c_key = (unsigned char *)[d_key bytes];

unsigned int idx = 22; //magic byte at offset 22

if (0x04 != c_key[idx++]) return nil;

//calculate length of the key

unsigned int c_len = c_key[idx++];

int det = c_len & 0x80;

if (!det) {

c_len = c_len & 0x7f;

} else {

int byteCount = c_len & 0x7f;

if (byteCount + idx > len) {

//rsa length field longer than buffer

return nil;

}

unsigned int accum = 0;

unsigned char *ptr = &c_key[idx];

idx += byteCount;

while (byteCount) {

accum = (accum << 8) + *ptr;

ptr++;

byteCount--;

}

c_len = accum;

}

// Now make a new NSData from this buffer

return [d_key subdataWithRange:NSMakeRange(idx, c_len)];

}

(SecKeyRef)addPublicKey:(NSString *)key{

NSRange spos = [key rangeOfString:@"-----BEGIN PUBLIC KEY-----"];

NSRange epos = [key rangeOfString:@"-----END PUBLIC KEY-----"];

if(spos.location != NSNotFound && epos.location != NSNotFound){

NSUInteger s = spos.location + spos.length;

NSUInteger e = epos.location;

NSRange range = NSMakeRange(s, e-s);

key = [key substringWithRange:range];

}

key = [key stringByReplacingOccurrencesOfString:@"r" withString:@""];

key = [key stringByReplacingOccurrencesOfString:@"n" withString:@""];

key = [key stringByReplacingOccurrencesOfString:@"t" withString:@""];

key = [key stringByReplacingOccurrencesOfString:@" " withString:@""];

// This will be base64 encoded, decode it.

NSData *data = base64_decode(key);

data = [RSA stripPublicKeyHeader:data];

if(!data){

return nil;

}

//a tag to read/write keychain storage

NSString *tag = @"RSAUtil_PubKey";

NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];

// Delete any old lingering key with the same tag

NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];

[publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];

[publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];

[publicKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];

SecItemDelete((__bridge CFDictionaryRef)publicKey);

// Add persistent version of the key to system keychain

[publicKey setObject:data forKey:(__bridge id)kSecValueData];

[publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)

kSecAttrKeyClass];

[publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)

kSecReturnPersistentRef];

CFTypeRef persistKey = nil;

OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);

if (persistKey != nil){

CFRelease(persistKey);

}

if ((status != noErr) && (status != errSecDuplicateItem)) {

return nil;

}

[publicKey removeObjectForKey:(__bridge id)kSecValueData];

[publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];

[publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];

[publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];

// Now fetch the SecKeyRef version of the key

SecKeyRef keyRef = nil;

status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);

if(status != noErr){

return nil;

}

return keyRef;

}

(SecKeyRef)addPrivateKey:(NSString *)key{

NSRange spos;

NSRange epos;

spos = [key rangeOfString:@"-----BEGIN RSA PRIVATE KEY-----"];

if(spos.length > 0){

epos = [key rangeOfString:@"-----END RSA PRIVATE KEY-----"];

}else{

spos = [key rangeOfString:@"-----BEGIN PRIVATE KEY-----"];

epos = [key rangeOfString:@"-----END PRIVATE KEY-----"];

}

if(spos.location != NSNotFound && epos.location != NSNotFound){

NSUInteger s = spos.location + spos.length;

NSUInteger e = epos.location;

NSRange range = NSMakeRange(s, e-s);

key = [key substringWithRange:range];

}

key = [key stringByReplacingOccurrencesOfString:@"r" withString:@""];

key = [key stringByReplacingOccurrencesOfString:@"n" withString:@""];

key = [key stringByReplacingOccurrencesOfString:@"t" withString:@""];

key = [key stringByReplacingOccurrencesOfString:@" " withString:@""];

// This will be base64 encoded, decode it.

NSData *data = base64_decode(key);

data = [RSA stripPrivateKeyHeader:data];

if(!data){

return nil;

}

//a tag to read/write keychain storage

NSString *tag = @"RSAUtil_PrivKey";

NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];

// Delete any old lingering key with the same tag

NSMutableDictionary *privateKey = [[NSMutableDictionary alloc] init];

[privateKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];

[privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];

[privateKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];

SecItemDelete((__bridge CFDictionaryRef)privateKey);

// Add persistent version of the key to system keychain

[privateKey setObject:data forKey:(__bridge id)kSecValueData];

[privateKey setObject:(__bridge id) kSecAttrKeyClassPrivate forKey:(__bridge id)

kSecAttrKeyClass];

[privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)

kSecReturnPersistentRef];

CFTypeRef persistKey = nil;

OSStatus status = SecItemAdd((__bridge CFDictionaryRef)privateKey, &persistKey);

if (persistKey != nil){

CFRelease(persistKey);

}

if ((status != noErr) && (status != errSecDuplicateItem)) {

return nil;

}

[privateKey removeObjectForKey:(__bridge id)kSecValueData];

[privateKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];

[privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];

[privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];

// Now fetch the SecKeyRef version of the key

SecKeyRef keyRef = nil;

status = SecItemCopyMatching((__bridge CFDictionaryRef)privateKey, (CFTypeRef *)&keyRef);

if(status != noErr){

return nil;

}

return keyRef;

}

/* START: Encryption & Decryption with RSA private key */

(NSData *)encryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{

const uint8_t *srcbuf = (const uint8_t *)[data bytes];

size_t srclen = (size_t)data.length;

size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);

void *outbuf = malloc(block_size);

size_t src_block_size = block_size - 11;

NSMutableData *ret = [[NSMutableData alloc] init];

for(int idx=0; idx //NSLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);

size_t data_len = srclen - idx;

if(data_len > src_block_size){

data_len = src_block_size;

}

size_t outlen = block_size;

OSStatus status = noErr;

status = SecKeyEncrypt(keyRef,

kSecPaddingPKCS1,

srcbuf + idx,

data_len,

outbuf,

&outlen

);

if (status != 0) {

NSLog(@"SecKeyEncrypt fail. Error Code: %d", status);

ret = nil;

break;

}else{

[ret appendBytes:outbuf length:outlen];

}

}

free(outbuf);

CFRelease(keyRef);

return ret;

}

(NSString *)encryptString:(NSString *)str privateKey:(NSString *)privKey{

NSData *data = [RSA encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] privateKey:privKey];

NSString *ret = base64_encode_data(data);

return ret;

}

(NSData *)encryptData:(NSData *)data privateKey:(NSString *)privKey{

if(!data || !privKey){

return nil;

}

SecKeyRef keyRef = [RSA addPrivateKey:privKey];

if(!keyRef){

return nil;

}

return [RSA encryptData:data withKeyRef:keyRef];

}

(NSData *)decryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{

const uint8_t *srcbuf = (const uint8_t *)[data bytes];

size_t srclen = (size_t)data.length;

size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);

UInt8 *outbuf = malloc(block_size);

size_t src_block_size = block_size;

NSMutableData *ret = [[NSMutableData alloc] init];

for(int idx=0; idx //NSLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);

size_t data_len = srclen - idx;

if(data_len > src_block_size){

data_len = src_block_size;

}

size_t outlen = block_size;

OSStatus status = noErr;

status = SecKeyDecrypt(keyRef,

kSecPaddingNone,

srcbuf + idx,

data_len,

outbuf,

&outlen

);

if (status != 0) {

NSLog(@"SecKeyEncrypt fail. Error Code: %d", status);

ret = nil;

break;

}else{

//the actual decrypted data is in the middle, locate it!

int idxFirstZero = -1;

int idxNextZero = (int)outlen;

for ( int i = 0; i < outlen; i++ ) {

if ( outbuf[i] == 0 ) {

if ( idxFirstZero < 0 ) {

idxFirstZero = i;

} else {

idxNextZero = i;

break;

}

}

}

[ret appendBytes:&outbuf[idxFirstZero+1] length:idxNextZero-idxFirstZero-1];

}

}

free(outbuf);

CFRelease(keyRef);

return ret;

}

(NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey{

NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];

data = [RSA decryptData:data privateKey:privKey];

NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

return ret;

}

(NSData *)decryptData:(NSData *)data privateKey:(NSString *)privKey{

if(!data || !privKey){

return nil;

}

SecKeyRef keyRef = [RSA addPrivateKey:privKey];

if(!keyRef){

return nil;

}

return [RSA decryptData:data withKeyRef:keyRef];

}

/* END: Encryption & Decryption with RSA private key */

/* START: Encryption & Decryption with RSA public key */

(NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey{

NSData *data = [RSA encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] publicKey:pubKey];

NSString *ret = base64_encode_data(data);

return ret;

}

(NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey{

if(!data || !pubKey){

return nil;

}

SecKeyRef keyRef = [RSA addPublicKey:pubKey];

if(!keyRef){

return nil;

}

return [RSA encryptData:data withKeyRef:keyRef];

}

(NSString *)decryptString:(NSString *)str publicKey:(NSString *)pubKey{

NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];

data = [RSA decryptData:data publicKey:pubKey];

NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

return ret;

}

(NSData *)decryptData:(NSData *)data publicKey:(NSString *)pubKey{

if(!data || !pubKey){

return nil;

}

SecKeyRef keyRef = [RSA addPublicKey:pubKey];

if(!keyRef){

return nil;

}

return [RSA decryptData:data withKeyRef:keyRef];

}

/* END: Encryption & Decryption with RSA public key */

@end

五、公钥加密Demo

次示例是适用于连个场景,服务器返回一个公钥字符串到iOS客户端,还有一种就是博客园官方接口给的公钥加密~大多数读者找到这里的时候都是因为服务器返回一个公钥字符串如何加密来到这里的吧~下面看demo代码~

一、加载公钥字符窜,本处隐藏,因为保密~

NSString *publicKey = @"YourPublicKey";

二、对账号密码加密~

NSString *name = [RSA encryptString:@"你的账号" publicKey:publicKey];

NSString *password = [RSA encryptString:@"你的密码" publicKey:publicKey];

三、OK,打印出来看看吧~

NSLog(@"%@",name);

NSLog(@"%@",password);

这个Demo很简单~不过在做RSA机密的时候遇到了一个问题,看下面~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: