iOS与后台配合实现—RSA 非对称加解密


 1.生成私钥文件
 $ openssl genrsa -out private.pem 1024
 
 openssl:
是一个自由的软件组织,专注做加密和解密的框架。
 genrsa:
指定了生成了算法使用RSA
 -out:
后面的参数表示生成的key的输入文件
 1024:
表示的是生成key的长度,单位字节(bits)
 
 2.
创建证书请求(按照提示输入信息)接下来就是公司名字,省市,还有名字的一些信息按着给下填就行。
 $ openssl req -new -key private_key.pem -out public_key.csr
 
 3.
可以拿着这个文件去数字证书颁发机构(即CA)申请一个数字证书。CA会给你一个新的文件cacert.pem,那才是你的数字证书。(要收费的)
 
生成证书并签名,有效期10
 $ openssl x509 -req -days 3650 -in public_key.csr -signkey private_key.pem -out public_key.crt
 
 509
是一种非常通用的证书格式。
 4.
将用上面生成的密钥private_key.pempublic_key.csr证书请求文件生成一个数字证书public_key.crt。这个就是公钥
 
转换格式 PEM 格式文件 转换成 DER 格式
 $ openssl x509 -outform der -in public_key.crt -out public_key.der
 
 5.
iOS开发中,公钥是不能使用base64编码的,上面的命令是将公钥的base64编码字符串转换成二进制数据
 
导出 P12 文件
 
 
iOS使用私钥不能直接使用,需要导出一个p12文件。下面命令就是将私钥文件导出为p12文件。
 $ openssl pkcs12 -export -out pkcs.p12 -inkey private_key.pem -in public_key.crt
 

 
iOS中验证证书。把public_key.der拖到xcode中,如果文件没有问题的话,那么就可以直接在xcode中打开,看到证书的各种信息)
 
  //
后台需要
 
根据私钥生成公钥: openssl rsa -in private_key.pem -out public_key.pem -pubout

 
Java(后台)中这时候的私钥还不能直接被使用,需要进行PKCS#8编码:
 openssl pkcs8 -topk8 -in private_key.pem -out pkcs8_private_key.pem -nocrypt


用法示例:
#import"RSA.h"

   //创建加密对象
   
RSA *rsa = [[RSA alloc]init];
   
//要加密的内容
   
NSString *msg = @"i love you";
   
//加载公钥
   
NSString *publicPath = [[NSBundle mainBundle] pathForResource:@"public_key.der" ofType:nil];
    [rsa
extractPublicKeyFromCertificateFilePublicKeyPath:publicPath];
   
//使用公钥加密
   
NSString *result = [rsa encryptToString:msg];
   
NSLog(@"加密 = %@",result);
   
   
   
//解密
   
//加载私钥
   
//密码是导出p12密码
   
NSString *privatePath = [[NSBundle mainBundle] pathForResource:@"pkcs" ofType:@"p12"];
    [rsa
extractEveryThingFromPKCS12FilePkcsPath:privatePath passphrase:@"123456"];
   
//使用私钥解密
   
NSString *result2 = [rsa decryptToString:result];
    NSLog(@"解密 = %@",result2);


RSA======Demo

**********************************RSA.h********************************************************************//
//
//  RSA.h
//  ICFundManager
//
//  Created by magus on 15/12/21.
//  Copyright © 2015 基金组. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface RSA : NSObject {
   
SecKeyRef _publicKey;
   
SecKeyRef _privateKey;
   
SecCertificateRef certificate;
   
SecPolicyRef policy;
   
SecTrustRef trust;
   
size_t maxPlainLen;
}


//证书获取公钥
- (
OSStatus)extractPublicKeyFromCertificateFilePublicKeyPath:(NSString *)publicKeyPath;
//数据加密
- (
NSMutableData *)encryptWithPublicKey:(NSData *)plainData;

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

- (
NSString *) encryptToString:(NSString *)content;



// 获取私钥。--解密
//p12文件中获取私钥 ,密码是你生成私钥的时候生成的
- (
OSStatus)extractEveryThingFromPKCS12FilePkcsPath:(NSString *)pkcsPath passphrase:(NSString *)pkcsPassword;
//数据解密。
- (
NSData *)decryptWithPrivateKey:(NSData *)cipherData;
- (
NSString *)decryptToString:(NSString *)content;
- (
NSData *)decryptWithString:(NSString *)content;

@end


**********************************RSA.m********************************************************************//


//
//  RSA—.m
//  ICFundManager
//
//  Created by magus on 15/12/21.
//  Copyright © 2015 基金组. All rights reserved.
//

#import "RSA.h"

@implementation RSA

