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  }