您的位置:首页 > 其它

天杀 的pfx证书 提取公钥秘钥 加密签名

2015-12-21 16:02 471 查看
项目一开始就入了一个坑

需求是这样的

后台甩给我一个.pfx格式的证书, 有些人就会问了 这个是啥, 我不是大神 就给那些不懂得人 通俗的说一下. 这个东西是一个证书文件, 其中包含 公钥 和 私钥 (一会解释这俩东西是啥), 这个在表面试看不出来的, 你可能会在网上找到很多提取这个东西里公钥私钥的方法 , demo .但是 我想你会在获取公钥的时候遇到问题.,

记住其中提取公钥的方法 一定要是.cer格式的公钥文件 .cer格式的公钥文件 .cer格式的公钥文件 说三遍

这个东西怎么弄呢? 在mac里 的终端可以解决这个问题 (百度 mac openssl 提取 公钥) 就是几行命令行 赋值粘贴就行了,具体的我还是希望你自己去努力调研! 之后在你工程里应该 有两个东西 一个是后台给你的操蛋pfx格式的证书 一个是你用终端提取的.cer的公钥文件

然后就是代码了

#import <Foundation/Foundation.h>
#import <Security/Security.h> //这是一个系统自带的库 别管他好是不好使 弄上去
#import <CommonCrypto/CommonDigest.h> //这是一个系统自带的库
别管他好是不好使 弄上去

@interface PrAndPu : NSObject {

SecKeyRef _privateKey;
SecKeyRef _publicKey;

}

//这个是一会要用的最后你要使用的 公钥 属性
@property (nonatomic, assign) SecKeyRef pubKey;

// 可以从PKCS#12文件中提取身份、信任、证书、公钥、私钥,这里,我们只需要保留私钥
- (OSStatus)extractEveryThingFromPKCS12File:(NSString *)pkcsPath passphrase:(NSString *)pkcsPassword;

// 从证书文件中提取公钥
- (OSStatus)extractPublicKeyFromCertificateFile:(NSString *)certPath;

// RSA公钥加密,支持长数据加密
- (NSData *)encryptWithPublicKey:(NSData *)plainData;

// RSA私钥解密,支持长数据解密
- (NSData *)decryptWithPrivateKey:(NSData *)cipherData;

@end

.m

//获取私钥
- (OSStatus)extractEveryThingFromPKCS12File:(NSString *)pkcsPath passphrase:(NSString *)pkcsPassword {
SecIdentityRef identity;
SecTrustRef trust;
OSStatus status = -1;
if (_privateKey == nil) {
NSData *p12Data = [NSData dataWithContentsOfFile:pkcsPath];
if (p12Data) {
CFStringRef password = (__bridge 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 ([(__bridge 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);
}

//这里,不提取公钥,提取公钥的任务放在extractPublicKeyFromCertificateFile方法中
// _publicKey = SecTrustCopyPublicKey(trust);
// if (_publicKey) {
//
// self.pubKey = (__bridge id)(_publicKey);
//
// }

}
}
}
}
if (options) {
CFRelease(options);
}
}
}
return status;
}

//获取公钥 注意!!!!!!******
只支持 cer
格式的文件 *****
- (OSStatus)extractPublicKeyFromCertificateFile:(NSString *)certPath {

OSStatus status = - 1;

if (_publicKey == nil) {

SecTrustRef trust;
SecTrustResultType trustResult;
NSData *derData = [NSData dataWithContentsOfFile:certPath];
if (derData) {
SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)derData);
SecPolicyRef policy = SecPolicyCreateBasicX509();
status = SecTrustCreateWithCertificates(cert, policy, &trust);
if (status == errSecSuccess && trust) {
NSArray *certs = [NSArray arrayWithObject:(__bridge 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~ ");
self.pubKey = _publicKey; //这个地方可以把提取出来的公钥 传个之前.h里的属性
}
if (cert) {
CFRelease(cert);
}
if (policy) {
CFRelease(policy);
}
if (trust) {
CFRelease(trust);
}
}
}
}
}
}
return status;
}

