github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/pkg/crypto/ed25519.go (about) 1 // Copyright 2017-2019 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package crypto 6 7 import ( 8 "crypto/rand" 9 "crypto/x509" 10 "encoding/pem" 11 "errors" 12 "io/ioutil" 13 "os" 14 15 "golang.org/x/crypto/ed25519" 16 ) 17 18 var ( 19 // PubKeyIdentifier is the PEM public key identifier 20 PubKeyIdentifier = "PUBLIC KEY" 21 // PrivKeyIdentifier is the PEM private key identifier 22 PrivKeyIdentifier = "PRIVATE KEY" 23 // PEMCipher is the PEM encryption algorithm 24 PEMCipher = x509.PEMCipherAES256 25 // PubKeyFilePermissions are the public key file perms 26 PubKeyFilePermissions os.FileMode = 0644 27 // PrivKeyFilePermissions are the private key file perms 28 PrivKeyFilePermissions os.FileMode = 0600 29 ) 30 31 // LoadPublicKeyFromFile loads PEM formatted ED25519 public key from file. 32 func LoadPublicKeyFromFile(publicKeyPath string) ([]byte, error) { 33 x509PEM, err := ioutil.ReadFile(publicKeyPath) 34 if err != nil { 35 return nil, err 36 } 37 38 // Parse x509 PEM file 39 var block *pem.Block 40 for { 41 block, x509PEM = pem.Decode(x509PEM) 42 if block == nil { 43 return nil, errors.New("can't decode PEM file") 44 } 45 if block.Type == PubKeyIdentifier { 46 break 47 } 48 } 49 50 return block.Bytes, nil 51 } 52 53 // LoadPrivateKeyFromFile loads PEM formatted ED25519 private key from file. 54 func LoadPrivateKeyFromFile(privateKeyPath string, password []byte) ([]byte, error) { 55 x509PEM, err := ioutil.ReadFile(privateKeyPath) 56 if err != nil { 57 return nil, err 58 } 59 60 // Parse x509 PEM file 61 var block *pem.Block 62 for { 63 block, x509PEM = pem.Decode(x509PEM) 64 if block == nil { 65 return nil, errors.New("can't decode PEM file") 66 } 67 if block.Type == PrivKeyIdentifier { 68 break 69 } 70 } 71 72 // Check for encrypted PEM format 73 if x509.IsEncryptedPEMBlock(block) { 74 decryptedKey, err := x509.DecryptPEMBlock(block, password) 75 if err != nil { 76 return nil, err 77 } 78 return decryptedKey, nil 79 } 80 81 return block.Bytes, nil 82 } 83 84 // GeneratED25519Key generates a ED25519 keypair 85 func GeneratED25519Key(password []byte, privateKeyFilePath string, publicKeyFilePath string) error { 86 pubKey, privKey, err := ed25519.GenerateKey(rand.Reader) 87 if err != nil { 88 return err 89 } 90 91 var privBlock = &pem.Block{ 92 Type: "PRIVATE KEY", 93 Bytes: privKey, 94 } 95 96 var pubBlock = &pem.Block{ 97 Type: "PUBLIC KEY", 98 Bytes: pubKey, 99 } 100 101 var privateKey []byte 102 if len(password) < 1 { 103 encrypted, err := x509.EncryptPEMBlock(rand.Reader, privBlock.Type, privBlock.Bytes, password, PEMCipher) 104 if err != nil { 105 return err 106 } 107 privateKey = pem.EncodeToMemory(encrypted) 108 } else { 109 privateKey = pem.EncodeToMemory(privBlock) 110 } 111 112 if err := ioutil.WriteFile(privateKeyFilePath, privateKey, PrivKeyFilePermissions); err != nil { 113 return err 114 } 115 116 return ioutil.WriteFile(publicKeyFilePath, pem.EncodeToMemory(pubBlock), PubKeyFilePermissions) 117 }