Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert ECPublicKey(SecKey) to PEM String in swift

I want to convert ECPublicKey to PEM format as below

"-----BEGIN PUBLIC KEY-----MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEo0WcFrFClvBE8iZ1Gdlj+mTgZoJWMNE3kDKTfRny2iaguwuSYxo+jCnXqzkR+kyFK9CR3D+pypD1sGb1BnfWAA==-----END PUBLIC KEY-----"

  1. Generated ECPublicKey with key Type "ECC/ECDSA/spec256r1". Below is the print

<SecKeyRef curve type: kSecECCurveSecp256r1, algorithm id: 3, key type: ECPublicKey, version: 4, block size: 256 bits, y: B6EEBB3791933312E10BD7C3D65C950AB7E1C325BCDB57A8663EB7B1E29BFA77, x: 1D41FDAD2137316D415B117227BCC465566E56A54E7B2B9B3A4B66C15A067611, addr: 0x7f818850f6d0>

  1. To my knowledge PEM format is nothing but base64 encoded string along with header and footer. Tried below code, but no success
var error:Unmanaged<CFError>?

guard let cfdata = SecKeyCopyExternalRepresentation(publicKey, &error)
else { return }

let data:Data = cfdata as Data

let b64String = data.base64EncodedString()

Appreciate any help here

like image 999
UdayM Avatar asked Oct 27 '25 15:10

UdayM


2 Answers

Start by converting to ASN.1 format: (see your decoded example in ASN.1 Decoder)

let publicKeyData: CFData = ...
let ecHeader: [UInt8] = [
    /* sequence          */ 0x30, 0x59,
    /* |-> sequence      */ 0x30, 0x13,
    /* |---> ecPublicKey */ 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, // (ANSI X9.62 public key type)
    /* |---> prime256v1  */ 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, // (ANSI X9.62 named elliptic curve)
    /* |-> bit headers   */ 0x07, 0x03, 0x42, 0x00
]

var asn1 = Data()
asn1.append(Data(ecHeader))
asn1.append(publicKeyData as Data)

Then Base64-encode and add PEM header & footer:

let encoded = asn1.base64EncodedString(options: .lineLength64Characters)
let pemString = "-----BEGIN PUBLIC KEY-----\r\n\(encoded)\r\n-----END PUBLIC KEY-----\r\n"
like image 106
Sulthan Avatar answered Oct 29 '25 06:10

Sulthan


Apple Developer Documentation for SecKeyCopyExternalRepresentation

For an elliptic curve public key, the format follows the ANSI X9.63 standard using a byte string of 04 || X || Y.

– https://developer.apple.com/documentation/security/1643698-seckeycopyexternalrepresentation

You can use CryptoKit's P256.Signing.PublicKey class to print various representations, including PEM,

  • https://developer.apple.com/documentation/cryptokit/p256/signing/publickey/init(x963representation:)

  • https://developer.apple.com/documentation/cryptokit/p256/signing/publickey/pemrepresentation

see an example below:

import CryptoKit 

// .... your code from above, start
var error:Unmanaged<CFError>?

guard let cfdata = SecKeyCopyExternalRepresentation(publicKey, &error) else { return }

let data:Data = cfdata as Data
// .... your code from above, end


let p256PublicKey = try P256.Signing.PublicKey(x963Representation: data)
print(p256PublicKey.pemRepresentation)

prints the format, here another example key

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEI8JXzxdgciiFjbyUfUu8+au9S9mK
U4NVJztkCgiTwwqGvSkawDPtYAZk7xAomyrnurU0VAbsQW45TcDfl3suvw==
-----END PUBLIC KEY-----
 
like image 35
Sevyls Avatar answered Oct 29 '25 05:10

Sevyls