//公钥加密,因为每次的加密长度有限,所以用到了分段加密,苹果官方文档中提到了分段加密思想。
- (NSData *)encryptWithPublicKey:(NSData *)plainData {

//分配内存块,用于存放加密后的数据段
size_t cipherBufferSize = SecKeyGetBlockSize(_pubKey);
uint8_t *cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));
/*

为什么这里要减12而不是减11?
苹果官方文档给出的说明是,加密时,如果sec padding使用的是kSecPaddingPKCS1,
那么支持的最长加密长度为SecKeyGetBlockSize()-11,

这里说的最长加密长度,我估计是包含了字符串最后的空字符'\0',
因为在实际应用中我们是不考虑'\0'的,所以,支持的真正最长加密长度应为SecKeyGetBlockSize()-12
*/
double totalLength = [plainData length];
size_t blockSize = cipherBufferSize - 12;//使用cipherBufferSize - 11是错误的!
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 = MIN(blockSize, [plainData length] - loc);
//截取需要加密的数据段
NSData *dataSegment = [plainData subdataWithRange:NSMakeRange(loc, dataSegmentRealSize)];
OSStatus status = SecKeyEncrypt(_publicKey,kSecPaddingNone(此处高能预警.估计你找的方法里 这个位置 是
kSecPaddingPKCS1 你最好点进去看看都有哪些东西, 苹果默认的方法是PKCS1但是 我们的后台 他们的默认格式却不是这个 想我的就是PKCS12 所以不同的标准会影响你加密之后传到服务器的东西服务器看不懂 会有乱码 然后告诉你 账号密码错误), (constuint8_t
*)[dataSegment bytes], dataSegmentRealSize, cipherBuffer, &cipherBufferSize);
if (status == errSecSuccess) {
NSData *encryptedDataSegment = [[NSData alloc] initWithBytes:(const void *)cipherBuffer length:cipherBufferSize];
//追加加密后的数据段
[encryptedData appendData:encryptedDataSegment];

} else {
if (cipherBuffer) {
free(cipherBuffer);
}
return nil;
}
}
if (cipherBuffer) {
free(cipherBuffer);
}
return encryptedData;
}

//私钥解密,用到分段解密。
- (NSData *)decryptWithPrivateKey:(NSData *)cipherData {

//分配内存块,用于存放解密后的数据段
size_t plainBufferSize = SecKeyGetBlockSize(_privateKey);
NSLog(@"plainBufferSize = %zd", plainBufferSize);
uint8_t *plainBuffer = malloc(plainBufferSize * sizeof(uint8_t));

//计算数据段最大长度及数据段的个数
double totalLength = [cipherData length];
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 = MIN(blockSize, totalLength - loc);
//截取需要解密的数据段
NSData *dataSegment = [cipherData subdataWithRange:NSMakeRange(loc, dataSegmentRealSize)];
OSStatus status = SecKeyDecrypt(_privateKey,kSecPaddingNone(解密也是一样的), (constuint8_t
*)[dataSegment bytes], dataSegmentRealSize, plainBuffer, &plainBufferSize);
if (status == errSecSuccess) {
NSData *decryptedDataSegment = [[NSData alloc] initWithBytes:(const void *)plainBuffer length:plainBufferSize];
[decryptedData appendData:decryptedDataSegment];
} else {
if (plainBuffer) {
free(plainBuffer);
}
return nil;
}
}
if (plainBuffer) {
free(plainBuffer);
}
return decryptedData;
}

鄙人不才 以上的方法我也几乎看不懂也是网上的大神写的只不过 有些东西对于一些特定情况 不一定会使用, 毕竟人家只是给你铺好路, 怎么走还是要自己想的.

说说怎么实现吧 引头文件什么的我就不说了
我写的是一个登录的流程 只是一个大概 看看就好

//如果没做过登录的可能 一听什么两次握手 我你妈比啊?@!@#!@# 不要紧 其实很简单

第一次握手其实就是 第一次访问服务器, 你的app在点击登录的一刹那 会对服务器进行两次访问, 而服务器也会返回给你两回数据 往下慢慢看吧

// *****************第一次请求 GET
请求 ************************

NSString *url = @"http://192.168.188.137/api/Account/HitMessage";

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