/*
 
 http://blog.csdn.net/chaijunkun/article/details/7275632
 
IOS
RSA的加密解密
 1.
生成私钥文件
 $ openssl genrsa -out private.pem 1024
 
 openssl:
是一个自由的软件组织,专注做加密和解密的框架。
 genrsa:
指定了生成了算法使用RSA
 -out:
后面的参数表示生成的key的输入文件
 1024:
表示的是生成key的长度,单位字节(bits)
 
 2.
创建证书请求(按照提示输入信息)接下来就是公司名字,省市,还有名字的一些信息按着给下填就行。
 $ openssl req -new -key private_key.pem -out public_key.csr
 
 3.
可以拿着这个文件去数字证书颁发机构(即CA)申请一个数字证书。CA会给你一个新的文件cacert.pem,那才是你的数字证书。(要收费的)
 
生成证书并签名,有效期10
 $ openssl x509 -req -days 3650 -in public_key.csr -signkey private_key.pem -out public_key.crt
 
 509
是一种非常通用的证书格式。
 4.
将用上面生成的密钥private_key.pempublic_key.csr证书请求文件生成一个数字证书public_key.crt。这个就是公钥
 
转换格式 PEM 格式文件 转换成 DER 格式
 $ openssl x509 -outform der -in public_key.crt -out public_key.der
 
 5.
iOS开发中,公钥是不能使用base64编码的,上面的命令是将公钥的base64编码字符串转换成二进制数据
 
导出 P12 文件
 
 
iOS使用私钥不能直接使用,需要导出一个p12文件。下面命令就是将私钥文件导出为p12文件。
 $ openssl pkcs12 -export -out pkcs.p12 -inkey private_key.pem -in public_key.crt
 

 
iOS中验证证书。把public_key.der拖到xcode中,如果文件没有问题的话,那么就可以直接在xcode中打开,看到证书的各种信息)
 
  //
后台需要
 
根据私钥生成公钥: openssl rsa -in private_key.pem -out public_key.pem -pubout

 
Java(后台)中这时候的私钥还不能直接被使用,需要进行PKCS#8编码:
 openssl pkcs8 -topk8 -in private_key.pem -out pkcs8_private_key.pem -nocrypt

 

*/

- (
id)init{
   
if (self = [super init]) {
    }
   
return self;
}

//4 证书获取公钥
- (
OSStatus)extractPublicKeyFromCertificateFilePublicKeyPath:(NSString *)publicKeyPath {
   
OSStatus status = -1;
   
if (_publicKey == nil) {
       
SecTrustResultType trustResult;
       
NSData *derData = [NSData dataWithContentsOfFile:publicKeyPath];
       
if (derData) {
           
SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)derData);
            
policy = SecPolicyCreateBasicX509();
            status =
SecTrustCreateWithCertificates(cert, policy, &trust);
           
if (status == errSecSuccess && trust) {
               
NSArray *certs = [NSArray arrayWithObject:(id)cert];
                status =
SecTrustSetAnchorCertificates(trust, (CFArrayRef)certs);
               
if (status == errSecSuccess) {
                    status =
SecTrustEvaluate(trust, &trustResult);
                   
// 自签名证书可信
                   
if (status == errSecSuccess && (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed)) {
                       
_publicKey = SecTrustCopyPublicKey(trust);
                       
if (_publicKey) {
                           
NSLog(@"Get public key successfully~ %@", _publicKey);
                             }
                       
if (cert) {
                           
CFRelease(cert);
                                }
                       
if (policy) {
                           
CFRelease(policy);
                                    }
                       
if (trust) {
                           
CFRelease(trust);
                         }
                    }
                }
            }
        }
    }
   
return status;
}



//5. 用公钥对数据加密。
//加密
- (
NSMutableData *)encryptWithPublicKey:(NSData *)plainData {
 
// 分配内存块,用于存放加密后的数据段
 
size_t cipherBufferSize = SecKeyGetBlockSize(_publicKey);
       
uint8_t *cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));
       
double totalLength = [plainData length];
       
size_t blockSize = cipherBufferSize - 12;
       
size_t blockCount = (size_t)ceil(totalLength / blockSize);
       
NSMutableData *encryptedData = [NSMutableData data];
       
// 分段加密
       
