pythonswiftcryptographypublic-keypublic-key-exchange# Output SecKeyCopyExternalRepresentation

I'm trying to pass around a public key from my iPhone to other parties, however I am unable to use the output from iOS.

```
let parameters: [String: Any] = [
kSecAttrKeySizeInBits as String: 384,
kSecAttrKeyType as String: kSecAttrKeyTypeEC,
kSecPrivateKeyAttrs as String: [
kSecAttrIsPermanent as String: false
]
]
var error: Unmanaged<CFError>?
let privateKey = SecKeyCreateRandomKey(parameters as CFDictionary, &error)
let publicKey = SecKeyCopyPublicKey(privateKey!)
let pub = SecKeyCopyExternalRepresentation(publicKey!, &error)
let pubData = pub as Data?
print(pubData!.base64EncodedString())
```

Example output:

BJSCZtBatd2BYEHtyLB0qTZNlphKf3ZTGI6Nke3dSxIDpyP9FWMZbG0zcdIXWENyndskfxV0No/yz369ngL2EHZYw6ggNysOnZ5IQSPOLFFl44m1aAk0o0NdaRXTVAz4jQ==

In python (where my second party is) I have the following:

```
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
pub_key = serialisation.load_pem_public_key(
data=xcode_data.encode(),
backend=default_backend()
)
```

The error I get is `ValueError: Could not deserialize key data.`

So what exactly is the output of the `SecKeyCopyExternalRepresentation`

as described by the documentation:

The method returns data in the PCKS #1 format for an RSA key. For an elliptic curve public key, the format follows the ANSI X9.63 standard using a byte string of 04 || X || Y. For an elliptic curve private key, the output is formatted as the public key concatenated with the big endian encoding of the secret scalar, or 04 || X || Y || K. All of these representations use constant size integers, including leading zeros as needed.

How would one describe the `X6.93`

format? And how would I go about converting it to something I can use in the python code?

P.S. I have tried to add headers such as `-----BEGIN PUBLIC KEY-----`

to the xcode output.

Solution

I havent quite found the answer to the question as I still don't know what exactly the output is that Apple provides, however, I came up with a solution found in this key import export manager.

```
let parameters: [String: Any] = [
kSecAttrKeySizeInBits as String: 384,
kSecAttrKeyType as String: kSecAttrKeyTypeEC,
kSecPrivateKeyAttrs as String: [
kSecAttrIsPermanent as String: false
]
]
var pubKey: SecKey?
var priKey: SecKey?
var error: Unmanaged<CFError>?
let keyPair = SecKeyGeneratePair(parameters as CFDictionary, &pubKey, &priKey)
let publicKeyData = SecKeyCopyExternalRepresentation(pubKey!, &error)
// Code from the library
let ieManager = CryptoExportImportManager()
if let exportPEM = ieManager.exportPublicKeyToPEM(publicKeyData as Data!, keyType: kSecAttrKeyTypeEC as String, keySize: 384) {
print(exportPEM)
} else {
print("Error exporting to PEM")
}
```

Example output:

`Exporting EC raw key: 97 bytes -----BEGIN PUBLIC KEY----- MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEFpCnTrJFQq0mZBvy+vzl9noKLZ4/s1cf I6hygug6s8dvBreMhabAcAbbhSa1losjCxV450nq92W9ZymonYasaAuhshDWjmvx 2qTXHEpVEVb9GawqX6XqpWtIBf+meHKS -----END PUBLIC KEY-----`

Implementation in python using cryptography

```
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
xcode = '-----BEGIN PUBLIC KEY-----\nMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEFpCnTrJFQq0mZBvy+vzl9noKLZ4/s1cf\nI6hygug6s8dvBreMhabAcAbbhSa1losjCxV450nq92W9ZymonYasaAuhshDWjmvx2\nqTXHEpVEVb9GawqX6XqpWtIBf+meHKS\n-----END PUBLIC KEY-----'
pub_key = serialization.load_pem_public_key(xcode.encode(), default_backend())
xcode
```

Outputs the following:
`<cryptography.hazmat.backends.openssl.ec._EllipticCurvePublicKey object at 0x7fb4f6f50e10>`

Note that you do have to add the new lines yourself in python in order for this all to work.

**Update**

The output of the `SecKeyCopyExternalRepresentation`

for ECC keys is the X9.62 or X9.63 format of the key (in uncompressed form). This is very different from DER and therefor PEM encoding.

The encoding is `04 || X || Y`

for a public key and `04 || X || Y || K`

for a private key. `04`

is a fixed byte for this format. The `X`

, `Y`

and optionally `K`

value are points or coordinates that define the curve of this key. More info about that over here.

- Python interpreter doesn't read json
- Renaming column names from a data set in pandas
- How do I use the functions within this Python script?
- Catch-all method in class that passes all unknown functions to instance in class
- Detecting collision in Python turtle game
- python-docx, access to paragraph font-size
- pandas describe by - additional parameters
- Ways to slice a string?
- Invalid argument when saving pickle file
- Python - numpy.loadtxt how to ignore end commas?
- Read and dump [bracket, list] from and to yaml with python
- No response when getting a table from a web using BeautifulSoap library
- ModuleNotFoundError: No module named 'apt_pkg' installing deadsnakes repository
- python selenium click on button
- What's the difference between Docker and Python virtualenv?
- Cannot read image using cv2.imread()
- Meaning of the retval return value in cv2.CalibrateCamera
- Initialize deque efficiently
- ModuleNotFoundError: No module named 'sklearn.preprocessing._data'
- Python a, b = b, a +b
- Why is my function always outputting "invalid" as a result?
- Add column sum as new column in PySpark dataframe
- Error while installing chatterbot using pip. How do I fix it?
- Subtracting numpy arrays produces unexpected results
- How to return history of validation loss in Keras
- How to return a non-match in two 2d list?
- matplotlib two different colors in the same annotate
- How to convert a MAC number to MAC string?
- Integrate a function that takes as input a scalar value and outputs a matrix
- Problems creating a transformer for a pipeline