1919package p2p
2020
2121import (
22+ "crypto/ed25519"
2223 "crypto/rand"
24+ "crypto/x509"
25+ "encoding/pem"
2326 "fmt"
2427 "os"
2528 "path"
@@ -34,7 +37,7 @@ import (
3437
3538// DefaultPrivKeyPath is the default path inside the node's root directory at which the private key
3639// for p2p identity is found and persisted to when a new one is generated.
37- const DefaultPrivKeyPath = "peerIDPrivKey.pem "
40+ const DefaultPrivKeyPath = "peerIDPrivKey.key "
3841
3942// PeerID is a string representation of a peer's public key, primarily used to avoid importing libp2p into packages that shouldn't need it
4043type PeerID string
@@ -84,15 +87,31 @@ func PeerIDFromPublicKey(pubKey crypto.PubKey) (PeerID, error) {
8487 return PeerID (peerID ), nil
8588}
8689
90+ // pemBlockType is the type of PEM block used for private keys
91+ const pemBlockType = "PRIVATE KEY"
92+
8793// loadPrivateKeyFromFile attempts to read raw privKey bytes from path
8894// It only supports Ed25519 keys.
8995func loadPrivateKeyFromFile (path string ) (crypto.PrivKey , error ) {
9096 bytes , err := os .ReadFile (path )
9197 if err != nil {
9298 return nil , err
9399 }
100+ p , _ := pem .Decode (bytes )
101+ if p == nil || p .Type != pemBlockType {
102+ return nil , fmt .Errorf ("failed to PEM decode private key at %s" , path )
103+ }
104+
105+ ak , err := x509 .ParsePKCS8PrivateKey (p .Bytes )
106+ if err != nil {
107+ return nil , err
108+ }
109+ sk , ok := ak .(ed25519.PrivateKey )
110+ if ! ok {
111+ return nil , fmt .Errorf ("unsupported private key type: %T, expecting ed25519" , ak )
112+ }
94113 // We only support Ed25519 keys
95- return crypto .UnmarshalEd25519PrivateKey (bytes )
114+ return crypto .UnmarshalEd25519PrivateKey (sk )
96115}
97116
98117// writePrivateKeyToFile attempts to write raw privKey bytes to path
@@ -101,7 +120,27 @@ func writePrivateKeyToFile(path string, privKey crypto.PrivKey) error {
101120 if err != nil {
102121 return err
103122 }
104- return os .WriteFile (path , bytes , 0600 )
123+ if len (bytes ) != ed25519 .PrivateKeySize {
124+ return fmt .Errorf ("incompatible ed25519 private key length: %d" , len (bytes ))
125+ }
126+ key := ed25519 .PrivateKey (bytes )
127+ derBytes , err := x509 .MarshalPKCS8PrivateKey (key )
128+ if err != nil {
129+ return err
130+ }
131+
132+ p := pem.Block {
133+ Type : pemBlockType ,
134+ Bytes : derBytes ,
135+ }
136+
137+ f , err := os .OpenFile (path , os .O_WRONLY | os .O_CREATE | os .O_TRUNC , 0600 )
138+ if err != nil {
139+ return err
140+ }
141+ defer f .Close ()
142+
143+ return pem .Encode (f , & p )
105144}
106145
107146// generatePrivKey creates a new Ed25519 key
0 commit comments