for (int i = 0; i < blockCount; i++) {
               
NSUInteger loc = i * blockSize;
               
// 数据段的实际大小。最后一段可能比blockSize小。
               
int dataSegmentRealSize = (int)MIN(blockSize, [plainData length] - loc);
               
// 截取需要加密的数据段
               
NSData *dataSegment = [plainData subdataWithRange:NSMakeRange(loc, dataSegmentRealSize)];
               
OSStatus status = SecKeyEncrypt(_publicKey, kSecPaddingPKCS1, (const uint8_t *)[dataSegment bytes], dataSegmentRealSize, cipherBuffer, &cipherBufferSize);
               
if (status == errSecSuccess) {
                       
NSData *encryptedDataSegment = [[NSData alloc] initWithBytes:(const void *)cipherBuffer length:cipherBufferSize];
                       
// 追加加密后的数据段
                        [encryptedData
appendData:encryptedDataSegment];
                        [encryptedDataSegment
release];
                    }
else {
                           
if (cipherBuffer) {
                                   
free(cipherBuffer);
                                }
                           
return nil;
                        }
            }
       
if (cipherBuffer) {
               
free(cipherBuffer);
            }
   
return encryptedData;
}



//加密
- (
NSData *) encryptWithString:(NSString *)content
{
   
if (content == nil || !content) {
       
return nil;
    }
   
return [self encryptWithPublicKey:[content dataUsingEncoding:NSUTF8StringEncoding]];
}

- (
NSString *) encryptToString:(NSString *)content
{
   
NSData *data = [self encryptWithString:content];
   
//base64编码
//    NSString *base64Encoded = [data base64EncodedStringWithOptions:0];
//    return base64Encoded;
   
return [self base64forData:data];
}

//6. 获取私钥。
//p12文件中获取私钥 ,密码是你生成私钥的时候生成的
- (
OSStatus)extractEveryThingFromPKCS12FilePkcsPath:(NSString *)pkcsPath passphrase:(NSString *)pkcsPassword{
   
SecIdentityRef identity;
   
OSStatus status = -1;
   
if (_privateKey == nil) {
       
NSData *p12Data = [NSData dataWithContentsOfFile:pkcsPath];
       
if (p12Data) {
           
CFStringRef password = (CFStringRef)pkcsPassword;
           
const void *keys[] = {
               
kSecImportExportPassphrase
            };
           
const void *values[] = {
                password
            };
           
CFDictionaryRef options = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 1, NULL, NULL);
           
CFArrayRef items = CFArrayCreate(kCFAllocatorDefault, NULL, 0, NULL);
            status =
SecPKCS12Import((CFDataRef)p12Data, options, &items);
           
if (status == errSecSuccess) {
               
CFDictionaryRef identity_trust_dic = CFArrayGetValueAtIndex(items, 0);
                identity = (
SecIdentityRef)CFDictionaryGetValue(identity_trust_dic, kSecImportItemIdentity);
               
trust = (SecTrustRef)CFDictionaryGetValue(identity_trust_dic, kSecImportItemTrust);
               
// certs数组中包含了所有的证书
               
CFArrayRef certs = (CFArrayRef)CFDictionaryGetValue(identity_trust_dic, kSecImportItemCertChain);
               
if ([(NSArray *)certs count] && trust && identity) {
                   
// 如果没有下面一句,自签名证书的评估信任结果永远是kSecTrustResultRecoverableTrustFailure
                    status =
SecTrustSetAnchorCertificates(trust, certs);
                   
if (status == errSecSuccess) {
                       
SecTrustResultType trustResultType;
                       
// 通常, 返回的trust result type应为kSecTrustResultUnspecified,如果是,就可以说明签名证书是可信的
                        status =
SecTrustEvaluate(trust, &trustResultType);
                       
if ((trustResultType == kSecTrustResultUnspecified || trustResultType == kSecTrustResultProceed) && status == errSecSuccess) {
                           
// 证书可信,可以提取私钥与公钥,然后可以使用公私钥进行加解密操作
                            status =
SecIdentityCopyPrivateKey(identity, &_privateKey);
                           
if (status == errSecSuccess && _privateKey) {
                               
// 成功提取私钥
                               
NSLog(@"Get private key successfully~ %@", _privateKey);
                            }
                        }
                    }
                }
            }
           
if (options) {
               
CFRelease(options);
            }
        }
    }
   
return 0;
}

