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

问题描述 投票:0回答:1

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

SecKey
对象。

这个问题对于使RSA密钥解析工作非常有用。

但我很难让它适应 EC 密钥

使用 RSA 密钥的示例

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 密钥失败的示例

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/ 生成公钥。

我还尝试了什么

我尝试使用 ASN1DecoderASN1Swift 提取 DER BIT STRING,但没有成功。

您知道这些 EC 密钥发生了什么吗? 非常感谢🙏

ios swift pem asn.1 seckeyref
1个回答
0
投票

正如 CyonAlexRdx 指出的,SECG 密钥必须是 X9.63 格式才能使用Security Framework导入。

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

您的项目使用 Swift 包管理器

您可以使用 CryptoKit 导入它,然后将其映射到 Security Framework 对象。

详细解释来自 developer.apple.com 论坛上的爱斯基摩人

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

例如下面的例程导入一个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")
© www.soinside.com 2019 - 2024. All rights reserved.