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 }