Parse curve25519 keys generated using openssl in Go

1.6k Views Asked by At

Using OpenSSL version 1.1 and or later, I'm able to generate a curve25519 key:

openssl genpkey -algorithm x25519

This produces a private key of the form:

-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VuBCIEIDgk3GuFMIaUJd3m95jn/Z8oU+cK9FzPoidIDn/bqRlk
-----END PRIVATE KEY-----

I want to parse this key file in Go and potentially use it using golang.org/x/crypto/nacl/box. Looking at crypto/x509 documentation, I can't find a parsing function that parses curve25519. Anyone have an idea?

I tried:

pKey := `-----BEGIN PUBLIC KEY-----
MCowBQYDK2VuAyEAfLLsWKkI/7EmTOkSf4fyHuRHDnKk6qNncWDzV8jlIUU=
-----END PUBLIC KEY-----`

block, _ := pem.Decode([]byte(pKey))
key, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
    fmt.Println(err)
}

I get the error unknown public key algorithm.

2

There are 2 best solutions below

0
matt On BEST ANSWER

Since there is currently no way to parse X25519 keys in the standard library, you may have to do this “by hand”.

You could do it “properly” by using the encoding/asn1 library to decode the keys, but in this case there is a simpler way.

It turns out that for both the private and public keys the actual key is just the last 32 bytes of the base64 decoded block of the key.

So you can just do:

block, _ := pem.Decode([]byte(pemString))
key := block.Bytes[len(block.Bytes)-32:]

This will work for both public and private keys, and will give you a 32 byte []byte containing the appropriate key.

5
colm.anseo On

Your inline key value is malform due to the tab/spaces before -----END PUBLIC KEY-----

As a result block is nil and cause the follow-up function to segfault.

Here's a quick fix for the decoding piece:

pKey := `-----BEGIN PRIVATE KEY-----
MCowBQYDK2VuAyEAfLLsWKkI/7EmTOkSf4fyHuRHDnKk6qNncWDzV8jlIUU=
-----END PRIVATE KEY-----`

block, _ := pem.Decode([]byte(pKey))

if block == nil || block.Type != "PRIVATE KEY" {
    log.Fatal("failed to decode PEM block containing private key")

}

key, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
    log.Println("Parse PKI Error:", err)
    return
}

Playground: https://play.golang.org/p/O2wk8rmKGWH

Note: ParsePKIXPublicKey function does not recognize this key algorithm.

2009/11/10 23:00:00 Parse PKI Error: x509: unknown public key algorithm