如何加载私钥为 SecKeyRef

news2025/6/4 7:44:46

本文介绍如何在 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.coloradmin.cn/o/2396125.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

el-tree拖拽事件,限制同级拖拽,获取拖拽后节点的前后节点,同级拖拽合并父节点name且子节点加入目标节点里

node-drag-start:开始拖拽节点时触发​​(按下鼠标按钮),无论是否允许放置,此事件都会触发。 allow-drop 返回 true 才能触发@node-drag-end="handleDragend"、@node-drop="handleDrop"; (1)allow-drop:动态控制​​是否允许放置; (2)node-dr…

day62—DFS—太平洋大西洋水流问题(LeetCode-417)

题目描述 有一个 m n 的矩形岛屿,与 太平洋 和 大西洋 相邻。 “太平洋” 处于大陆的左边界和上边界,而 “大西洋” 处于大陆的右边界和下边界。 这个岛被分割成一个由若干方形单元格组成的网格。给定一个 m x n 的整数矩阵 heights , hei…

《Python基础》第2期:环境搭建

在开始编写 Python 代码前,还需要搭建 Python 的开发环境。 电脑是没办法直接读懂 Python 代码的,而是需要一个解释器,实时把代码翻译成字节码,字节码再转换成 0 和 1,电脑就能读懂了。 Python 的运行过程就是翻译一行…

WSL 安装 Debian 12 后,Linux 如何安装 curl , quickjs ?

在 WSL 的 Debian 12 系统中安装 curl 非常简单,你可以直接使用 APT 包管理器从官方仓库安装。以下是详细步骤: 1. 更新软件包索引 首先确保系统的包索引是最新的: sudo apt update2. 安装 curl 执行以下命令安装 curl: sudo…

[CSS3]vw/vh移动适配

vw/vh 目标: 能够使用vw单位设置网页元素的尺寸 相对单位相对视口的尺寸计算结果.vw全称viewport width; 1vw1/100视口宽度 vh全称viewport height; 1vh1/100视口高度 体验vw和vh单位 <!DOCTYPE html> <html lang"en"> <head><meta charset…

YOLOX 的动态标签分类(如 SimOTA)与 Anchor-free 机制解析2025.5.29

YOLOX 的动态标签分类&#xff08;如 SimOTA&#xff09;与 Anchor-free 机制是其核心改进中的两个关键部分&#xff0c;它们在目标检测中的作用和实现方式存在显著差异。以下从原理、实现细节及效果三个方面进行详细对比&#xff1a; 一、核心原理与目标 1. Anchor-free 机制…

724.寻找数组的中心下标前缀和

题目链接&#xff1a; https://leetcode.cn/problems/find-pivot-index/ 这道题目我们可以使用暴力解法&#xff0c;就一个下标前数组之和&#xff0c;再求一个下标后数组之和&#xff0c;时间复杂度达到n方&#xff0c;我们来写一下&#xff1a; int pivotIndex(vector<in…

软考-系统架构设计师-第十六章 层次式架构设计理论与实践

层次式架构设计理论与实践 16.2 表现层框架设计16.3 中间层框架设计16.4 数据访问层设计16.5 数据架构规划与设计16.6 物联网层次架构设计 软件体系结构为软件系统提供了结构、行为和属性的高级抽象&#xff0c;由构成系统的元素描述这些元素的相互作用、指导元素集成的模式以及…

Docker学习笔记:基础知识

本文是自己的学习笔记 1、什么是Docker2、Docker的架构设计2.1、镜像&#xff08;Image&#xff09;2.2、容器&#xff08;Container&#xff09;2.3、仓库&#xff08;Repository)2.4、Docker使用场景案例 1、什么是Docker Docker是基于Go语言实现的云开源项目。它的角色是作…

5.2 初识Spark Streaming

在本节实战中&#xff0c;我们初步探索了Spark Streaming&#xff0c;它是Spark的流式数据处理子框架&#xff0c;具备高吞吐量、可伸缩性和强容错能力。我们了解了Spark Streaming的基本概念和运行原理&#xff0c;并通过两个案例演示了如何利用Spark Streaming实现词频统计。…

