ios - PEM编码的椭圆曲线公钥转换iOS

标签 ios swift pem asn.1 seckeyref

在 iOS 应用程序中,我收到 PEM 编码的椭圆曲线公钥。 我想从中创建一个 SecKey 对象。

This问题对于让RSA key 解析工作非常有用。

但我很难将其调整为与 EC key 一起使用。

使用 RSA key 的示例

var secKeyCreateError : Unmanaged<CFError>?
guard
    let stringPublicKey = Data(
        base64Encoded: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhT0OXGhPWpbrZBTIScIFQVooi/Qo/NyTYRnrIyZ42nksKCBeSOBu+FPOHCI5U4RUSc2cUOe83dyuKmboU2Kdc1dTq9HDAau3dhpE7VLzZKzMHay+8XW5V6kQJ2oOIGKJphsjJLDM5KxCr5etHEHE5rfrPIBZA0sgcvyT0TsavOAhr55Eu4U2fu8SefxM4CWobXKANiWbmSzzYbo2EIZrfhhe2RncwnH5kr0PMk6Q+kEcuRt58VyYoDAa7vRQvY+KDwxE81CCkIjKpJ55f4uN0/VDclXzFjK8FeOgIiH3n8KD6xqtkvmFc+M8tEJYlzdHWIRN7VoNqbn4IoevnziYhQIDAQAB"
    ),
    let peerPublicKey = SecKeyCreateWithData(
        stringPublicKey as CFData,
        [
            kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
            kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
        ] as CFDictionary,
        &secKeyCreateError
    )
else {
    NSLog("Failed to create SecKey : %@", secKeyCreateError!.takeRetainedValue().localizedDescription)
    return
}

NSLog("SecKey successfully created")

使用 EC key 失败的示例

var secKeyCreateError : Unmanaged<CFError>?
guard
    let stringPublicKey = Data(
        base64Encoded: "MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEhYvCTeKdth6ffyCKReeO7cJSfN94BfieZ/9zkE6sDFz/ZifyMkgeg7mq8XB4UYn7aSEcsnqFNswROLnU4NqVFbmGDi5wAI0jRazdskGFBf+0R/zIPozZgJOSrREMEqi7"
    ),
    let peerPublicKey = SecKeyCreateWithData(
        stringPublicKey as CFData,
        [
            kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
            kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
        ] as CFDictionary,
        &secKeyCreateError
    )
else {
    NSLog("Failed to create SecKey : %@", secKeyCreateError!.takeRetainedValue().localizedDescription)
    return
}

NSLog("SecKey successfully created")

执行返回以下日志:

[seckey] SecKeyCreate init(ECPublicKey) failed: -26275
Failed to create SecKey : The operation couldn’t be completed. (OSStatus error -50 - EC public key creation from data failed)

作为信息,我使用了 https://mkjwk.org/生成公钥。

我还尝试了什么

我尝试使用 ASN1Decoder 提取 DER BIT STRING和 ASN1Swift没有成功。

您知道这些 EC key 是怎么回事吗? 非常感谢🙏

最佳答案

pointed out by CyonAlexRdx here ,SECG key 必须采用X9.63格式,才能使用安全框架导入。

在这里,我们遇到了麻烦,因为 key 是PEM格式。我确定了 2 个解决方案。

您的项目使用 Swift 包管理器

您可以使用CryptoKit导入它,然后将其映射到安全框架对象。

Detailed explainations from eskimo on developer.apple.com forum

  1. 使用 Apple CryptoKit 导入 PEM key 。
  2. 获取 X9.63 表示形式。
  3. 从中创建安全框架 key 。

例如,以下例程导入 PEM secp256r1 私钥并返回 SecKey 对象:

func createSecKeyWithPEMSecp256r1Private(_ pem: String) throws -> SecKey {
    let privateKeyCK = try P256.Signing.PrivateKey(pemRepresentation: pem)
    let x963Data = privateKeyCK.x963Representation
    var errorQ: Unmanaged<CFError>? = nil
    guard let privateKeySF = SecKeyCreateWithData(x963Data as NSData, [
        kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,
        kSecAttrKeyClass: kSecAttrKeyClassPrivate,
    ] as NSDictionary, &errorQ) else {
        throw errorQ!.takeRetainedValue()
    }
    return privateKeySF
}

您的项目使用cocoapods

您可以使用ASN1Decoder从 DER 中提取关键数据(x9.63 格式)。

import ASN1Decoder

class DerDecoder {
    func decodePublicKey(_ data: Data,  _ error: UnsafeMutablePointer<Unmanaged<CFError>?>?) -> SecKey? {
        guard
            let asn1 = try? ASN1DERDecoder.decode(data: data),
            let keyData = asn1.first?.sub(1)?.value as? Data
        else {
            return nil
        }
        return SecKeyCreateWithData(
            keyData as CFData,
            [
                kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
                kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
            ] as CFDictionary,
            error
        )
    }
}


var secKeyCreateError : Unmanaged<CFError>?
guard
    let stringPublicKey = Data(
        base64Encoded: "MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEhYvCTeKdth6ffyCKReeO7cJSfN94BfieZ/9zkE6sDFz/ZifyMkgeg7mq8XB4UYn7aSEcsnqFNswROLnU4NqVFbmGDi5wAI0jRazdskGFBf+0R/zIPozZgJOSrREMEqi7"
    ),
    let peerPublicKey = DerDecoder().decodePublicKey(
        stringPublicKey,
        &secKeyCreateError,
    )
else {
    NSLog("Failed to create SecKey : %@", secKeyCreateError!.takeRetainedValue().localizedDescription)
    return
}

NSLog("SecKey successfully created")

关于ios - PEM编码的椭圆曲线公钥转换iOS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75072057/

相关文章:

ios - watchos 3 beta 6 中的 WKInterfaceController header 拼写错误?

ios - 无法满足约束 - 视觉格式语言

Swift-通过角度设置物理体速度

ios - 如何在分页 UIScrollView 中显示确定的项目而不是仅从 0 加载它

c++ - Openssl X509 cert 获取人类可读的字符串

iphone - resignFirstResponder 出现后续处理问题(键盘在 iPhone 5 上被阻止或崩溃)

ios - 通过UITextView修改CoreData实体属性值

ios - 使用 SwiftyDropbox 创建指向文件的共享链接

swift - 如何在 swift 中将 RSA pem 文件转换为 XML?或者如何快速获取 RSA XML?

Java 证书客户端 SSL : unable to find valid certification path to requested target