Closed Chralu closed 1 year ago
@Chralu Base64 decoding (e.g using this online tool) your Base64encoded string "MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEhYvCTeKdth6ffyCKReeO7cJSfN94BfieZ/9zkE6sDFz/ZifyMkgeg7mq8XB4UYn7aSEcsnqFNswROLnU4NqVFbmGDi5wAI0jRazdskGFBf+0R/zIPozZgJOSrREMEqi7"
yields this hex:
3076301006072A8648CE3D020106052B8104002203620004858BC24DE29DB61E9F7F208A45E78EEDC2527CDF7805F89E67FF73904EAC0C5CFF6627F232481E83B9AAF170785189FB69211CB27A8536CC1138B9D4E0DA9515B9860E2E70008D2345ACDDB2418505FFB447FCC83E8CD9809392AD110C12A8BB
Which ASN1 decoded
shows that you have specified the SECG Elliptic Curve Called secp384r1
which is also called P-384.
Looking at osstatus.com error -26275 is errSecInvalidKey
If I were you I would avoid Keychain APIs and use CryptoKit (or the open source variant swift-crypto) instead. With some Data+Hex conversion tool in Swift, this unit tests passes:
func test_p384() throws {
let der = "3076301006072A8648CE3D020106052B8104002203620004858BC24DE29DB61E9F7F208A45E78EEDC2527CDF7805F89E67FF73904EAC0C5CFF6627F232481E83B9AAF170785189FB69211CB27A8536CC1138B9D4E0DA9515B9860E2E70008D2345ACDDB2418505FFB447FCC83E8CD9809392AD110C12A8BB"
let pubKey = try CryptoKit.P384.Signing.PublicKey(derRepresentation: Data(hex: der))
XCTAssertEqual(pubKey.rawRepresentation.hex(), "858bc24de29db61e9f7f208a45e78eedc2527cdf7805f89e67ff73904eac0c5cff6627f232481e83b9aaf170785189fb69211cb27a8536cc1138b9d4e0da9515b9860e2e70008d2345acddb2418505ffb447fcc83e8cd9809392ad110c12a8bb")
}
So rawRepresentation (uncompressed: X || Y
) of your public key is: 858bc24de29db61e9f7f208a45e78eedc2527cdf7805f89e67ff73904eac0c5cff6627f232481e83b9aaf170785189fb69211cb27a8536cc1138b9d4e0da9515b9860e2e70008d2345acddb2418505ffb447fcc83e8cd9809392ad110c12a8bb
(in hex)
@CyonAlexRDX Thank you for your help.
My question needs a bit more context about what I need to achieve.
If I understand correctly the documentation, I need a SecKeyRef
object representing the peer public EC key.
That's why I'm trying to create a SecKeyRef
from my PEM encoded public key.
@Chralu see https://developer.apple.com/forums/thread/680572
you’re working with Security framework, use SecKeyCreateWithData to import an SECG key. If you have a secp256r1 public key in X9.63 format
And:
Note I’m using secp256r1 as an example. The code in this section will work for the other SECG key types, secp384r1 and secp521r1.
Just so you know: P384
and secp384r1
is the same Curve
Thank you @CyonAlexRDX , that forum post is a huge help 🙏
I'll use the Security Framework solution, to be compatible with iOS < 14.0. To get it work, I'll have to convert the public key from DER format to X9.63.
@Chralu use CrypoKit for DER -> X9.63 conversion!
Here is a DER
initializer on P384.Signing.PublicKey
and then you can use this property to read out the data on x963Representation
Unfortunately, this is iOS14+ compatible 😔 I need a wider compatibility.
Unfortunately, this is iOS14+ compatible 😔
I need a wider compatibility.
Then you can use open source version of CryptoKit! Swift-crypto, which has iOS13 support, check https://github.com/apple/swift-crypto/blob/main/Sources/Crypto/Key%20Agreement/ECDH.swift#L330
Having troubles to use Swift-Crypto in a Cocoapods project (project is a Flutter plugin), I used ASN1Decoder to extract key data from DER.
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")
In an iOS application, I would like to calculate a PIV secret.
To do so, I receive the peer PEM-encoded Elliptic curve public key. And I need to create a
SecKey
object from it.This question has been very useful to get RSA key parsing to work.
But I struggle adapting it to work with an EC key.
Example working with an RSA key
Example failing with an EC key
Execution returns the following logs :
For information, I used https://mkjwk.org/ to generate public keys.
What else did I try
I tried to extract the DER BIT STRING using ASN1Decoder and ASN1Swift without success.
Would you have any idea of what's going on with those EC keys ? Thanks a lot 🙏