当前位置: 首页 > news >正文

如何加载私钥为 SecKeyRef

本文介绍如何在 iOS/macOS 下将私钥加载为 SecKeyRef,涵盖 PEM 格式的 ECC 密钥读取、X9.63 数据构建、以及与 Keychain 的集成。


1. 使用 SecKeyCreateWithData 加载私钥

Apple 提供的 SecKeyCreateWithData 方法可以直接将密钥数据加载为 SecKeyRef 对象。

SecKeyRef SecKeyCreateWithData(CFDataRef keyData, CFDictionaryRef attributes, CFErrorRef  _Nullable *error);

文档:SecKeyCreateWithData(::_😃 | Apple Developer Documentation

attributes 必须包含如下 key

  • kSecAttrKeyType:密钥类型,如 ECC、RSA
  • kSecAttrKeyClass:密钥类(公钥/私钥)

keyData 的数据格式

  • ECC 私钥数据应采用 X9.63 格式。
  • RSA 私钥应为 PKCS #1 格式。

详见:SecKeyCopyExternalRepresentation(:😃 | Apple Developer Documentation

X9.63 格式说明

  • ECC 公钥:04 || X || Y
  • ECC 私钥:04 || X || Y || K
    其中 X、Y 为公钥坐标,K 为大端序编码的私钥值,所有字段均为定长,必要时补零。

构建 X9.63 可参考:将加密工具包密钥存储在钥匙串 | 苹果开发者文档


2. PEM 格式转换与读取

2.1 PEM 转 P256

如果你有 PEM 编码的 P256 私钥,可用 CryptoKit 直接解析为 P256 私钥对象:

文档:init(pemRepresentation:) | Apple Developer Documentation

2.2 读取 ECC PEM 密钥为 SecKey

示例代码(Swift):

/// 加载 PEM 证书为 SecKey
/// - Parameter name: PEM 文件名(不含扩展名)
/// - Returns: SecKey 类型值
class func loadECCSecKeyFromPem(_ name: String) -> SecKey? {guard let pemURL = Bundle.main.url(forResource: name, withExtension: "pem") else {return nil}do {let pemStr = try String(contentsOf: pemURL)let p256 = try P256.Signing.PrivateKey(pemRepresentation: pemStr)let attributes: [String: Any] = [kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,kSecAttrKeyClass as String: kSecAttrKeyClassPrivate]// kSecAttrIsPermanent 是否需要存储,默认不存储guard let secKey = SecKeyCreateWithData(p256.x963Representation as CFData,attributes as CFDictionary,nil)else {return nil}return secKey} catch {print(error)return nil}
}

如果需要将 PEM 转换为 X9.63,可先用 CryptoKit 读取后再取其 x963Representation 字节。


3. iOS 端创建 ECC 私钥并存储到 Keychain

如需新建私钥并写入钥匙串,可参考如下 Objective-C 代码:

+ (NSDictionary *)privateKeyParams {return @{(__bridge NSString *) kSecClass : (__bridge NSString *) kSecClassKey,(__bridge NSString *) kSecAttrApplicationLabel : MTRCAKeyChainLabel,// 存入钥匙串时,按需设置属性(__bridge NSString *) kSecAttrKeyClass : (__bridge NSString *) kSecAttrKeyClassSymmetric,};
}
+ (NSDictionary *)privateKeyCreationParams {// 按需设置密钥长度const size_t keySizeInBits = 256;return @{(__bridge NSString *) kSecAttrKeyClass : (__bridge NSString *) kSecAttrKeyClassPrivate,(__bridge NSString *) kSecAttrKeyType : (__bridge NSNumber *) kSecAttrKeyTypeECSECPrimeRandom,(__bridge NSString *) kSecAttrKeySizeInBits : @(keySizeInBits),(__bridge NSString *) kSecAttrIsPermanent : @(NO), // 是否永久保存};
}
/// 创建并存储 ECC 私钥
+ (SecKeyRef)generateCAPrivateKey {NSMutableDictionary *query = [[NSMutableDictionary alloc] initWithDictionary:[MSMatterFabricKeys privateKeyParams]];// 先删除旧密钥,防止添加失败SecItemDelete((__bridge CFDictionaryRef) query);CFErrorRef error = NULL;SecKeyRef key = SecKeyCreateRandomKey((__bridge CFDictionaryRef)[MSMatterFabricKeys privateKeyCreationParams], &error);if (error) {NSLog(@"Could not generate private key: %@", (__bridge NSError *) error);return NULL;}NSData *keyData = (__bridge_transfer NSData *) SecKeyCopyExternalRepresentation(key, &error);if (error) {NSLog(@"Could not get key external representation: %@", (__bridge NSError *) error);CFRelease(key);return NULL;}query[(__bridge NSString *) kSecValueData] = [keyData base64EncodedDataWithOptions:0];OSStatus status = SecItemAdd((__bridge CFDictionaryRef) query, NULL);if (status != errSecSuccess) {NSLog(@"Failed to store private key : %d", status);CFRelease(key);return NULL;}return key;
}

4. 证书直接读取

如需直接读取证书内容,可参考:证书读取方法(CSDN)


5. 相关资源

  • SecKeyCreateWithData | Apple Developer Documentation
  • SecKeyCopyExternalRepresentation | Apple Developer Documentation
  • 将加密工具包密钥存储在钥匙串 | Apple Developer Documentation
  • PEM 转 P256 | Apple Developer Documentation
  • 证书读取方法(CSDN)

http://www.xdnf.cn/news/685207.html

相关文章:

  • Word表格怎样插入自动序号或编号
  • AMBA总线家族成员
  • 基于FPGA的DES加解密系统verilog实现,包含testbench和开发板硬件测试
  • c++设计模式-单例模式
  • 数据类型(基本类型下半)day3
  • 智警杯备赛--数据库管理与优化
  • [神经网络]使用olivettiface数据集进行训练并优化,观察对比loss结果
  • LINUX528 重定向
  • Git使用手册保姆级教程
  • 【Python办公】Excel简易透视办公小工具
  • EasyExcel使用导出模版后设置 CellStyle失效问题解决
  • python完成批量复制Excel文件并根据另一个Excel文件中的名称重命名
  • C++之string题目练习
  • jQuery和CSS3卡片列表布局特效
  • tauri2项目打开某个文件夹,类似于mac系统中的 open ./
  • mybatis的mapper对应的xml写法
  • 【技术测评】黑龙江亿林网络「启强 Plus」服务器实测:56 核 32G 配置下的性能表现与应用场景解析
  • BEVDepth- Acquisition of Reliable Depth for Multi-view 3D Object Detection
  • [蓝桥杯C++ 2024 国 B ] 立定跳远(二分)
  • [Hackers and Painters] 读书笔记 | 设计模式思想 | LISP
  • 设计模式-装饰模式
  • 机器学习中无监督学习方法的聚类:划分式聚类、层次聚类、密度聚类
  • Python爬虫第22节- 结合Selenium识别滑动验证码实战
  • Java设计模式之设计原则
  • 莫毅明和钟家庆数学命题证明使用的预期理由和或然推理的错误
  • 使用JAVA 语言中 JNA 和 PDU 的区别
  • 深兰科技陈海波率队考察南京,加速AI医诊大模型区域落地应用
  • Python爬虫(40)基于Selenium与ScrapyRT构建高并发动态网页爬虫架构:原理、实现与性能优化
  • vscode 配置 QtCreat Cmake项目
  • 文件上传绕过方法总结