[manager GET:url parameters:nil success:^(NSURLSessionDataTask *task, id responseObject) {

//这个地方 我家的服务器 会返回 一个 字典 { hit : 6位的随机数,
requste:(一大长串的字符串 一会 进行第二次访问的时候 要用)}

NSString *hit = [NSString stringWithFormat:@"%@", [responseObject valueForKey:@"hit"]];

// NSLog(@"%@", hit);

NSString *requset = [NSString stringWithFormat:@"%@", [responseObject valueForKey:@"request"]];

//第二吃访问的链接
NSString *url2 = [NSString stringWithFormat:@"http://192.168.188.137/api/Account/Login/%@/1", requset(这个就是第一次访问服务器返回的requset)];

//之前的工具类
PrAndPu *tool = [[PrAndPu alloc] init];

//获得公钥
[tool extractPublicKeyFromCertificateFile:@"/Users/cloudfit/cloudfitb_ios/CloudSports/CloudSports/pubKey证书.cer”];(格式别弄错了
公钥文件)

//获取私钥(这是另一个的请无视...... 直接用那个方法就行)
SecKeyRef privateKey =[DJZSafeTool getPrivateKey];

//私钥签名(这一步很关键了, 首先你要吧你第一次访问服务器 返回给你的验证码 进行私钥加签(其实也可以说是加密) 这么做的原因是
你在网上约到了一个 py 见面的时候需要对暗号, 你的把你想表达的意思 用你们约定好的好表达出来, 你的py听见了 心里想: 哦 原来那个人就是你呀 .所以首先你就已经成功了一半了, 就是说你最起码通过了服务器的认证证明他之前确实联系过你
// NSLog(@"%@", hit);
//私钥加签之后的字符串
NSString *HitMess = [DJZSafeTool signTheDataSHA1WithRSA:hit privateKey:privateKey];

//我猜通常可能一般 你们后台会让你们 把 设备id 账号 密码 用你们的方法拼接起来然后 公钥加密 第二次握手的时候 传上去
//获取 UUID
(获取设备 ID)
APPIdentificationManager * identificationManager = [[APPIdentificationManager alloc] init];
NSString * uuid = [identificationManager readUDID];

//账号 测试的时候 一定要确定你的账号密码是对的 如果真是你们后台的问题别干打自己脸的事
NSString *userId = @"su#001025";
//密码
NSString *usePassWord = @"123456";

//拼接
NSString *tokens = [NSString stringWithFormat:@"%@&%@&%@", userId, usePassWord, uuid];

// NSString转换 NSData(这俩玩意可以互转的)
NSData * tokenData = [tokens dataUsingEncoding:NSUTF8StringEncoding];

//
公钥加密 (公钥加密的原理就是 你和你的 py对完见面时确认彼此的暗号了 就要商量 去哪家宾馆的 几零几 但是你们不能就这么说 万一让你媳妇或者老公发现了就完了, 所以 你需要把你们要去的 地址门牌号用另一种方式说出来 ,就是公钥加密了)
NSData *da = [tool encryptWithPublicKey:tokenData];

//这里 你可能会在网上看到什么GTMBase64de 东东 我告诉你 没有用因为那是 上古的方法 7.0以后 系统自带了

//这个东西就是一会你要上传的数据...之一
NSString * Token = [da base64EncodedStringWithOptions:0];

// NSLog(@"base64 == %@", Token);

#warning测试用!!!(其实这个并没有什么卵用, 有可能会让你打自己脸,当你气冲冲的 和别人说, 这回登录的问题 不是你的问题,,,,,其实可能就是你的问题,
因为你在你自己家里加密解密都是有自己的一套标准的 所以你会觉得没问题...别干那种傻事, 仔细看看你传到后台的东西 服务器解密之后是什么鬼..当然这还是一个判断你的公钥加密是否有问题的好方法)
// //私钥
解密
NSData *tokenPrivate = [DJZSafeTool rsaDecryptWithData:da usingKey:privateKey];

NSString *tokenPrivateStr = [[NSString alloc] initWithData:tokenPrivate encoding:NSUTF8StringEncoding];

NSLog(@"++++++++++++++测试:私钥解密后的结果是————:%@",tokenPrivateStr);

#pragma mark —第二次握手 //第二次上床…不..是握手 就是你已经和你的py对完见面确认是不是彼此的安好了 也说好哪家宾馆的那个房间了
就要去ppppp了;
//其实就是在你第一次获取网络数据成功之后在访问以下服务器, 只不过这回事post因为你要传参数到服务器
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

//参数
(私钥加签之后的字符串)
// NSLog(@"hitmess=== %@", [NSString stringWithFormat:@"%@", HitMess]);
(公钥加密的 设备id 账号密码 拼接的字符串)
// NSLog(@"token === %@", [NSString stringWithFormat:@"%@", Token]);
//几乎都是传一个字典上去
NSDictionary *parameters = @{@"HitMess" : HitMess,
@"Token" : Token};

