github.com/fluxcd/go-git-providers@v0.19.3/gitprovider/testutils/key_pair.go (about)

     1  /*
     2  Copyright 2020 The Flux authors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package testutils
    18  
    19  import (
    20  	"crypto/ecdsa"
    21  	"crypto/ed25519"
    22  	"crypto/elliptic"
    23  	"crypto/rand"
    24  	"crypto/rsa"
    25  	"crypto/x509"
    26  	"encoding/pem"
    27  
    28  	"golang.org/x/crypto/ssh"
    29  )
    30  
    31  // KeyPair holds the public and private key PEM block bytes.
    32  type KeyPair struct {
    33  	PublicKey  []byte
    34  	PrivateKey []byte
    35  }
    36  
    37  // KeyPairGenerator generates a new key pair.
    38  type KeyPairGenerator interface {
    39  	Generate() (*KeyPair, error)
    40  }
    41  
    42  // RSAGenerator generates RSA key pairs.
    43  type RSAGenerator struct {
    44  	bits int
    45  }
    46  
    47  // NewRSAGenerator returns a new RSA key pair generator.
    48  func NewRSAGenerator(bits int) KeyPairGenerator {
    49  	return &RSAGenerator{bits}
    50  }
    51  
    52  // Generate generates a new key pair.
    53  func (g *RSAGenerator) Generate() (*KeyPair, error) {
    54  	pk, err := rsa.GenerateKey(rand.Reader, g.bits)
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  	err = pk.Validate()
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  	pub, err := generatePublicKey(&pk.PublicKey)
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  	priv, err := encodePrivateKeyToPEM(pk)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  	return &KeyPair{
    71  		PublicKey:  pub,
    72  		PrivateKey: priv,
    73  	}, nil
    74  }
    75  
    76  // ECDSAGenerator generates ECDSA key pairs.
    77  type ECDSAGenerator struct {
    78  	c elliptic.Curve
    79  }
    80  
    81  // NewECDSAGenerator returns a new ECDSA key pair generator.
    82  func NewECDSAGenerator(c elliptic.Curve) KeyPairGenerator {
    83  	return &ECDSAGenerator{c}
    84  }
    85  
    86  // Generate generates a new key pair.
    87  func (g *ECDSAGenerator) Generate() (*KeyPair, error) {
    88  	pk, err := ecdsa.GenerateKey(g.c, rand.Reader)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  	pub, err := generatePublicKey(&pk.PublicKey)
    93  	if err != nil {
    94  		return nil, err
    95  	}
    96  	priv, err := encodePrivateKeyToPEM(pk)
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  	return &KeyPair{
   101  		PublicKey:  pub,
   102  		PrivateKey: priv,
   103  	}, nil
   104  }
   105  
   106  // Ed25519Generator generates Ed25519 key pairs.
   107  type Ed25519Generator struct{}
   108  
   109  // NewEd25519Generator returns a new Ed25519 key pair generator.
   110  func NewEd25519Generator() KeyPairGenerator {
   111  	return &Ed25519Generator{}
   112  }
   113  
   114  // Generate generates a new key pair.
   115  func (g *Ed25519Generator) Generate() (*KeyPair, error) {
   116  	pk, pv, err := ed25519.GenerateKey(rand.Reader)
   117  	if err != nil {
   118  		return nil, err
   119  	}
   120  	pub, err := generatePublicKey(pk)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  	priv, err := encodePrivateKeyToPEM(pv)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  	return &KeyPair{
   129  		PublicKey:  pub,
   130  		PrivateKey: priv,
   131  	}, nil
   132  }
   133  
   134  func generatePublicKey(pk interface{}) ([]byte, error) {
   135  	b, err := ssh.NewPublicKey(pk)
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  	k := ssh.MarshalAuthorizedKey(b)
   140  	return k, nil
   141  }
   142  
   143  // encodePrivateKeyToPEM encodes the given private key to a PEM block.
   144  // The encoded format is PKCS#8 for universal support of the most
   145  // common key types (rsa, ecdsa, ed25519).
   146  func encodePrivateKeyToPEM(pk interface{}) ([]byte, error) {
   147  	b, err := x509.MarshalPKCS8PrivateKey(pk)
   148  	if err != nil {
   149  		return nil, err
   150  	}
   151  	block := pem.Block{
   152  		Type:  "PRIVATE KEY",
   153  		Bytes: b,
   154  	}
   155  	return pem.EncodeToMemory(&block), nil
   156  }