package crypto import ( "crypto/ed25519" "crypto/rand" "crypto/x509" "encoding/pem" "errors" ) // NewPersistedED25519 public & private keys func NewPersistedED25519() ([]byte, []byte, error) { pub, prv, err := ed25519.GenerateKey(rand.Reader) if err != nil { return nil, nil, err } // marshal public key pubB, err := marshalEdPublicKey(pub) if err != nil { return nil, nil, err } // marshal private key prvB, err := marshalEdPrivateKey(prv) if err != nil { return nil, nil, err } // done return pubB, prvB, nil } func marshalEdPrivateKey(key ed25519.PrivateKey) ([]byte, error) { b, err := x509.MarshalPKCS8PrivateKey(key) if err != nil { return nil, err } enc := pem.EncodeToMemory( &pem.Block{ Type: "PRIVATE KEY", Bytes: b, }, ) return enc, nil } func parseEdPrivateKey(d []byte) (ed25519.PrivateKey, error) { block, _ := pem.Decode(d) if block == nil { return nil, errors.New("failed to parse PEM block containing the key") } b, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { return nil, err } switch pub := b.(type) { case ed25519.PrivateKey: return pub, nil default: return nil, errors.New("key type is not RSA") } } func marshalEdPublicKey(key ed25519.PublicKey) ([]byte, error) { b, err := x509.MarshalPKIXPublicKey(key) if err != nil { return nil, err } enc := pem.EncodeToMemory( &pem.Block{ Type: "PUBLIC KEY", Bytes: b, }, ) return enc, nil } func parseEdPublicKey(d []byte) (ed25519.PublicKey, error) { block, _ := pem.Decode(d) if block == nil { return nil, errors.New("failed to parse PEM block containing the key") } b, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { return nil, err } switch pub := b.(type) { case ed25519.PublicKey: return pub, nil default: return nil, errors.New("key type is not RSA") } }