[manager POST:url2 parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject) {

NSLog(@"%@", responseObject);

//进入用户首页 开始 pppppp
UserHomePageViewController *userHomeVc = [[UserHomePageViewController alloc] init];
[self.navigationController pushViewController:userHomeVc animated:YES];

} failure:^(NSURLSessionDataTask *task, NSError *error) {

}];

} failure:^(NSURLSessionDataTask *task, NSError *error) {

}];;

算了DJL也放上去吧

#import <Foundation/Foundation.h>
//pfx文件名
#define PFX_NAME @"cloudfit_debug"
@interface DJZSafeTool : NSObject
/**
* SHA1加密
*
* @param plainText
加密前data
*
* @return
加密后data
*/
+ (NSData *)getHashBytes:(NSData *)plainText;
/**
*
从pfx或p12文件中获取公钥
*
* @return
公钥
*/
+ (SecKeyRef)getPublicKey;
/**

*
从pfx文件中获取私钥
*
* @return
私钥
*/
+ (SecKeyRef)getPrivateKey;
/**

*
使用公钥加密
*
* @param data
加密前data
* @param key
公钥
*
* @return
加密后data
*/
+ (NSData*)rsaEncryptWithData:(NSData*)data usingKey:(SecKeyRef)key;
/**
*
私钥解密
*
* @param data
解密前data
* @param key
私钥
*
* @return
解密后data
*/
+ (NSData*)rsaDecryptWithData:(NSData*)data usingKey:(SecKeyRef)key;
/**

*
私钥对字符串数字签名
*
* @param plainText
密码
* @param privateKeyRef
私钥
*
* @return
签名后字符串
*/
+ (NSString *)signTheDataSHA1WithRSA:(NSString *)plainText privateKey:(SecKeyRef)privateKeyRef;

- (NSData *)getHashBytes:(NSData *)plainText;
- (NSString *)signTheDataSHA1WithRSA:(NSString *)plainText;

}

#import "DJZSafeTool.h"
#import <Security/Security.h>
#import "GTMBase64.h"
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>
static NSString * const publicString = @"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAteoLIiNA2bfQu5pMrRsP9Hfwbr8FouWVwj0pG4akT0OFQkjKPDVC5GGNxE3OjpO4Y8Cr7aJLQxZtvJBEaDh2uOEdSHj5MRwnmWpv2VvJ2s42wsABGEQbx26baHNZmLXsH6Ad/JIx0Ow3cgBxLACWBuasd/V7C3/CysxyXg1KpIZYF1Fepo47HxWWDVYsdXaqIyuorabz2stJgqExOuLC5FchzYOn+nSlADwN43nV4VBWVnVRCr6SKccHCUjm7Wn6YCxatPluX49Be78ScxEF/PtpNuNItYqCryBY462flLCe9tLRnOg8QxjRyix1gPs/t1r+pJkKwXObQvHfiw3u/wIDAQAB";

#define kChosenDigestLength CC_SHA1_DIGEST_LENGTH // SHA-1消息摘要的数据位数160位

@implementation DJZSafeTool
#pragma mark -
获取公钥
+ (SecKeyRef)getPublicKey
{

SecCertificateRef myCertificate = nil;

NSString *path = [[NSBundle mainBundle] pathForResource: @"pubKey证书" ofType:@"cer"];
//NSLog(@"%@", path);
NSData *certificateData = [NSData dataWithContentsOfFile:path];

NSString *str = [GTMBase64 encodeBase64Data:certificateData];

// NSData *pubData = [GTMBase64 decodeString:publicString];
// NSString *str = [[NSString alloc] initWithData:certificateData encoding:NSUTF8StringEncoding];
// NSRange startRange = [str rangeOfString:@"-----BEGIN PUBLIC KEY-----\n"];
// str = [str stringByReplacingCharactersInRange:startRange withString:@""];
// NSRange endRange = [str rangeOfString:@"-----END PUBLIC KEY-----\n"];
// str = [str stringByReplacingCharactersInRange:endRange withString:@""];
// NSLog(@"%@", str);
// NSData *data = [GTMBase64 decodeData:certificateData];

myCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certificateData);
NSLog(@"%@", myCertificate);

if (myCertificate == nil) {
NSLog(@"获取公钥失败");
return nil;
}
SecPolicyRef myPolicy = SecPolicyCreateBasicX509();
SecTrustRef myTrust;
OSStatus status = SecTrustCreateWithCertificates(myCertificate,myPolicy,&myTrust);
SecTrustResultType trustResult;
if (status == noErr) {
status = SecTrustEvaluate(myTrust, &trustResult);
}

