什么是pfx

公钥加密技术12号标准。

公钥加密技术12号标准(Public Key Cryptography Standards #12,PKCS#12)为存储和传输用户或服务器私钥、公钥和证书指定了一个可移植的格式。它是一种二进制格式,这些文件也称为PFX文件。开发人员通常需要将PFX文件转换为某些不同的格式,如PEM或JKS,以便可以为使用SSL通信的独立Java客户端或WebLogic Server使用。

下面是pfx证书提取公私钥的步骤

//

//  PrAndPu.h

//  PFX

//

//  Created by cloudfit on 15/12/12.

//  Copyright © 2015年 cloudfit. All rights reserved.

//

#import

#import

#import

@interface PrAndPu : NSObject {

SecKeyRef _privateKey;

SecKeyRef _publicKey;

}

// 可以从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

//

//  PrAndPu.m

//  PFX

//

//  Created by cloudfit on 15/12/12.

//  Copyright © 2015年 cloudfit. All rights reserved.

//

#import “PrAndPu.h”

@implementation PrAndPu

//获取私钥

– (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) {

//获取公钥

NSLog(@”Get public key successfully~ %@”, _publicKey);

}

}

}

}

}

if (options) {

CFRelease(options);

}

}

}

return status;

}

//获取公钥

– (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~ %@”, _publicKey);

}

if (cert) {

CFRelease(cert);

}

if (policy) {

CFRelease(policy);

}

if (trust) {

CFRelease(trust);

}

}

}

}

}

}

return status;

}

//公钥加密,因为每次的加密长度有限,所以用到了分段加密,苹果官方文档中提到了分段加密思想。

– (NSData *)encryptWithPublicKey:(NSData *)plainData {

// 分配内存块,用于存放加密后的数据段

size_t cipherBufferSize = SecKeyGetBlockSize(_publicKey);

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, 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];

} 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, 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];

} else {

if (plainBuffer) {

free(plainBuffer);

}

return nil;

}

}

if (plainBuffer) {

free(plainBuffer);

}

return decryptedData;

}

@end

java pfx提取私钥加签,详解pfx证书提取公私钥的方法相关推荐

  1. 银行接口的私钥和公钥详解

    银行接口的私钥和公钥详解 中国银行.建设银行.农业银行.工商银行.招商银行等支付接口的私钥和公钥详解 密钥: 我理解是公钥+私钥的统称. 密钥对: 公钥(证书)和私钥成对存在. 通信双方各持有自己的私 ...

  2. python正则表达式提取数字比较好_python正则表达式从字符串中提取数字的思路详解...

    python从字符串中提取数字 使用正则表达式,用法如下: ## 总结 ## ^ 匹配字符串的开始. ## $ 匹配字符串的结尾. ## \b 匹配一个单词的边界. ## \d 匹配任意数字. ## ...

  3. java string()函数_转载java String.split()函数的用法详解

    转载java String.split()函数的用法详解 如果您发现本文排版有问题,可以先点击下面的链接切换至老版进行查看!!!在java.lang包中有String.split()方法的原型是: p ...

  4. 2015年 第06届 蓝桥杯 Java B组 决赛真题详解及小结

    蓝桥杯 Java B组 省赛决赛 真题详解及小结汇总[2013年(第4届)~2020年(第11届)] 第11届 蓝桥杯-第1.2次模拟(软件类)真题-(2020年3月.4月)-官方讲解视频 说明:大部 ...

  5. 2017年 第08届 蓝桥杯 Java B组 决赛真题详解及小结

    ​​​​​蓝桥杯 Java B组 省赛决赛 真题详解及小结汇总[2013年(第4届)~2020年(第11届)] 第11届 蓝桥杯-第1.2次模拟(软件类)真题-(2020年3月.4月)-官方讲解视频 ...

  6. (7)Java数据结构--集合map,set,list详解

    MAP,SET,LIST,等JAVA中集合解析(了解) - clam_clam的专栏 - CSDN博---有颜色, http://blog.csdn.net/clam_clam/article/det ...

  7. Java(enum)枚举用法详解

    转载自 Java(enum)枚举用法详解 本篇文章主要介绍了Java 枚举用法详解,枚举的好处:可以将常量组织起来,统一进行管理.有兴趣的可以一起来了解一下. 概念 enum的全称为 enumerat ...

  8. 【转】Java魔法堂:String.format详解

    Java魔法堂:String.format详解   目录     一.前言     二.重载方法     三.占位符     四.对字符.字符串进行格式化     五.对整数进行格式化     六.对 ...

  9. java学习 类变量 类方法_这篇文章主要介绍了JAVA类变量及类方法代码实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下类变量(...

    这篇文章主要介绍了JAVA类变量及类方法代码实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 类变量(static) 类变量是该类的所有对象共 ...

最新文章

  1. VSTS LoadTest使用原则
  2. 区块链系列4-智能合约
  3. 又一理论横空出现或将颠覆世界
  4. scikit-learn kmeans++
  5. day41——多进程的消息队列、消息队列pipe
  6. statCVS的问题剖析
  7. Java网络爬虫实操(8)
  8. 牛客网【每日一题】4月17日题目精讲 华华给月月准备礼物
  9. Ubuntu16.04下Nvidia+Cuda8.0+Dynet安装教程
  10. C++自增和自减运算符(--和++)
  11. win8需要计算机管理员权限才能删除,win8系统使用管理员权限无法删除部分文件怎么办...
  12. 用友u8服务器修改ipv4,用友U8-OA11.1 用友U8加密狗更换服务器了-用友U8
  13. 继续逼近FLASH效果
  14. Android MTU 值修改
  15. 【奥黛丽赫本】女神一样的优雅
  16. jme-旋转的双子星
  17. 给一个IP地址,如何划分为几个子网?
  18. 把一个用阿拉伯数字表示的正整数转换成汉字大写表示
  19. 服务器的创意工坊文件,Steam 创意工坊实现指南
  20. Asset Store上常用的40个Unity插件汇总——进阶开发者必备Unity插件

热门文章

  1. Potted Flower(线段树+dp)
  2. JAVA 即时网络通信我的服务器
  3. 尝试从远程计算机访问Web服务不显示调用按钮
  4. 如何解决markdown中图片上传的问题
  5. 从程序员角度--解决ipad白苹果问题的最佳办法---纠正网上的错误言论
  6. JDBC的批量查询报告内存溢出解决方法
  7. 基于深度学习的个性化新闻推荐.pdf(附下载链接)
  8. 全球首发!计算机视觉Polygon Mesh Processing总结7——Remeshing Local Structure
  9. 用python写行列式_用Python开发线性代数算法(一) | 手写行列式算法的实现
  10. 吉林大学计算机专业宿舍研究生,吉林大学计算机系的研究生宿舍怎么样?我想考那的..._在职考研_帮考网...