Python趣学篇:交互式词云生成器(jieba + Tkinter + WordCloud等)

名人说&#xff1a;路漫漫其修远兮&#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、为什么要做词云&#xff1f;让文字"活"起来&#xff01;二、核心…

理解解释器架构:原理、组成与运行机制全解析

目录 前言1. 什么是解释器架构2. 解释器的基本组成2.1 被解释执行的程序2.2 解释器引擎2.3 解释器内部状态2.4 程序执行的当前状态2.5 存储器模型 3. 解释器的工作原理3.1 解析源代码3.2 初始化运行环境3.3 逐条执行语法结构3.4 维护程序状态3.5 内存管理与变量作用域 4. 举例&…

2025华为OD机试真题+全流程解析+备考攻略+经验分享+Java/python/JavaScript/C++/C/GO六种语言最佳实现

华为OD全流程解析&#xff0c;备考攻略 快捷目录 华为OD全流程解析&#xff0c;备考攻略一、什么是华为OD&#xff1f;二、什么是华为OD机试&#xff1f;三、华为OD面试流程四、华为OD薪资待遇及职级体系五、ABCDE卷类型及特点六、题型与考点七、机试备考策略八、薪资与转正九、…

设计模式——桥接设计模式(结构型)

摘要 桥接设计模式是一种结构型设计模式&#xff0c;用于将抽象与实现解耦&#xff0c;使二者可以独立变化。它通过将一个类拆分为“抽象”和“实现”两部分&#xff0c;并通过桥接关系组合&#xff0c;避免了类继承层次结构过于庞大。桥接模式包含抽象类、扩充抽象类、实现类…

LLaDa——基于 Diffusion 的大语言模型 打平 LLama 3

这里分享一篇文章《Large Language Diffusion Models》&#xff0c;来自人民大学高领人工智能学院&#xff0c;一篇尝试改变传统自回归范&#xff08;预测下一个token&#xff09; LLM 架构&#xff0c;探索扩散模型在 LLM 上的作用&#xff0c;通过随机掩码-预测逆向思维&…

2. 数据结构基本概念 (2)

本文部分ppt、视频截图来自&#xff1a;[青岛大学-王卓老师的个人空间-王卓老师个人主页-哔哩哔哩视频] 1. 数据结构基本概念 1.1 数据类型和抽象数据类型 (1) 数据类型(Data Type) 概念 数据类型是一组性质相同的值的集合以及定义于这个值集合上的一组操作的总称。 在使用…

STM32F407寄存器操作(多通道单ADC+DMA)

1.前言 又是半年没更新了&#xff0c;趁着端午放假有点时间&#xff0c;并且最近项目要用这块知识&#xff0c;我就顺带研究一下ADC吧。 一般来说ADC主要用法包含了1.单通道软件触发&#xff08;这是最简单和最常用的用法&#xff09;2.单通道多次采集&#xff08;需要快速采…

基于React和TypeScript的金融市场模拟器开发与模式分析

基于React和TypeScript的金融市场模拟器开发与模式分析 项目概述 本项目开发了一个基于React和TypeScript的金融市场模拟器&#xff0c;通过模拟订单流和价格发现机制&#xff0c;重现了真实市场的动态特性。该模拟器不仅提供了实时价格图表、订单簿和交易功能&#xff0c;还…

reverse_ssh 建立反向 SSH 连接指南 混淆AV [好东西哟]

目录 &#x1f310; 工具简介 ⚙️ 前提条件 攻击主机 (Linux) 目标主机 (Windows) &#x1f4cb; 详细步骤 步骤 1&#xff1a;安装 Go 环境 步骤 2&#xff1a;安装必要依赖 步骤 3&#xff1a;下载并编译 reverse_ssh 步骤 4&#xff1a;配置密钥 步骤 5&#xff…

lvs-keepalived高可用群集

目录 1.Keepalived 概述及安装 1.1 Keepalived 的热备方式 1.2 keepalived的安装与服务控制 &#xff08;1&#xff09;安装keep alived (2)控制 Keepalived 服务DNF 安装 keepalived 后,执行以下命令将keepalived 服务设置为开机启动。 2.使用 Keepalived 实现双机热备 …