return SecTrustCopyPublicKey(trustResult);

}

#pragma mark -
获取私钥
+ (SecKeyRef)getPrivateKey
{
NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:PFX_NAME ofType:@"pfx"];
NSData *pfxkeyData = [[NSData alloc]initWithContentsOfFile:publicKeyPath];

NSMutableDictionary * options = [[NSMutableDictionary alloc] init];
[options setObject:@"123456" forKey:(__bridge id)kSecImportExportPassphrase];

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

OSStatus securityError = SecPKCS12Import((__bridge CFDataRef) pfxkeyData,
(__bridge CFDictionaryRef)options, &items);

CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
SecIdentityRef identityApp =
(SecIdentityRef)CFDictionaryGetValue(identityDict,
kSecImportItemIdentity);

assert(securityError == noErr);
SecKeyRef privateKeyRef;
SecIdentityCopyPrivateKey(identityApp, &privateKeyRef);

// NSLog(@"私钥%@", privateKeyRef);

return privateKeyRef;

}
#pragma mark -
公钥加密
+ (NSData*)rsaEncryptWithData:(NSData*)data usingKey:(SecKeyRef)key {

size_t cipherBufferSize = SecKeyGetBlockSize(key);
uint8_t *cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));
memset((void *)cipherBuffer, 0*0, cipherBufferSize);

NSData *plainTextBytes = data;
size_t blockSize = cipherBufferSize - 11;
size_t blockCount = (size_t)ceil([plainTextBytes length] / (double)blockSize);
NSMutableData *encryptedData = [NSMutableData dataWithCapacity:0];

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

int bufferSize = MIN(blockSize,[plainTextBytes length] - i * blockSize);
NSData *buffer = [plainTextBytes subdataWithRange:NSMakeRange(i * blockSize, bufferSize)];

OSStatus status = SecKeyEncrypt(key,
kSecPaddingPKCS1,
(const uint8_t *)[buffer bytes],
[buffer length],
cipherBuffer,
&cipherBufferSize);

if (status == noErr){
NSData *encryptedBytes = [NSData dataWithBytes:(const void *)cipherBuffer length:cipherBufferSize];
[encryptedData appendData:encryptedBytes];

}else{

if (cipherBuffer) {
free(cipherBuffer);
}
return nil;
}
}
if (cipherBuffer) free(cipherBuffer);
return encryptedData;

}
#pragma mark -
私钥解密

//私钥解密:
+ (NSData*)rsaDecryptWithData:(NSData*)data usingKey:(SecKeyRef)key {
NSData *wrappedSymmetricKey = data;

size_t cipherBufferSize = SecKeyGetBlockSize(key);
size_t keyBufferSize = [wrappedSymmetricKey length];

NSMutableData *bits = [NSMutableData dataWithLength:keyBufferSize];
OSStatus sanityCheck = SecKeyDecrypt(key,
kSecPaddingNone,
(const uint8_t *) [wrappedSymmetricKey bytes],
cipherBufferSize,
[bits mutableBytes],
&keyBufferSize);
NSAssert(sanityCheck == noErr, @"Error decrypting, OSStatus == %d.", (int)sanityCheck);

[bits setLength:keyBufferSize];

return bits;

}
#pragma mark -
私钥加签
+ (NSString *)signTheDataSHA1WithRSA:(NSString *)plainText privateKey:(SecKeyRef)privateKeyRef
{
uint8_t* signedBytes = NULL;
size_t signedBytesSize = 0;
OSStatus sanityCheck = noErr;
NSData* signedHash = nil;

signedBytesSize = SecKeyGetBlockSize(privateKeyRef);

NSData *plainTextBytes = [plainText dataUsingEncoding:NSUTF8StringEncoding];

signedBytes = malloc( signedBytesSize * sizeof(uint8_t) ); //分配一个缓冲区来保存签名

memset((void *)signedBytes, 0x0, signedBytesSize);

sanityCheck = SecKeyRawSign(privateKeyRef,
kSecPaddingPKCS1SHA1,
(const uint8_t *)[[self getHashBytes:plainTextBytes] bytes],
kChosenDigestLength,
(uint8_t *)signedBytes,
&signedBytesSize);
// NSLog(@"sanityCheck%d", (int)sanityCheck);

if (sanityCheck == errSecSuccess)
{
signedHash = [NSData dataWithBytes:(const void *)signedBytes length:(NSUInteger)signedBytesSize];

}else{

NSLog(@"【error!!】 err code:%d", (int)sanityCheck);
return nil;
}

if (signedBytes)
{
free(signedBytes);
}

NSString *signatureResult=[NSString stringWithFormat:@"%@",[GTMBase64 encodeBase64Data:signedHash]];
return signatureResult;
}

