在 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
- 使用 Apple CryptoKit 导入 PEM key 。
- 获取 X9.63 表示形式。
- 从中创建安全框架 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/