apple / swift-crypto

Open-source implementation of a substantial portion of the API of Apple CryptoKit suitable for use on Linux platforms.

Home Page:https://apple.github.io/swift-crypto

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

PEM/DER Support for Curve25519

annathomasQB opened this issue · comments

New API Proposal: Curve25519

Motivation:

I know CryptoKit provides Curve25519, but to export the public key as a pem string is not possible, as the raw representation of the key is compressed 32 bytes. For pem, we require uncompressed bytes along with ASN1 encoding and other stuff right?

Importance:

Saw in the source code the files like SubjectPublicKeyInfo.swift. This helps wrap the raw bytes and export them as pem. My current requirement is to export the curve25519 public key as a pem string. No libraries out there does this currently.

This is a good idea. I'll circulate the idea around and see how we feel about it.

I will add:

as the raw representation of the key is compressed 32 bytes. For pem, we require uncompressed bytes along with ASN1 encoding and other stuff right?

This is not true: Curve25519 public keys are not being emitted compressed, but they are always 32-bytes (Curve25519 keys only need the x coordinate). So the current output of the library is sufficient to produce a PEM format.

So the current output of the library is sufficient to produce a PEM format

Yes, I tried.
I'm currently achieving the same by prefixing a standard header that I got from Eskimo from Apple developer forums. But I'm sure everyone would be having this requirement, and nowhere is the prefix data for each curve type available as a list online.

Here's my question and the answer that I got for this. This is working 👍

https://developer.apple.com/forums/thread/679787

Just wanted to mention regarding:

and nowhere is the prefix data for each curve type available as a list online.

These values are available out on the internet in RFC8410 listed by the algorithm identifier OID.
They are buried in an ASN.1 structure for SubjectPublicKeyInfo so it's hard to identify the ones that count for the algorithm you are using.

It looks like Quinn was giving you a head start on defining this structure when the following was provided:

let prefix = Data([0x30, 0x2A, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x6E, 0x03, 0x21, 0x00])

Which roughly translates to:

0x30 = SEQUENCE (42 bytes length (0x2A))
0x30 = SEQUENCE (5 bytes length (0x05))
0x06 = OBJECT IDENTIFIER (3 bytes length (0x03))
0x2B = 43 (I believe this represents an OID formula for 140+3 or 1.3 (x40+Y))
0x65 = 101 {iso(1) org(3) thawte(101)} (https://oidref.com/1.3.101)
0x6E = 110 (OID id-X25519(110) for https://datatracker.ietf.org/doc/html/rfc8410)
0x03 = BIT STRING (33 bytes in length 0x00 + your key bytes)

And that is why appending your raw key bytes to your prefix worked out to generate your PEM.

Thank you @agnosticdev for that detailed description :)
I did want an explanation for the series of bits and you provided it. Thank you!

Renaming the issue to better reflect what this is about. We'll take it in for consideration!