-
-
Notifications
You must be signed in to change notification settings - Fork 25
/
ssh_test.go
229 lines (202 loc) · 9.5 KB
/
ssh_test.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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
package keys_test
import (
"encoding/hex"
"fmt"
"log"
"testing"
"github.com/keys-pub/keys"
"github.com/stretchr/testify/require"
"golang.org/x/crypto/ssh"
)
func TestSSHPublicKey(t *testing.T) {
rsa := `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDLpB8I4juBPSPPZyIMVfFpohwuyEqZOZ2qbtbbYUeS8Ag8Mk5PqLfYyPA68swf4AIBbY4JGYU3J/I0Lova4rnaqZgYFe93RCNBBTdzyKB9aTgNjYSABIvYgNVgU/gj182zVQ317Gt5OeCp3SBuUfbDp9XEdubjZXNtGO2i0gbKLHFkTB1yfTzezavX2foTK2vMR2lmid8XrQ4TMH1RhPOYumV4Uwq7ss8YMIzy4YcnfIZtO1aTsThGLyQ8r+dVYQalZF+KjwRcI+73iAVn367Q93LB+FH92cr72d38s7bKjL3VFNWkygjUXBUgLr6V8qyvC0eyWx1jCpI63mhFSR0AtjCvwvvr4mVViD8TsqIdx489j38GSSUVw9e9At7KE/Hi5tJnJuKUXtv+1+6ZJXwbXSDacPbcvcGBxBpdCYqhGPBQEUvfKTXkzlpndz4UGv85D+K8gml1CXKn9AyjPUG0d5XzlL6k+uFLIc+X7aZFtHXjdDIOzgNcghbj0PhLM2E= [email protected]`
_, err := keys.ParseSSHPublicKey(rsa)
require.EqualError(t, err, "SSH RSA key not currently supported")
ed := `ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ4jWl0FmuOcpONIojVzigw30/NppVZjiPvJGbmLKP2P [email protected]`
key, err := keys.ParseSSHPublicKey(ed)
require.NoError(t, err)
require.NotNil(t, key)
require.Equal(t, keys.ID("kex1nc345hg9nt3eef8rfz3r2uu2psma8umf54tx8z8meyvmnzeglk8s50xu7y"), key.ID())
}
func TestSSHKey(t *testing.T) {
edpriv := `-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCeI1pdBZrjnKTjSKI1c4oMN9PzaaVWY4j7yRm5iyj9jwAAAJDRmZP80ZmT
/AAAAAtzc2gtZWQyNTUxOQAAACCeI1pdBZrjnKTjSKI1c4oMN9PzaaVWY4j7yRm5iyj9jw
AAAED2F09VUc5ig2cF/HpYJQM6Jzin26cDxFGELnR5HRIF3Z4jWl0FmuOcpONIojVzigw3
0/NppVZjiPvJGbmLKP2PAAAADWdhYmVAb2subG9jYWw=
-----END OPENSSH PRIVATE KEY-----`
priv, err := keys.ParseSSHKey([]byte(edpriv), nil, true)
require.NoError(t, err)
require.NotNil(t, priv)
require.Equal(t, keys.ID("kex1nc345hg9nt3eef8rfz3r2uu2psma8umf54tx8z8meyvmnzeglk8s50xu7y"), priv.ID())
edpriv2 := `-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABALoavAb2
8dIcqlGPi6liV7AAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIDERTslBAFkDBcvs
xfvxDrCZf9ikmkyU/ElRf++wm9MSAAAAkPGjgsYt9GShNkO2ifLOMb6T2VVROP9xzDL8I5
yiN0ujsWXO8GueOBMqb08XKkZFe/UTjiKqCDjdJ6+i56T/WmKAVC5Jtw6wEcK5aUF3neXk
3lr1u4TqwOqfU1VHjnA6SynlfePhOqb/LZbtOJrXKBSnw2PUcUN7KuVq9cY61omabqpmme
+K2j/PXc0mNxIN5A==
-----END OPENSSH PRIVATE KEY-----`
_, err = keys.ParseSSHKey([]byte(edpriv2), nil, true)
require.EqualError(t, err, "failed to parse ssh key: ssh: this private key is passphrase protected")
priv, err = keys.ParseSSHKey([]byte(edpriv2), []byte("12345"), true)
require.NoError(t, err)
require.NotNil(t, priv)
require.Equal(t, keys.ID("kex1xyg5aj2pqpvsxpwtanzlhugwkzvhlk9ynfxfflzf29l7lvym6vfqswnvq3"), priv.ID())
rsa := `-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----`
_, err = keys.ParseSSHKey([]byte(rsa), nil, true)
require.EqualError(t, err, "SSH RSA key not currently supported")
}
func TestSSHEncode(t *testing.T) {
alice := keys.NewEdX25519KeyFromSeed(testSeed(0x01))
sout, err := alice.EncodeToSSH(nil)
require.NoError(t, err)
out, err := keys.ParseSSHKey(sout, nil, false)
require.NoError(t, err)
require.NotNil(t, out)
require.Equal(t, out.Private(), alice.Private())
require.Equal(t, out.Public(), alice.Public())
sout, err = alice.EncodeToSSH([]byte{})
require.NoError(t, err)
out, err = keys.ParseSSHKey(sout, nil, false)
require.NoError(t, err)
require.NotNil(t, out)
require.Equal(t, out.Private(), alice.Private())
require.Equal(t, out.Public(), alice.Public())
sout, err = alice.EncodeToSSH(nil)
require.NoError(t, err)
_, err = ssh.ParsePrivateKey(sout)
require.NoError(t, err)
// TODO: Verify bytes
sout, err = alice.EncodeToSSH([]byte("testpassword"))
require.NoError(t, err)
_, err = keys.ParseSSHKey(sout, nil, false)
require.EqualError(t, err, "failed to parse ssh key: ssh: this private key is passphrase protected")
out, err = keys.ParseSSHKey(sout, []byte("testpassword"), false)
require.NoError(t, err)
require.NotNil(t, out)
require.Equal(t, out.Private(), alice.Private())
require.Equal(t, out.Public(), alice.Public())
sout, err = alice.EncodeToSSH([]byte("testpassword"))
require.NoError(t, err)
_, err = ssh.ParsePrivateKeyWithPassphrase(sout, []byte("testpassword"))
require.NoError(t, err)
// TODO: Verify bytes
}
func TestSSHEncodePublic(t *testing.T) {
alice := keys.NewEdX25519KeyFromSeed(testSeed(0x01))
b := alice.PublicKey().EncodeToSSHAuthorized()
out, err := keys.ParseSSHPublicKey(string(b))
require.NoError(t, err)
require.Equal(t, out.Public(), alice.PublicKey().Bytes())
}
func TestEncodeDecodeSSHKey(t *testing.T) {
sk := keys.NewEdX25519KeyFromSeed(testSeed(0x01))
// SSH (public)
msg, err := keys.EncodeSSHKey(sk.PublicKey(), "")
require.NoError(t, err)
out, err := keys.DecodeSSHKey(msg, "")
require.NoError(t, err)
require.Equal(t, sk.PublicKey().Type(), out.Type())
require.Equal(t, sk.PublicKey().Public(), out.Public())
// SSH (password)
msg, err = keys.EncodeSSHKey(sk, "testpassword")
require.NoError(t, err)
out, err = keys.DecodeSSHKey(msg, "testpassword")
require.NoError(t, err)
require.Equal(t, sk.Type(), out.Type())
require.Equal(t, sk.Private(), out.Private())
require.Equal(t, sk.Public(), out.Public())
// SSH (password, helper)
msg, err = keys.EncodeSSHKey(sk, "testpassword")
require.NoError(t, err)
out, err = keys.DecodeSSHKey(msg, "testpassword")
require.NoError(t, err)
require.Equal(t, sk.Type(), out.Type())
require.Equal(t, sk.Private(), out.Private())
require.Equal(t, sk.Public(), out.Public())
// SSH (no password)
msg, err = keys.EncodeSSHKey(sk, "")
require.NoError(t, err)
out, err = keys.DecodeSSHKey(msg, "")
require.NoError(t, err)
require.Equal(t, sk.Type(), out.Type())
require.Equal(t, sk.Private(), out.Private())
require.Equal(t, sk.Public(), out.Public())
// SSH (no password, helper)
msg, err = keys.EncodeSSHKey(sk, "")
require.NoError(t, err)
out, err = keys.DecodeSSHKey(msg, "")
require.NoError(t, err)
require.Equal(t, sk.Type(), out.Type())
require.Equal(t, sk.Private(), out.Private())
require.Equal(t, sk.Public(), out.Public())
// SSH
pk, err := keys.DecodeSSHKey("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIqI4910CfGV/VLbLTy6XXLKZwm/HZQSG/N0iAG0D29c", "")
require.NoError(t, err)
require.Equal(t, "8a88e3dd7409f195fd52db2d3cba5d72ca6709bf1d94121bf3748801b40f6f5c", hex.EncodeToString(pk.Public()))
// Errors
_, err = keys.DecodeSSHKey("", "")
require.EqualError(t, err, "failed to parse ssh key: ssh: no key found")
}
func ExampleEncodeSSHKey() {
sk := keys.GenerateEdX25519Key()
privateKey, err := keys.EncodeSSHKey(sk, "testpassword")
if err != nil {
log.Fatal(err)
}
log.Printf("%s\n", privateKey)
publicKey, err := keys.EncodeSSHKey(sk.PublicKey(), "")
if err != nil {
log.Fatal(err)
}
log.Printf("%s\n", publicKey)
// Output:
//
}
func ExampleDecodeSSHKey() {
pk, err := keys.DecodeSSHKey("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIqI4910CfGV/VLbLTy6XXLKZwm/HZQSG/N0iAG0D29c", "")
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", pk.ID())
// Output: kex132yw8ht5p8cetl2jmvknewjawt9xwzdlrk2pyxlnwjyqrdq0dawqqph077
}