-(NSString *)signTheDataSHA1WithRSA:(NSString *)plainText
{
uint8_t* signedBytes = NULL;
size_t signedBytesSize = 0;
OSStatus sanityCheck = noErr;
NSData* signedHash = nil;

NSString * path = [[NSBundle mainBundle]pathForResource:@"cloudfit_debug" ofType:@"pfx"];
NSData * data = [NSData dataWithContentsOfFile:path];
NSMutableDictionary * options = [[NSMutableDictionary alloc] init]; // Set the private key query dictionary.
[options setObject:@"123456" forKey:(id)kSecImportExportPassphrase];
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
OSStatus securityError = SecPKCS12Import((CFDataRef) data, (CFDictionaryRef)options, &items);
if (securityError!=noErr) {
return nil ;
}
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
SecIdentityRef identityApp =(SecIdentityRef)CFDictionaryGetValue(identityDict,kSecImportItemIdentity);
SecKeyRef privateKeyRef=nil;
SecIdentityCopyPrivateKey(identityApp, &privateKeyRef);
signedBytesSize = SecKeyGetBlockSize(privateKeyRef);

NSData *plainTextBytes = [plainText dataUsingEncoding:NSUTF8StringEncoding];

signedBytes = malloc( signedBytesSize * sizeof(uint8_t) ); // Malloc a buffer to hold signature.
memset((void *)signedBytes, 0x0, signedBytesSize);

sanityCheck = SecKeyRawSign(privateKeyRef,
kSecPaddingPKCS1SHA1,
(const uint8_t *)[[self getHashBytes:plainTextBytes] bytes],
kChosenDigestLength,
(uint8_t *)signedBytes,
&signedBytesSize);

if (sanityCheck == noErr)
{
signedHash = [NSData dataWithBytes:(const void *)signedBytes length:(NSUInteger)signedBytesSize];
}
else
{
return nil;
}

if (signedBytes)
{
free(signedBytes);
}
// NSLog(@"signedHash == %@", signedHash);

NSString *signatureResult=[NSString stringWithFormat:@"%@",[GTMBase64 encodeBase64Data:signedHash]];
// NSLog(@"签名之后%@", signatureResult);
return signatureResult;
}

- (NSData *)getHashBytes:(NSData *)plainText {
CC_SHA1_CTX ctx;
uint8_t * hashBytes = NULL;
NSData * hash = nil;

// Malloc a buffer to hold hash.
hashBytes = malloc( kChosenDigestLength * sizeof(uint8_t) );
memset((void *)hashBytes, 0x0, kChosenDigestLength);
// Initialize the context.
CC_SHA1_Init(&ctx);
// Perform the hash.
CC_SHA1_Update(&ctx, (void *)[plainText bytes], [plainText length]);
// Finalize the output.
CC_SHA1_Final(hashBytes, &ctx);

// Build up the SHA1 blob.
hash = [NSData dataWithBytes:(const void *)hashBytes length:(NSUInteger)kChosenDigestLength];
if (hashBytes) free(hashBytes);

return hash;
}

#pragma mark - SHA1
+ (NSData *)getHashBytes:(NSData *)plainText {
CC_SHA1_CTX ctx;
uint8_t * hashBytes = NULL;
NSData * hash = nil;

// Malloc a buffer to hold hash.
hashBytes = malloc( kChosenDigestLength * sizeof(uint8_t) );
memset((void *)hashBytes, 0x0, kChosenDigestLength);
// Initialize the context.
CC_SHA1_Init(&ctx);
// Perform the hash.
CC_SHA1_Update(&ctx, (void *)[plainText bytes], [plainText length]);
// Finalize the output.
CC_SHA1_Final(hashBytes, &ctx);

// Build up the SHA1 blob.
hash = [NSData dataWithBytes:(const void *)hashBytes length:(NSUInteger)kChosenDigestLength];
if (hashBytes) free(hashBytes);

return hash;

}

都是一个参考 加油吧骚年
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: