-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkeys.go
123 lines (113 loc) · 3.62 KB
/
keys.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package sshutil
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"io"
"os"
"golang.org/x/crypto/ssh"
)
// LoadCertFromKeyFileOpenSSH returns an ssh.Signer from the unencrypted key
// stored at the given filesystem path with a public key that is the ssh
// certificate loaded from the file "<path>-cert.pub". This is how ssh-add looks
// for certs when adding keys to ssh-agent.
func LoadCertFromKeyFileOpenSSH(keypath string) (ssh.Signer, error) {
certpath := keypath + "-cert.pub"
return LoadCertFromFiles(keypath, certpath)
}
// LoadCertFromKeyFileEncOpenSSH returns an ssh.Signer from the encrypted key
// stored at the given filesystem path with a public key that is the ssh
// certificate loaded from the file "<path>-cert.pub". This is how ssh-add looks
// for certs when adding keys to ssh-agent.
func LoadCertFromKeyFileEncOpenSSH(keypath string, pass []byte) (ssh.Signer, error) {
certpath := keypath + "-cert.pub"
return LoadCertFromFilesEnc(keypath, certpath, pass)
}
// LoadCertFromFiles returns an ssh.Signer with private key loaded from the
// unecrypted path keypath and a public cert component loaded from certpath.
func LoadCertFromFiles(keypath, certpath string) (ssh.Signer, error) {
// Read host key from a file, parse using x/crypto/ssh.
kb, err := os.ReadFile(keypath)
if err != nil {
return nil, err
}
key, err := ssh.ParsePrivateKey(kb)
if err != nil {
return nil, err
}
cb, err := os.ReadFile(certpath)
if err != nil {
return nil, err
}
pub, _, _, _, err := ssh.ParseAuthorizedKey(cb)
if err != nil {
return nil, err
}
cert := pub.(*ssh.Certificate)
return ssh.NewCertSigner(cert, key)
}
// LoadCertFromFilesEnc returns an ssh.Signer with private key loaded from the
// ecrypted key at path keypath and a public cert component loaded from certpath.
func LoadCertFromFilesEnc(keypath, certpath string, pass []byte) (ssh.Signer, error) {
// Read host key from a file, parse using x/crypto/ssh.
kb, err := os.ReadFile(keypath)
if err != nil {
return nil, err
}
key, err := ssh.ParsePrivateKeyWithPassphrase(kb, pass)
if err != nil {
return nil, err
}
cb, err := os.ReadFile(certpath)
if err != nil {
return nil, err
}
pub, _, _, _, err := ssh.ParseAuthorizedKey(cb)
if err != nil {
return nil, err
}
cert := pub.(*ssh.Certificate)
return ssh.NewCertSigner(cert, key)
}
// LoadKeyFromFile returns an ssh.Signer from the unencrypted key stored
// at the given filesystem path.
func LoadKeyFromFile(path string) (ssh.Signer, error) {
// Read host key from a file, parse using x/crypto/ssh.
bytes, err := os.ReadFile(path)
if err != nil {
return nil, err
}
key, err := ssh.ParsePrivateKey(bytes)
if err != nil {
return nil, err
}
return key, nil
}
// LoadKeyFromFileWithPass returns an ssh.Signer from the key stored at the
// given filesystem path, decrypted using pass.
func LoadKeyFromFileWithPass(path, pass string) (ssh.Signer, error) {
// Read host key from a file, parse using x/crypto/ssh.
bytes, err := os.ReadFile(path)
if err != nil {
return nil, err
}
key, err := ssh.ParsePrivateKeyWithPassphrase(bytes, []byte(pass))
if err != nil {
return nil, err
}
return key, nil
}
// GenerateKey creates an in-momory ssh ecdsa p256 key to be used with the
// x/crypto/ssh package.
func GenerateKey() (ssh.Signer, error) {
return GenerateKeyRand(rand.Reader)
}
// GenerateKeyRand creates an in-momory ssh ecdsa p256 key to be used with the
// x/crypto/ssh package. Supply an arbitrary rand reader r.
func GenerateKeyRand(r io.Reader) (ssh.Signer, error) {
priv, err := ecdsa.GenerateKey(elliptic.P256(), r)
if err != nil {
return nil, err
}
return ssh.NewSignerFromSigner(priv)
}