//7.数据解密。
- (
NSData *)decryptWithPrivateKey:(NSData *)cipherData {
   
// 分配内存块,用于存放解密后的数据段
   
size_t plainBufferSize = SecKeyGetBlockSize(_privateKey);
   
NSLog(@"plainBufferSize = %zd", plainBufferSize);
   
uint8_t *plainBuffer = malloc(plainBufferSize * sizeof(uint8_t));
   
// 计算数据段最大长度及数据段的个数
   
NSLog(@"totalLength = %lu", (unsigned long)[cipherData length]);
   
int totalLength = (int) [cipherData length];
   
NSLog(@"totalLength = %d", totalLength);
   
size_t blockSize = plainBufferSize;
   
size_t blockCount = (size_t)ceil(totalLength / blockSize);
   
NSMutableData *decryptedData = [NSMutableData data];
   
// 分段解密
   
for (int i = 0; i < blockCount; i++) {
       
NSUInteger loc = i * blockSize;
       
// 数据段的实际大小。最后一段可能比blockSize小。
       
int dataSegmentRealSize =(int) MIN(blockSize, totalLength - loc);
       
// 截取需要解密的数据段
       
NSData *dataSegment = [cipherData subdataWithRange:NSMakeRange(loc, dataSegmentRealSize)];
       
OSStatus status = SecKeyDecrypt(_privateKey, kSecPaddingPKCS1, (const uint8_t *)[dataSegment bytes], dataSegmentRealSize, plainBuffer, &plainBufferSize);
       
if (status == errSecSuccess) {
           
NSData *decryptedDataSegment = [[NSData alloc] initWithBytes:(const void *)plainBuffer length:plainBufferSize];
            [decryptedData
appendData:decryptedDataSegment];
            [decryptedDataSegment
release];
        }
else {
           
if (plainBuffer) {
               
free(plainBuffer);
            }
           
return nil;
        }
    }
   
if (plainBuffer) {
       
free(plainBuffer);
    }
   
return decryptedData;
}


- (
NSData *)decryptWithString:(NSString *)content
{
   
NSLog(@"conten = %@",content);
   
if (content == nil || !content) {
       
return nil;
    }
   
//base64解码
   
NSData *dataFromBase64String = [[NSData alloc] initWithBase64EncodedString:content options:0];
   
return [self decryptWithPrivateKey:dataFromBase64String];
}

- (
NSString *)decryptToString:(NSString *)content {
   
NSData *decryptData = [self decryptWithString:content];
   
//NSData  -->NSString
   
NSString *decryptStr = [[NSString alloc] initWithData:decryptData encoding:NSUTF8StringEncoding];
   
return decryptStr;
}


// convert NSData to NSString
- (
NSString *)base64forData:(NSData *)theData {
   
const uint8_t* input = (const uint8_t*)[theData bytes];
   
NSInteger length = [theData length];
   
   
static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
   
   
NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
   
uint8_t* output = (uint8_t*)data.mutableBytes;
   
   
NSInteger i;
   
for (i=0; i < length; i += 3) {
       
NSInteger value = 0;
       
NSInteger j;
       
for (j = i; j < (i + 3); j++) {
            value <<=
8;
           
           
if (j < length) {
                value |= (
0xFF & input[j]);
            }
        }
       
       
NSInteger theIndex = (i / 3) * 4;
        output[theIndex +
0] =                    table[(value >> 18) & 0x3F];
        output[theIndex +
1] =                    table[(value >> 12) & 0x3F];
        output[theIndex +
2] = (i + 1) < length ? table[(value >> 6)  & 0x3F] : '=';
        output[theIndex +
3] = (i + 2) < length ? table[(value >> 0)  & 0x3F] : '=';
    }
   
   
return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
}
/*
NSString *content = @"nihao";
//
系统自带的 NS_AVAILABLE(10_9, 7_0);//base64编码
//NSString -->NSData
NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];
//NSData--base64
编码-->NSString
 NSString *base64Encoded = [data base64EncodedStringWithOptions:0];

 
//base64
解码
NSString
base64编码) --base64解码-->NSData
NSData *data1 = [[NSData alloc] initWithBase64EncodedString:content options:0];
//NSData--->NSString
NSString *deStr = [[NSString alloc] initWithData:data1 encoding:NSUTF8StringEncoding];
*/


/*
用法示例:
//
创建加密对象
RSA *rsa = [[RSA alloc]init];
//
要加密的内容
NSString *msg = @"i love you";
//
加载公钥
NSString *publicPath = [[NSBundle mainBundle] pathForResource:@"public_key.der" ofType:nil];
[rsa extractPublicKeyFromCertificateFilePublicKeyPath:publicPath];
//
使用公钥加密
NSString *result = [rsa encryptToString:msg];
NSLog(@"
加密 = %@",result);


//
解密
//
加载私钥
//
密码是导出p12密码
NSString *privatePath = [[NSBundle mainBundle] pathForResource:@"pkcs" ofType:@"p12"];
[rsa extractEveryThingFromPKCS12FilePkcsPath:privatePath passphrase:@"123456"];
//
使用私钥解密
NSString *result2 = [rsa decryptToString:result];
NSLog(@"
解密 = %@",result2);
 */

@end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值