main
1// Copyright 2012 The Go 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
5package ssh
6
7import (
8 "bytes"
9 "crypto"
10 "crypto/aes"
11 "crypto/cipher"
12 "crypto/dsa"
13 "crypto/ecdsa"
14 "crypto/ed25519"
15 "crypto/elliptic"
16 "crypto/md5"
17 "crypto/rand"
18 "crypto/rsa"
19 "crypto/sha256"
20 "crypto/x509"
21 "encoding/asn1"
22 "encoding/base64"
23 "encoding/binary"
24 "encoding/hex"
25 "encoding/pem"
26 "errors"
27 "fmt"
28 "io"
29 "math/big"
30 "strings"
31
32 "golang.org/x/crypto/ssh/internal/bcrypt_pbkdf"
33)
34
35// Public key algorithms names. These values can appear in PublicKey.Type,
36// ClientConfig.HostKeyAlgorithms, Signature.Format, or as AlgorithmSigner
37// arguments.
38const (
39 KeyAlgoRSA = "ssh-rsa"
40 KeyAlgoDSA = "ssh-dss"
41 KeyAlgoECDSA256 = "ecdsa-sha2-nistp256"
42 KeyAlgoSKECDSA256 = "sk-ecdsa-sha2-nistp256@openssh.com"
43 KeyAlgoECDSA384 = "ecdsa-sha2-nistp384"
44 KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
45 KeyAlgoED25519 = "ssh-ed25519"
46 KeyAlgoSKED25519 = "sk-ssh-ed25519@openssh.com"
47
48 // KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms, not
49 // public key formats, so they can't appear as a PublicKey.Type. The
50 // corresponding PublicKey.Type is KeyAlgoRSA. See RFC 8332, Section 2.
51 KeyAlgoRSASHA256 = "rsa-sha2-256"
52 KeyAlgoRSASHA512 = "rsa-sha2-512"
53)
54
55const (
56 // Deprecated: use KeyAlgoRSA.
57 SigAlgoRSA = KeyAlgoRSA
58 // Deprecated: use KeyAlgoRSASHA256.
59 SigAlgoRSASHA2256 = KeyAlgoRSASHA256
60 // Deprecated: use KeyAlgoRSASHA512.
61 SigAlgoRSASHA2512 = KeyAlgoRSASHA512
62)
63
64// parsePubKey parses a public key of the given algorithm.
65// Use ParsePublicKey for keys with prepended algorithm.
66func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err error) {
67 switch algo {
68 case KeyAlgoRSA:
69 return parseRSA(in)
70 case KeyAlgoDSA:
71 return parseDSA(in)
72 case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
73 return parseECDSA(in)
74 case KeyAlgoSKECDSA256:
75 return parseSKECDSA(in)
76 case KeyAlgoED25519:
77 return parseED25519(in)
78 case KeyAlgoSKED25519:
79 return parseSKEd25519(in)
80 case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
81 cert, err := parseCert(in, certKeyAlgoNames[algo])
82 if err != nil {
83 return nil, nil, err
84 }
85 return cert, nil, nil
86 }
87 return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", algo)
88}
89
90// parseAuthorizedKey parses a public key in OpenSSH authorized_keys format
91// (see sshd(8) manual page) once the options and key type fields have been
92// removed.
93func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) {
94 in = bytes.TrimSpace(in)
95
96 i := bytes.IndexAny(in, " \t")
97 if i == -1 {
98 i = len(in)
99 }
100 base64Key := in[:i]
101
102 key := make([]byte, base64.StdEncoding.DecodedLen(len(base64Key)))
103 n, err := base64.StdEncoding.Decode(key, base64Key)
104 if err != nil {
105 return nil, "", err
106 }
107 key = key[:n]
108 out, err = ParsePublicKey(key)
109 if err != nil {
110 return nil, "", err
111 }
112 comment = string(bytes.TrimSpace(in[i:]))
113 return out, comment, nil
114}
115
116// ParseKnownHosts parses an entry in the format of the known_hosts file.
117//
118// The known_hosts format is documented in the sshd(8) manual page. This
119// function will parse a single entry from in. On successful return, marker
120// will contain the optional marker value (i.e. "cert-authority" or "revoked")
121// or else be empty, hosts will contain the hosts that this entry matches,
122// pubKey will contain the public key and comment will contain any trailing
123// comment at the end of the line. See the sshd(8) manual page for the various
124// forms that a host string can take.
125//
126// The unparsed remainder of the input will be returned in rest. This function
127// can be called repeatedly to parse multiple entries.
128//
129// If no entries were found in the input then err will be io.EOF. Otherwise a
130// non-nil err value indicates a parse error.
131func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey, comment string, rest []byte, err error) {
132 for len(in) > 0 {
133 end := bytes.IndexByte(in, '\n')
134 if end != -1 {
135 rest = in[end+1:]
136 in = in[:end]
137 } else {
138 rest = nil
139 }
140
141 end = bytes.IndexByte(in, '\r')
142 if end != -1 {
143 in = in[:end]
144 }
145
146 in = bytes.TrimSpace(in)
147 if len(in) == 0 || in[0] == '#' {
148 in = rest
149 continue
150 }
151
152 i := bytes.IndexAny(in, " \t")
153 if i == -1 {
154 in = rest
155 continue
156 }
157
158 // Strip out the beginning of the known_host key.
159 // This is either an optional marker or a (set of) hostname(s).
160 keyFields := bytes.Fields(in)
161 if len(keyFields) < 3 || len(keyFields) > 5 {
162 return "", nil, nil, "", nil, errors.New("ssh: invalid entry in known_hosts data")
163 }
164
165 // keyFields[0] is either "@cert-authority", "@revoked" or a comma separated
166 // list of hosts
167 marker := ""
168 if keyFields[0][0] == '@' {
169 marker = string(keyFields[0][1:])
170 keyFields = keyFields[1:]
171 }
172
173 hosts := string(keyFields[0])
174 // keyFields[1] contains the key type (e.g. “ssh-rsa”).
175 // However, that information is duplicated inside the
176 // base64-encoded key and so is ignored here.
177
178 key := bytes.Join(keyFields[2:], []byte(" "))
179 if pubKey, comment, err = parseAuthorizedKey(key); err != nil {
180 return "", nil, nil, "", nil, err
181 }
182
183 return marker, strings.Split(hosts, ","), pubKey, comment, rest, nil
184 }
185
186 return "", nil, nil, "", nil, io.EOF
187}
188
189// ParseAuthorizedKey parses a public key from an authorized_keys
190// file used in OpenSSH according to the sshd(8) manual page.
191func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) {
192 for len(in) > 0 {
193 end := bytes.IndexByte(in, '\n')
194 if end != -1 {
195 rest = in[end+1:]
196 in = in[:end]
197 } else {
198 rest = nil
199 }
200
201 end = bytes.IndexByte(in, '\r')
202 if end != -1 {
203 in = in[:end]
204 }
205
206 in = bytes.TrimSpace(in)
207 if len(in) == 0 || in[0] == '#' {
208 in = rest
209 continue
210 }
211
212 i := bytes.IndexAny(in, " \t")
213 if i == -1 {
214 in = rest
215 continue
216 }
217
218 if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
219 return out, comment, options, rest, nil
220 }
221
222 // No key type recognised. Maybe there's an options field at
223 // the beginning.
224 var b byte
225 inQuote := false
226 var candidateOptions []string
227 optionStart := 0
228 for i, b = range in {
229 isEnd := !inQuote && (b == ' ' || b == '\t')
230 if (b == ',' && !inQuote) || isEnd {
231 if i-optionStart > 0 {
232 candidateOptions = append(candidateOptions, string(in[optionStart:i]))
233 }
234 optionStart = i + 1
235 }
236 if isEnd {
237 break
238 }
239 if b == '"' && (i == 0 || (i > 0 && in[i-1] != '\\')) {
240 inQuote = !inQuote
241 }
242 }
243 for i < len(in) && (in[i] == ' ' || in[i] == '\t') {
244 i++
245 }
246 if i == len(in) {
247 // Invalid line: unmatched quote
248 in = rest
249 continue
250 }
251
252 in = in[i:]
253 i = bytes.IndexAny(in, " \t")
254 if i == -1 {
255 in = rest
256 continue
257 }
258
259 if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
260 options = candidateOptions
261 return out, comment, options, rest, nil
262 }
263
264 in = rest
265 continue
266 }
267
268 return nil, "", nil, nil, errors.New("ssh: no key found")
269}
270
271// ParsePublicKey parses an SSH public key formatted for use in
272// the SSH wire protocol according to RFC 4253, section 6.6.
273func ParsePublicKey(in []byte) (out PublicKey, err error) {
274 algo, in, ok := parseString(in)
275 if !ok {
276 return nil, errShortRead
277 }
278 var rest []byte
279 out, rest, err = parsePubKey(in, string(algo))
280 if len(rest) > 0 {
281 return nil, errors.New("ssh: trailing junk in public key")
282 }
283
284 return out, err
285}
286
287// MarshalAuthorizedKey serializes key for inclusion in an OpenSSH
288// authorized_keys file. The return value ends with newline.
289func MarshalAuthorizedKey(key PublicKey) []byte {
290 b := &bytes.Buffer{}
291 b.WriteString(key.Type())
292 b.WriteByte(' ')
293 e := base64.NewEncoder(base64.StdEncoding, b)
294 e.Write(key.Marshal())
295 e.Close()
296 b.WriteByte('\n')
297 return b.Bytes()
298}
299
300// MarshalPrivateKey returns a PEM block with the private key serialized in the
301// OpenSSH format.
302func MarshalPrivateKey(key crypto.PrivateKey, comment string) (*pem.Block, error) {
303 return marshalOpenSSHPrivateKey(key, comment, unencryptedOpenSSHMarshaler)
304}
305
306// MarshalPrivateKeyWithPassphrase returns a PEM block holding the encrypted
307// private key serialized in the OpenSSH format.
308func MarshalPrivateKeyWithPassphrase(key crypto.PrivateKey, comment string, passphrase []byte) (*pem.Block, error) {
309 return marshalOpenSSHPrivateKey(key, comment, passphraseProtectedOpenSSHMarshaler(passphrase))
310}
311
312// PublicKey represents a public key using an unspecified algorithm.
313//
314// Some PublicKeys provided by this package also implement CryptoPublicKey.
315type PublicKey interface {
316 // Type returns the key format name, e.g. "ssh-rsa".
317 Type() string
318
319 // Marshal returns the serialized key data in SSH wire format, with the name
320 // prefix. To unmarshal the returned data, use the ParsePublicKey function.
321 Marshal() []byte
322
323 // Verify that sig is a signature on the given data using this key. This
324 // method will hash the data appropriately first. sig.Format is allowed to
325 // be any signature algorithm compatible with the key type, the caller
326 // should check if it has more stringent requirements.
327 Verify(data []byte, sig *Signature) error
328}
329
330// CryptoPublicKey, if implemented by a PublicKey,
331// returns the underlying crypto.PublicKey form of the key.
332type CryptoPublicKey interface {
333 CryptoPublicKey() crypto.PublicKey
334}
335
336// A Signer can create signatures that verify against a public key.
337//
338// Some Signers provided by this package also implement MultiAlgorithmSigner.
339type Signer interface {
340 // PublicKey returns the associated PublicKey.
341 PublicKey() PublicKey
342
343 // Sign returns a signature for the given data. This method will hash the
344 // data appropriately first. The signature algorithm is expected to match
345 // the key format returned by the PublicKey.Type method (and not to be any
346 // alternative algorithm supported by the key format).
347 Sign(rand io.Reader, data []byte) (*Signature, error)
348}
349
350// An AlgorithmSigner is a Signer that also supports specifying an algorithm to
351// use for signing.
352//
353// An AlgorithmSigner can't advertise the algorithms it supports, unless it also
354// implements MultiAlgorithmSigner, so it should be prepared to be invoked with
355// every algorithm supported by the public key format.
356type AlgorithmSigner interface {
357 Signer
358
359 // SignWithAlgorithm is like Signer.Sign, but allows specifying a desired
360 // signing algorithm. Callers may pass an empty string for the algorithm in
361 // which case the AlgorithmSigner will use a default algorithm. This default
362 // doesn't currently control any behavior in this package.
363 SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error)
364}
365
366// MultiAlgorithmSigner is an AlgorithmSigner that also reports the algorithms
367// supported by that signer.
368type MultiAlgorithmSigner interface {
369 AlgorithmSigner
370
371 // Algorithms returns the available algorithms in preference order. The list
372 // must not be empty, and it must not include certificate types.
373 Algorithms() []string
374}
375
376// NewSignerWithAlgorithms returns a signer restricted to the specified
377// algorithms. The algorithms must be set in preference order. The list must not
378// be empty, and it must not include certificate types. An error is returned if
379// the specified algorithms are incompatible with the public key type.
380func NewSignerWithAlgorithms(signer AlgorithmSigner, algorithms []string) (MultiAlgorithmSigner, error) {
381 if len(algorithms) == 0 {
382 return nil, errors.New("ssh: please specify at least one valid signing algorithm")
383 }
384 var signerAlgos []string
385 supportedAlgos := algorithmsForKeyFormat(underlyingAlgo(signer.PublicKey().Type()))
386 if s, ok := signer.(*multiAlgorithmSigner); ok {
387 signerAlgos = s.Algorithms()
388 } else {
389 signerAlgos = supportedAlgos
390 }
391
392 for _, algo := range algorithms {
393 if !contains(supportedAlgos, algo) {
394 return nil, fmt.Errorf("ssh: algorithm %q is not supported for key type %q",
395 algo, signer.PublicKey().Type())
396 }
397 if !contains(signerAlgos, algo) {
398 return nil, fmt.Errorf("ssh: algorithm %q is restricted for the provided signer", algo)
399 }
400 }
401 return &multiAlgorithmSigner{
402 AlgorithmSigner: signer,
403 supportedAlgorithms: algorithms,
404 }, nil
405}
406
407type multiAlgorithmSigner struct {
408 AlgorithmSigner
409 supportedAlgorithms []string
410}
411
412func (s *multiAlgorithmSigner) Algorithms() []string {
413 return s.supportedAlgorithms
414}
415
416func (s *multiAlgorithmSigner) isAlgorithmSupported(algorithm string) bool {
417 if algorithm == "" {
418 algorithm = underlyingAlgo(s.PublicKey().Type())
419 }
420 for _, algo := range s.supportedAlgorithms {
421 if algorithm == algo {
422 return true
423 }
424 }
425 return false
426}
427
428func (s *multiAlgorithmSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
429 if !s.isAlgorithmSupported(algorithm) {
430 return nil, fmt.Errorf("ssh: algorithm %q is not supported: %v", algorithm, s.supportedAlgorithms)
431 }
432 return s.AlgorithmSigner.SignWithAlgorithm(rand, data, algorithm)
433}
434
435type rsaPublicKey rsa.PublicKey
436
437func (r *rsaPublicKey) Type() string {
438 return "ssh-rsa"
439}
440
441// parseRSA parses an RSA key according to RFC 4253, section 6.6.
442func parseRSA(in []byte) (out PublicKey, rest []byte, err error) {
443 var w struct {
444 E *big.Int
445 N *big.Int
446 Rest []byte `ssh:"rest"`
447 }
448 if err := Unmarshal(in, &w); err != nil {
449 return nil, nil, err
450 }
451
452 if w.E.BitLen() > 24 {
453 return nil, nil, errors.New("ssh: exponent too large")
454 }
455 e := w.E.Int64()
456 if e < 3 || e&1 == 0 {
457 return nil, nil, errors.New("ssh: incorrect exponent")
458 }
459
460 var key rsa.PublicKey
461 key.E = int(e)
462 key.N = w.N
463 return (*rsaPublicKey)(&key), w.Rest, nil
464}
465
466func (r *rsaPublicKey) Marshal() []byte {
467 e := new(big.Int).SetInt64(int64(r.E))
468 // RSA publickey struct layout should match the struct used by
469 // parseRSACert in the x/crypto/ssh/agent package.
470 wirekey := struct {
471 Name string
472 E *big.Int
473 N *big.Int
474 }{
475 KeyAlgoRSA,
476 e,
477 r.N,
478 }
479 return Marshal(&wirekey)
480}
481
482func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error {
483 supportedAlgos := algorithmsForKeyFormat(r.Type())
484 if !contains(supportedAlgos, sig.Format) {
485 return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type())
486 }
487 hash := hashFuncs[sig.Format]
488 h := hash.New()
489 h.Write(data)
490 digest := h.Sum(nil)
491
492 // Signatures in PKCS1v15 must match the key's modulus in
493 // length. However with SSH, some signers provide RSA
494 // signatures which are missing the MSB 0's of the bignum
495 // represented. With ssh-rsa signatures, this is encouraged by
496 // the spec (even though e.g. OpenSSH will give the full
497 // length unconditionally). With rsa-sha2-* signatures, the
498 // verifier is allowed to support these, even though they are
499 // out of spec. See RFC 4253 Section 6.6 for ssh-rsa and RFC
500 // 8332 Section 3 for rsa-sha2-* details.
501 //
502 // In practice:
503 // * OpenSSH always allows "short" signatures:
504 // https://github.com/openssh/openssh-portable/blob/V_9_8_P1/ssh-rsa.c#L526
505 // but always generates padded signatures:
506 // https://github.com/openssh/openssh-portable/blob/V_9_8_P1/ssh-rsa.c#L439
507 //
508 // * PuTTY versions 0.81 and earlier will generate short
509 // signatures for all RSA signature variants. Note that
510 // PuTTY is embedded in other software, such as WinSCP and
511 // FileZilla. At the time of writing, a patch has been
512 // applied to PuTTY to generate padded signatures for
513 // rsa-sha2-*, but not yet released:
514 // https://git.tartarus.org/?p=simon/putty.git;a=commitdiff;h=a5bcf3d384e1bf15a51a6923c3724cbbee022d8e
515 //
516 // * SSH.NET versions 2024.0.0 and earlier will generate short
517 // signatures for all RSA signature variants, fixed in 2024.1.0:
518 // https://github.com/sshnet/SSH.NET/releases/tag/2024.1.0
519 //
520 // As a result, we pad these up to the key size by inserting
521 // leading 0's.
522 //
523 // Note that support for short signatures with rsa-sha2-* may
524 // be removed in the future due to such signatures not being
525 // allowed by the spec.
526 blob := sig.Blob
527 keySize := (*rsa.PublicKey)(r).Size()
528 if len(blob) < keySize {
529 padded := make([]byte, keySize)
530 copy(padded[keySize-len(blob):], blob)
531 blob = padded
532 }
533 return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), hash, digest, blob)
534}
535
536func (r *rsaPublicKey) CryptoPublicKey() crypto.PublicKey {
537 return (*rsa.PublicKey)(r)
538}
539
540type dsaPublicKey dsa.PublicKey
541
542func (k *dsaPublicKey) Type() string {
543 return "ssh-dss"
544}
545
546func checkDSAParams(param *dsa.Parameters) error {
547 // SSH specifies FIPS 186-2, which only provided a single size
548 // (1024 bits) DSA key. FIPS 186-3 allows for larger key
549 // sizes, which would confuse SSH.
550 if l := param.P.BitLen(); l != 1024 {
551 return fmt.Errorf("ssh: unsupported DSA key size %d", l)
552 }
553
554 return nil
555}
556
557// parseDSA parses an DSA key according to RFC 4253, section 6.6.
558func parseDSA(in []byte) (out PublicKey, rest []byte, err error) {
559 var w struct {
560 P, Q, G, Y *big.Int
561 Rest []byte `ssh:"rest"`
562 }
563 if err := Unmarshal(in, &w); err != nil {
564 return nil, nil, err
565 }
566
567 param := dsa.Parameters{
568 P: w.P,
569 Q: w.Q,
570 G: w.G,
571 }
572 if err := checkDSAParams(¶m); err != nil {
573 return nil, nil, err
574 }
575
576 key := &dsaPublicKey{
577 Parameters: param,
578 Y: w.Y,
579 }
580 return key, w.Rest, nil
581}
582
583func (k *dsaPublicKey) Marshal() []byte {
584 // DSA publickey struct layout should match the struct used by
585 // parseDSACert in the x/crypto/ssh/agent package.
586 w := struct {
587 Name string
588 P, Q, G, Y *big.Int
589 }{
590 k.Type(),
591 k.P,
592 k.Q,
593 k.G,
594 k.Y,
595 }
596
597 return Marshal(&w)
598}
599
600func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error {
601 if sig.Format != k.Type() {
602 return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
603 }
604 h := hashFuncs[sig.Format].New()
605 h.Write(data)
606 digest := h.Sum(nil)
607
608 // Per RFC 4253, section 6.6,
609 // The value for 'dss_signature_blob' is encoded as a string containing
610 // r, followed by s (which are 160-bit integers, without lengths or
611 // padding, unsigned, and in network byte order).
612 // For DSS purposes, sig.Blob should be exactly 40 bytes in length.
613 if len(sig.Blob) != 40 {
614 return errors.New("ssh: DSA signature parse error")
615 }
616 r := new(big.Int).SetBytes(sig.Blob[:20])
617 s := new(big.Int).SetBytes(sig.Blob[20:])
618 if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) {
619 return nil
620 }
621 return errors.New("ssh: signature did not verify")
622}
623
624func (k *dsaPublicKey) CryptoPublicKey() crypto.PublicKey {
625 return (*dsa.PublicKey)(k)
626}
627
628type dsaPrivateKey struct {
629 *dsa.PrivateKey
630}
631
632func (k *dsaPrivateKey) PublicKey() PublicKey {
633 return (*dsaPublicKey)(&k.PrivateKey.PublicKey)
634}
635
636func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
637 return k.SignWithAlgorithm(rand, data, k.PublicKey().Type())
638}
639
640func (k *dsaPrivateKey) Algorithms() []string {
641 return []string{k.PublicKey().Type()}
642}
643
644func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
645 if algorithm != "" && algorithm != k.PublicKey().Type() {
646 return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm)
647 }
648
649 h := hashFuncs[k.PublicKey().Type()].New()
650 h.Write(data)
651 digest := h.Sum(nil)
652 r, s, err := dsa.Sign(rand, k.PrivateKey, digest)
653 if err != nil {
654 return nil, err
655 }
656
657 sig := make([]byte, 40)
658 rb := r.Bytes()
659 sb := s.Bytes()
660
661 copy(sig[20-len(rb):20], rb)
662 copy(sig[40-len(sb):], sb)
663
664 return &Signature{
665 Format: k.PublicKey().Type(),
666 Blob: sig,
667 }, nil
668}
669
670type ecdsaPublicKey ecdsa.PublicKey
671
672func (k *ecdsaPublicKey) Type() string {
673 return "ecdsa-sha2-" + k.nistID()
674}
675
676func (k *ecdsaPublicKey) nistID() string {
677 switch k.Params().BitSize {
678 case 256:
679 return "nistp256"
680 case 384:
681 return "nistp384"
682 case 521:
683 return "nistp521"
684 }
685 panic("ssh: unsupported ecdsa key size")
686}
687
688type ed25519PublicKey ed25519.PublicKey
689
690func (k ed25519PublicKey) Type() string {
691 return KeyAlgoED25519
692}
693
694func parseED25519(in []byte) (out PublicKey, rest []byte, err error) {
695 var w struct {
696 KeyBytes []byte
697 Rest []byte `ssh:"rest"`
698 }
699
700 if err := Unmarshal(in, &w); err != nil {
701 return nil, nil, err
702 }
703
704 if l := len(w.KeyBytes); l != ed25519.PublicKeySize {
705 return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l)
706 }
707
708 return ed25519PublicKey(w.KeyBytes), w.Rest, nil
709}
710
711func (k ed25519PublicKey) Marshal() []byte {
712 w := struct {
713 Name string
714 KeyBytes []byte
715 }{
716 KeyAlgoED25519,
717 []byte(k),
718 }
719 return Marshal(&w)
720}
721
722func (k ed25519PublicKey) Verify(b []byte, sig *Signature) error {
723 if sig.Format != k.Type() {
724 return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
725 }
726 if l := len(k); l != ed25519.PublicKeySize {
727 return fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l)
728 }
729
730 if ok := ed25519.Verify(ed25519.PublicKey(k), b, sig.Blob); !ok {
731 return errors.New("ssh: signature did not verify")
732 }
733
734 return nil
735}
736
737func (k ed25519PublicKey) CryptoPublicKey() crypto.PublicKey {
738 return ed25519.PublicKey(k)
739}
740
741func supportedEllipticCurve(curve elliptic.Curve) bool {
742 return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
743}
744
745// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1.
746func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
747 var w struct {
748 Curve string
749 KeyBytes []byte
750 Rest []byte `ssh:"rest"`
751 }
752
753 if err := Unmarshal(in, &w); err != nil {
754 return nil, nil, err
755 }
756
757 key := new(ecdsa.PublicKey)
758
759 switch w.Curve {
760 case "nistp256":
761 key.Curve = elliptic.P256()
762 case "nistp384":
763 key.Curve = elliptic.P384()
764 case "nistp521":
765 key.Curve = elliptic.P521()
766 default:
767 return nil, nil, errors.New("ssh: unsupported curve")
768 }
769
770 key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes)
771 if key.X == nil || key.Y == nil {
772 return nil, nil, errors.New("ssh: invalid curve point")
773 }
774 return (*ecdsaPublicKey)(key), w.Rest, nil
775}
776
777func (k *ecdsaPublicKey) Marshal() []byte {
778 // See RFC 5656, section 3.1.
779 keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y)
780 // ECDSA publickey struct layout should match the struct used by
781 // parseECDSACert in the x/crypto/ssh/agent package.
782 w := struct {
783 Name string
784 ID string
785 Key []byte
786 }{
787 k.Type(),
788 k.nistID(),
789 keyBytes,
790 }
791
792 return Marshal(&w)
793}
794
795func (k *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
796 if sig.Format != k.Type() {
797 return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
798 }
799
800 h := hashFuncs[sig.Format].New()
801 h.Write(data)
802 digest := h.Sum(nil)
803
804 // Per RFC 5656, section 3.1.2,
805 // The ecdsa_signature_blob value has the following specific encoding:
806 // mpint r
807 // mpint s
808 var ecSig struct {
809 R *big.Int
810 S *big.Int
811 }
812
813 if err := Unmarshal(sig.Blob, &ecSig); err != nil {
814 return err
815 }
816
817 if ecdsa.Verify((*ecdsa.PublicKey)(k), digest, ecSig.R, ecSig.S) {
818 return nil
819 }
820 return errors.New("ssh: signature did not verify")
821}
822
823func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey {
824 return (*ecdsa.PublicKey)(k)
825}
826
827// skFields holds the additional fields present in U2F/FIDO2 signatures.
828// See openssh/PROTOCOL.u2f 'SSH U2F Signatures' for details.
829type skFields struct {
830 // Flags contains U2F/FIDO2 flags such as 'user present'
831 Flags byte
832 // Counter is a monotonic signature counter which can be
833 // used to detect concurrent use of a private key, should
834 // it be extracted from hardware.
835 Counter uint32
836}
837
838type skECDSAPublicKey struct {
839 // application is a URL-like string, typically "ssh:" for SSH.
840 // see openssh/PROTOCOL.u2f for details.
841 application string
842 ecdsa.PublicKey
843}
844
845func (k *skECDSAPublicKey) Type() string {
846 return KeyAlgoSKECDSA256
847}
848
849func (k *skECDSAPublicKey) nistID() string {
850 return "nistp256"
851}
852
853func parseSKECDSA(in []byte) (out PublicKey, rest []byte, err error) {
854 var w struct {
855 Curve string
856 KeyBytes []byte
857 Application string
858 Rest []byte `ssh:"rest"`
859 }
860
861 if err := Unmarshal(in, &w); err != nil {
862 return nil, nil, err
863 }
864
865 key := new(skECDSAPublicKey)
866 key.application = w.Application
867
868 if w.Curve != "nistp256" {
869 return nil, nil, errors.New("ssh: unsupported curve")
870 }
871 key.Curve = elliptic.P256()
872
873 key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes)
874 if key.X == nil || key.Y == nil {
875 return nil, nil, errors.New("ssh: invalid curve point")
876 }
877
878 return key, w.Rest, nil
879}
880
881func (k *skECDSAPublicKey) Marshal() []byte {
882 // See RFC 5656, section 3.1.
883 keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y)
884 w := struct {
885 Name string
886 ID string
887 Key []byte
888 Application string
889 }{
890 k.Type(),
891 k.nistID(),
892 keyBytes,
893 k.application,
894 }
895
896 return Marshal(&w)
897}
898
899func (k *skECDSAPublicKey) Verify(data []byte, sig *Signature) error {
900 if sig.Format != k.Type() {
901 return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
902 }
903
904 h := hashFuncs[sig.Format].New()
905 h.Write([]byte(k.application))
906 appDigest := h.Sum(nil)
907
908 h.Reset()
909 h.Write(data)
910 dataDigest := h.Sum(nil)
911
912 var ecSig struct {
913 R *big.Int
914 S *big.Int
915 }
916 if err := Unmarshal(sig.Blob, &ecSig); err != nil {
917 return err
918 }
919
920 var skf skFields
921 if err := Unmarshal(sig.Rest, &skf); err != nil {
922 return err
923 }
924
925 blob := struct {
926 ApplicationDigest []byte `ssh:"rest"`
927 Flags byte
928 Counter uint32
929 MessageDigest []byte `ssh:"rest"`
930 }{
931 appDigest,
932 skf.Flags,
933 skf.Counter,
934 dataDigest,
935 }
936
937 original := Marshal(blob)
938
939 h.Reset()
940 h.Write(original)
941 digest := h.Sum(nil)
942
943 if ecdsa.Verify((*ecdsa.PublicKey)(&k.PublicKey), digest, ecSig.R, ecSig.S) {
944 return nil
945 }
946 return errors.New("ssh: signature did not verify")
947}
948
949func (k *skECDSAPublicKey) CryptoPublicKey() crypto.PublicKey {
950 return &k.PublicKey
951}
952
953type skEd25519PublicKey struct {
954 // application is a URL-like string, typically "ssh:" for SSH.
955 // see openssh/PROTOCOL.u2f for details.
956 application string
957 ed25519.PublicKey
958}
959
960func (k *skEd25519PublicKey) Type() string {
961 return KeyAlgoSKED25519
962}
963
964func parseSKEd25519(in []byte) (out PublicKey, rest []byte, err error) {
965 var w struct {
966 KeyBytes []byte
967 Application string
968 Rest []byte `ssh:"rest"`
969 }
970
971 if err := Unmarshal(in, &w); err != nil {
972 return nil, nil, err
973 }
974
975 if l := len(w.KeyBytes); l != ed25519.PublicKeySize {
976 return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l)
977 }
978
979 key := new(skEd25519PublicKey)
980 key.application = w.Application
981 key.PublicKey = ed25519.PublicKey(w.KeyBytes)
982
983 return key, w.Rest, nil
984}
985
986func (k *skEd25519PublicKey) Marshal() []byte {
987 w := struct {
988 Name string
989 KeyBytes []byte
990 Application string
991 }{
992 KeyAlgoSKED25519,
993 []byte(k.PublicKey),
994 k.application,
995 }
996 return Marshal(&w)
997}
998
999func (k *skEd25519PublicKey) Verify(data []byte, sig *Signature) error {
1000 if sig.Format != k.Type() {
1001 return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
1002 }
1003 if l := len(k.PublicKey); l != ed25519.PublicKeySize {
1004 return fmt.Errorf("invalid size %d for Ed25519 public key", l)
1005 }
1006
1007 h := hashFuncs[sig.Format].New()
1008 h.Write([]byte(k.application))
1009 appDigest := h.Sum(nil)
1010
1011 h.Reset()
1012 h.Write(data)
1013 dataDigest := h.Sum(nil)
1014
1015 var edSig struct {
1016 Signature []byte `ssh:"rest"`
1017 }
1018
1019 if err := Unmarshal(sig.Blob, &edSig); err != nil {
1020 return err
1021 }
1022
1023 var skf skFields
1024 if err := Unmarshal(sig.Rest, &skf); err != nil {
1025 return err
1026 }
1027
1028 blob := struct {
1029 ApplicationDigest []byte `ssh:"rest"`
1030 Flags byte
1031 Counter uint32
1032 MessageDigest []byte `ssh:"rest"`
1033 }{
1034 appDigest,
1035 skf.Flags,
1036 skf.Counter,
1037 dataDigest,
1038 }
1039
1040 original := Marshal(blob)
1041
1042 if ok := ed25519.Verify(k.PublicKey, original, edSig.Signature); !ok {
1043 return errors.New("ssh: signature did not verify")
1044 }
1045
1046 return nil
1047}
1048
1049func (k *skEd25519PublicKey) CryptoPublicKey() crypto.PublicKey {
1050 return k.PublicKey
1051}
1052
1053// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey,
1054// *ecdsa.PrivateKey or any other crypto.Signer and returns a
1055// corresponding Signer instance. ECDSA keys must use P-256, P-384 or
1056// P-521. DSA keys must use parameter size L1024N160.
1057func NewSignerFromKey(key interface{}) (Signer, error) {
1058 switch key := key.(type) {
1059 case crypto.Signer:
1060 return NewSignerFromSigner(key)
1061 case *dsa.PrivateKey:
1062 return newDSAPrivateKey(key)
1063 default:
1064 return nil, fmt.Errorf("ssh: unsupported key type %T", key)
1065 }
1066}
1067
1068func newDSAPrivateKey(key *dsa.PrivateKey) (Signer, error) {
1069 if err := checkDSAParams(&key.PublicKey.Parameters); err != nil {
1070 return nil, err
1071 }
1072
1073 return &dsaPrivateKey{key}, nil
1074}
1075
1076type wrappedSigner struct {
1077 signer crypto.Signer
1078 pubKey PublicKey
1079}
1080
1081// NewSignerFromSigner takes any crypto.Signer implementation and
1082// returns a corresponding Signer interface. This can be used, for
1083// example, with keys kept in hardware modules.
1084func NewSignerFromSigner(signer crypto.Signer) (Signer, error) {
1085 pubKey, err := NewPublicKey(signer.Public())
1086 if err != nil {
1087 return nil, err
1088 }
1089
1090 return &wrappedSigner{signer, pubKey}, nil
1091}
1092
1093func (s *wrappedSigner) PublicKey() PublicKey {
1094 return s.pubKey
1095}
1096
1097func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
1098 return s.SignWithAlgorithm(rand, data, s.pubKey.Type())
1099}
1100
1101func (s *wrappedSigner) Algorithms() []string {
1102 return algorithmsForKeyFormat(s.pubKey.Type())
1103}
1104
1105func (s *wrappedSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
1106 if algorithm == "" {
1107 algorithm = s.pubKey.Type()
1108 }
1109
1110 if !contains(s.Algorithms(), algorithm) {
1111 return nil, fmt.Errorf("ssh: unsupported signature algorithm %q for key format %q", algorithm, s.pubKey.Type())
1112 }
1113
1114 hashFunc := hashFuncs[algorithm]
1115 var digest []byte
1116 if hashFunc != 0 {
1117 h := hashFunc.New()
1118 h.Write(data)
1119 digest = h.Sum(nil)
1120 } else {
1121 digest = data
1122 }
1123
1124 signature, err := s.signer.Sign(rand, digest, hashFunc)
1125 if err != nil {
1126 return nil, err
1127 }
1128
1129 // crypto.Signer.Sign is expected to return an ASN.1-encoded signature
1130 // for ECDSA and DSA, but that's not the encoding expected by SSH, so
1131 // re-encode.
1132 switch s.pubKey.(type) {
1133 case *ecdsaPublicKey, *dsaPublicKey:
1134 type asn1Signature struct {
1135 R, S *big.Int
1136 }
1137 asn1Sig := new(asn1Signature)
1138 _, err := asn1.Unmarshal(signature, asn1Sig)
1139 if err != nil {
1140 return nil, err
1141 }
1142
1143 switch s.pubKey.(type) {
1144 case *ecdsaPublicKey:
1145 signature = Marshal(asn1Sig)
1146
1147 case *dsaPublicKey:
1148 signature = make([]byte, 40)
1149 r := asn1Sig.R.Bytes()
1150 s := asn1Sig.S.Bytes()
1151 copy(signature[20-len(r):20], r)
1152 copy(signature[40-len(s):40], s)
1153 }
1154 }
1155
1156 return &Signature{
1157 Format: algorithm,
1158 Blob: signature,
1159 }, nil
1160}
1161
1162// NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey,
1163// or ed25519.PublicKey returns a corresponding PublicKey instance.
1164// ECDSA keys must use P-256, P-384 or P-521.
1165func NewPublicKey(key interface{}) (PublicKey, error) {
1166 switch key := key.(type) {
1167 case *rsa.PublicKey:
1168 return (*rsaPublicKey)(key), nil
1169 case *ecdsa.PublicKey:
1170 if !supportedEllipticCurve(key.Curve) {
1171 return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported")
1172 }
1173 return (*ecdsaPublicKey)(key), nil
1174 case *dsa.PublicKey:
1175 return (*dsaPublicKey)(key), nil
1176 case ed25519.PublicKey:
1177 if l := len(key); l != ed25519.PublicKeySize {
1178 return nil, fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l)
1179 }
1180 return ed25519PublicKey(key), nil
1181 default:
1182 return nil, fmt.Errorf("ssh: unsupported key type %T", key)
1183 }
1184}
1185
1186// ParsePrivateKey returns a Signer from a PEM encoded private key. It supports
1187// the same keys as ParseRawPrivateKey. If the private key is encrypted, it
1188// will return a PassphraseMissingError.
1189func ParsePrivateKey(pemBytes []byte) (Signer, error) {
1190 key, err := ParseRawPrivateKey(pemBytes)
1191 if err != nil {
1192 return nil, err
1193 }
1194
1195 return NewSignerFromKey(key)
1196}
1197
1198// ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private
1199// key and passphrase. It supports the same keys as
1200// ParseRawPrivateKeyWithPassphrase.
1201func ParsePrivateKeyWithPassphrase(pemBytes, passphrase []byte) (Signer, error) {
1202 key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase)
1203 if err != nil {
1204 return nil, err
1205 }
1206
1207 return NewSignerFromKey(key)
1208}
1209
1210// encryptedBlock tells whether a private key is
1211// encrypted by examining its Proc-Type header
1212// for a mention of ENCRYPTED
1213// according to RFC 1421 Section 4.6.1.1.
1214func encryptedBlock(block *pem.Block) bool {
1215 return strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED")
1216}
1217
1218// A PassphraseMissingError indicates that parsing this private key requires a
1219// passphrase. Use ParsePrivateKeyWithPassphrase.
1220type PassphraseMissingError struct {
1221 // PublicKey will be set if the private key format includes an unencrypted
1222 // public key along with the encrypted private key.
1223 PublicKey PublicKey
1224}
1225
1226func (*PassphraseMissingError) Error() string {
1227 return "ssh: this private key is passphrase protected"
1228}
1229
1230// ParseRawPrivateKey returns a private key from a PEM encoded private key. It supports
1231// RSA, DSA, ECDSA, and Ed25519 private keys in PKCS#1, PKCS#8, OpenSSL, and OpenSSH
1232// formats. If the private key is encrypted, it will return a PassphraseMissingError.
1233func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
1234 block, _ := pem.Decode(pemBytes)
1235 if block == nil {
1236 return nil, errors.New("ssh: no key found")
1237 }
1238
1239 if encryptedBlock(block) {
1240 return nil, &PassphraseMissingError{}
1241 }
1242
1243 switch block.Type {
1244 case "RSA PRIVATE KEY":
1245 return x509.ParsePKCS1PrivateKey(block.Bytes)
1246 // RFC5208 - https://tools.ietf.org/html/rfc5208
1247 case "PRIVATE KEY":
1248 return x509.ParsePKCS8PrivateKey(block.Bytes)
1249 case "EC PRIVATE KEY":
1250 return x509.ParseECPrivateKey(block.Bytes)
1251 case "DSA PRIVATE KEY":
1252 return ParseDSAPrivateKey(block.Bytes)
1253 case "OPENSSH PRIVATE KEY":
1254 return parseOpenSSHPrivateKey(block.Bytes, unencryptedOpenSSHKey)
1255 default:
1256 return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
1257 }
1258}
1259
1260// ParseRawPrivateKeyWithPassphrase returns a private key decrypted with
1261// passphrase from a PEM encoded private key. If the passphrase is wrong, it
1262// will return x509.IncorrectPasswordError.
1263func ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase []byte) (interface{}, error) {
1264 block, _ := pem.Decode(pemBytes)
1265 if block == nil {
1266 return nil, errors.New("ssh: no key found")
1267 }
1268
1269 if block.Type == "OPENSSH PRIVATE KEY" {
1270 return parseOpenSSHPrivateKey(block.Bytes, passphraseProtectedOpenSSHKey(passphrase))
1271 }
1272
1273 if !encryptedBlock(block) || !x509.IsEncryptedPEMBlock(block) {
1274 return nil, errors.New("ssh: not an encrypted key")
1275 }
1276
1277 buf, err := x509.DecryptPEMBlock(block, passphrase)
1278 if err != nil {
1279 if err == x509.IncorrectPasswordError {
1280 return nil, err
1281 }
1282 return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err)
1283 }
1284
1285 var result interface{}
1286
1287 switch block.Type {
1288 case "RSA PRIVATE KEY":
1289 result, err = x509.ParsePKCS1PrivateKey(buf)
1290 case "EC PRIVATE KEY":
1291 result, err = x509.ParseECPrivateKey(buf)
1292 case "DSA PRIVATE KEY":
1293 result, err = ParseDSAPrivateKey(buf)
1294 default:
1295 err = fmt.Errorf("ssh: unsupported key type %q", block.Type)
1296 }
1297 // Because of deficiencies in the format, DecryptPEMBlock does not always
1298 // detect an incorrect password. In these cases decrypted DER bytes is
1299 // random noise. If the parsing of the key returns an asn1.StructuralError
1300 // we return x509.IncorrectPasswordError.
1301 if _, ok := err.(asn1.StructuralError); ok {
1302 return nil, x509.IncorrectPasswordError
1303 }
1304
1305 return result, err
1306}
1307
1308// ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as
1309// specified by the OpenSSL DSA man page.
1310func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
1311 var k struct {
1312 Version int
1313 P *big.Int
1314 Q *big.Int
1315 G *big.Int
1316 Pub *big.Int
1317 Priv *big.Int
1318 }
1319 rest, err := asn1.Unmarshal(der, &k)
1320 if err != nil {
1321 return nil, errors.New("ssh: failed to parse DSA key: " + err.Error())
1322 }
1323 if len(rest) > 0 {
1324 return nil, errors.New("ssh: garbage after DSA key")
1325 }
1326
1327 return &dsa.PrivateKey{
1328 PublicKey: dsa.PublicKey{
1329 Parameters: dsa.Parameters{
1330 P: k.P,
1331 Q: k.Q,
1332 G: k.G,
1333 },
1334 Y: k.Pub,
1335 },
1336 X: k.Priv,
1337 }, nil
1338}
1339
1340func unencryptedOpenSSHKey(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) {
1341 if kdfName != "none" || cipherName != "none" {
1342 return nil, &PassphraseMissingError{}
1343 }
1344 if kdfOpts != "" {
1345 return nil, errors.New("ssh: invalid openssh private key")
1346 }
1347 return privKeyBlock, nil
1348}
1349
1350func passphraseProtectedOpenSSHKey(passphrase []byte) openSSHDecryptFunc {
1351 return func(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) {
1352 if kdfName == "none" || cipherName == "none" {
1353 return nil, errors.New("ssh: key is not password protected")
1354 }
1355 if kdfName != "bcrypt" {
1356 return nil, fmt.Errorf("ssh: unknown KDF %q, only supports %q", kdfName, "bcrypt")
1357 }
1358
1359 var opts struct {
1360 Salt string
1361 Rounds uint32
1362 }
1363 if err := Unmarshal([]byte(kdfOpts), &opts); err != nil {
1364 return nil, err
1365 }
1366
1367 k, err := bcrypt_pbkdf.Key(passphrase, []byte(opts.Salt), int(opts.Rounds), 32+16)
1368 if err != nil {
1369 return nil, err
1370 }
1371 key, iv := k[:32], k[32:]
1372
1373 c, err := aes.NewCipher(key)
1374 if err != nil {
1375 return nil, err
1376 }
1377 switch cipherName {
1378 case "aes256-ctr":
1379 ctr := cipher.NewCTR(c, iv)
1380 ctr.XORKeyStream(privKeyBlock, privKeyBlock)
1381 case "aes256-cbc":
1382 if len(privKeyBlock)%c.BlockSize() != 0 {
1383 return nil, fmt.Errorf("ssh: invalid encrypted private key length, not a multiple of the block size")
1384 }
1385 cbc := cipher.NewCBCDecrypter(c, iv)
1386 cbc.CryptBlocks(privKeyBlock, privKeyBlock)
1387 default:
1388 return nil, fmt.Errorf("ssh: unknown cipher %q, only supports %q or %q", cipherName, "aes256-ctr", "aes256-cbc")
1389 }
1390
1391 return privKeyBlock, nil
1392 }
1393}
1394
1395func unencryptedOpenSSHMarshaler(privKeyBlock []byte) ([]byte, string, string, string, error) {
1396 key := generateOpenSSHPadding(privKeyBlock, 8)
1397 return key, "none", "none", "", nil
1398}
1399
1400func passphraseProtectedOpenSSHMarshaler(passphrase []byte) openSSHEncryptFunc {
1401 return func(privKeyBlock []byte) ([]byte, string, string, string, error) {
1402 salt := make([]byte, 16)
1403 if _, err := rand.Read(salt); err != nil {
1404 return nil, "", "", "", err
1405 }
1406
1407 opts := struct {
1408 Salt []byte
1409 Rounds uint32
1410 }{salt, 16}
1411
1412 // Derive key to encrypt the private key block.
1413 k, err := bcrypt_pbkdf.Key(passphrase, salt, int(opts.Rounds), 32+aes.BlockSize)
1414 if err != nil {
1415 return nil, "", "", "", err
1416 }
1417
1418 // Add padding matching the block size of AES.
1419 keyBlock := generateOpenSSHPadding(privKeyBlock, aes.BlockSize)
1420
1421 // Encrypt the private key using the derived secret.
1422
1423 dst := make([]byte, len(keyBlock))
1424 key, iv := k[:32], k[32:]
1425 block, err := aes.NewCipher(key)
1426 if err != nil {
1427 return nil, "", "", "", err
1428 }
1429
1430 stream := cipher.NewCTR(block, iv)
1431 stream.XORKeyStream(dst, keyBlock)
1432
1433 return dst, "aes256-ctr", "bcrypt", string(Marshal(opts)), nil
1434 }
1435}
1436
1437const privateKeyAuthMagic = "openssh-key-v1\x00"
1438
1439type openSSHDecryptFunc func(CipherName, KdfName, KdfOpts string, PrivKeyBlock []byte) ([]byte, error)
1440type openSSHEncryptFunc func(PrivKeyBlock []byte) (ProtectedKeyBlock []byte, cipherName, kdfName, kdfOptions string, err error)
1441
1442type openSSHEncryptedPrivateKey struct {
1443 CipherName string
1444 KdfName string
1445 KdfOpts string
1446 NumKeys uint32
1447 PubKey []byte
1448 PrivKeyBlock []byte
1449}
1450
1451type openSSHPrivateKey struct {
1452 Check1 uint32
1453 Check2 uint32
1454 Keytype string
1455 Rest []byte `ssh:"rest"`
1456}
1457
1458type openSSHRSAPrivateKey struct {
1459 N *big.Int
1460 E *big.Int
1461 D *big.Int
1462 Iqmp *big.Int
1463 P *big.Int
1464 Q *big.Int
1465 Comment string
1466 Pad []byte `ssh:"rest"`
1467}
1468
1469type openSSHEd25519PrivateKey struct {
1470 Pub []byte
1471 Priv []byte
1472 Comment string
1473 Pad []byte `ssh:"rest"`
1474}
1475
1476type openSSHECDSAPrivateKey struct {
1477 Curve string
1478 Pub []byte
1479 D *big.Int
1480 Comment string
1481 Pad []byte `ssh:"rest"`
1482}
1483
1484// parseOpenSSHPrivateKey parses an OpenSSH private key, using the decrypt
1485// function to unwrap the encrypted portion. unencryptedOpenSSHKey can be used
1486// as the decrypt function to parse an unencrypted private key. See
1487// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key.
1488func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.PrivateKey, error) {
1489 if len(key) < len(privateKeyAuthMagic) || string(key[:len(privateKeyAuthMagic)]) != privateKeyAuthMagic {
1490 return nil, errors.New("ssh: invalid openssh private key format")
1491 }
1492 remaining := key[len(privateKeyAuthMagic):]
1493
1494 var w openSSHEncryptedPrivateKey
1495 if err := Unmarshal(remaining, &w); err != nil {
1496 return nil, err
1497 }
1498 if w.NumKeys != 1 {
1499 // We only support single key files, and so does OpenSSH.
1500 // https://github.com/openssh/openssh-portable/blob/4103a3ec7/sshkey.c#L4171
1501 return nil, errors.New("ssh: multi-key files are not supported")
1502 }
1503
1504 privKeyBlock, err := decrypt(w.CipherName, w.KdfName, w.KdfOpts, w.PrivKeyBlock)
1505 if err != nil {
1506 if err, ok := err.(*PassphraseMissingError); ok {
1507 pub, errPub := ParsePublicKey(w.PubKey)
1508 if errPub != nil {
1509 return nil, fmt.Errorf("ssh: failed to parse embedded public key: %v", errPub)
1510 }
1511 err.PublicKey = pub
1512 }
1513 return nil, err
1514 }
1515
1516 var pk1 openSSHPrivateKey
1517 if err := Unmarshal(privKeyBlock, &pk1); err != nil || pk1.Check1 != pk1.Check2 {
1518 if w.CipherName != "none" {
1519 return nil, x509.IncorrectPasswordError
1520 }
1521 return nil, errors.New("ssh: malformed OpenSSH key")
1522 }
1523
1524 switch pk1.Keytype {
1525 case KeyAlgoRSA:
1526 var key openSSHRSAPrivateKey
1527 if err := Unmarshal(pk1.Rest, &key); err != nil {
1528 return nil, err
1529 }
1530
1531 if err := checkOpenSSHKeyPadding(key.Pad); err != nil {
1532 return nil, err
1533 }
1534
1535 pk := &rsa.PrivateKey{
1536 PublicKey: rsa.PublicKey{
1537 N: key.N,
1538 E: int(key.E.Int64()),
1539 },
1540 D: key.D,
1541 Primes: []*big.Int{key.P, key.Q},
1542 }
1543
1544 if err := pk.Validate(); err != nil {
1545 return nil, err
1546 }
1547
1548 pk.Precompute()
1549
1550 return pk, nil
1551 case KeyAlgoED25519:
1552 var key openSSHEd25519PrivateKey
1553 if err := Unmarshal(pk1.Rest, &key); err != nil {
1554 return nil, err
1555 }
1556
1557 if len(key.Priv) != ed25519.PrivateKeySize {
1558 return nil, errors.New("ssh: private key unexpected length")
1559 }
1560
1561 if err := checkOpenSSHKeyPadding(key.Pad); err != nil {
1562 return nil, err
1563 }
1564
1565 pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
1566 copy(pk, key.Priv)
1567 return &pk, nil
1568 case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
1569 var key openSSHECDSAPrivateKey
1570 if err := Unmarshal(pk1.Rest, &key); err != nil {
1571 return nil, err
1572 }
1573
1574 if err := checkOpenSSHKeyPadding(key.Pad); err != nil {
1575 return nil, err
1576 }
1577
1578 var curve elliptic.Curve
1579 switch key.Curve {
1580 case "nistp256":
1581 curve = elliptic.P256()
1582 case "nistp384":
1583 curve = elliptic.P384()
1584 case "nistp521":
1585 curve = elliptic.P521()
1586 default:
1587 return nil, errors.New("ssh: unhandled elliptic curve: " + key.Curve)
1588 }
1589
1590 X, Y := elliptic.Unmarshal(curve, key.Pub)
1591 if X == nil || Y == nil {
1592 return nil, errors.New("ssh: failed to unmarshal public key")
1593 }
1594
1595 if key.D.Cmp(curve.Params().N) >= 0 {
1596 return nil, errors.New("ssh: scalar is out of range")
1597 }
1598
1599 x, y := curve.ScalarBaseMult(key.D.Bytes())
1600 if x.Cmp(X) != 0 || y.Cmp(Y) != 0 {
1601 return nil, errors.New("ssh: public key does not match private key")
1602 }
1603
1604 return &ecdsa.PrivateKey{
1605 PublicKey: ecdsa.PublicKey{
1606 Curve: curve,
1607 X: X,
1608 Y: Y,
1609 },
1610 D: key.D,
1611 }, nil
1612 default:
1613 return nil, errors.New("ssh: unhandled key type")
1614 }
1615}
1616
1617func marshalOpenSSHPrivateKey(key crypto.PrivateKey, comment string, encrypt openSSHEncryptFunc) (*pem.Block, error) {
1618 var w openSSHEncryptedPrivateKey
1619 var pk1 openSSHPrivateKey
1620
1621 // Random check bytes.
1622 var check uint32
1623 if err := binary.Read(rand.Reader, binary.BigEndian, &check); err != nil {
1624 return nil, err
1625 }
1626
1627 pk1.Check1 = check
1628 pk1.Check2 = check
1629 w.NumKeys = 1
1630
1631 // Use a []byte directly on ed25519 keys.
1632 if k, ok := key.(*ed25519.PrivateKey); ok {
1633 key = *k
1634 }
1635
1636 switch k := key.(type) {
1637 case *rsa.PrivateKey:
1638 E := new(big.Int).SetInt64(int64(k.PublicKey.E))
1639 // Marshal public key:
1640 // E and N are in reversed order in the public and private key.
1641 pubKey := struct {
1642 KeyType string
1643 E *big.Int
1644 N *big.Int
1645 }{
1646 KeyAlgoRSA,
1647 E, k.PublicKey.N,
1648 }
1649 w.PubKey = Marshal(pubKey)
1650
1651 // Marshal private key.
1652 key := openSSHRSAPrivateKey{
1653 N: k.PublicKey.N,
1654 E: E,
1655 D: k.D,
1656 Iqmp: k.Precomputed.Qinv,
1657 P: k.Primes[0],
1658 Q: k.Primes[1],
1659 Comment: comment,
1660 }
1661 pk1.Keytype = KeyAlgoRSA
1662 pk1.Rest = Marshal(key)
1663 case ed25519.PrivateKey:
1664 pub := make([]byte, ed25519.PublicKeySize)
1665 priv := make([]byte, ed25519.PrivateKeySize)
1666 copy(pub, k[32:])
1667 copy(priv, k)
1668
1669 // Marshal public key.
1670 pubKey := struct {
1671 KeyType string
1672 Pub []byte
1673 }{
1674 KeyAlgoED25519, pub,
1675 }
1676 w.PubKey = Marshal(pubKey)
1677
1678 // Marshal private key.
1679 key := openSSHEd25519PrivateKey{
1680 Pub: pub,
1681 Priv: priv,
1682 Comment: comment,
1683 }
1684 pk1.Keytype = KeyAlgoED25519
1685 pk1.Rest = Marshal(key)
1686 case *ecdsa.PrivateKey:
1687 var curve, keyType string
1688 switch name := k.Curve.Params().Name; name {
1689 case "P-256":
1690 curve = "nistp256"
1691 keyType = KeyAlgoECDSA256
1692 case "P-384":
1693 curve = "nistp384"
1694 keyType = KeyAlgoECDSA384
1695 case "P-521":
1696 curve = "nistp521"
1697 keyType = KeyAlgoECDSA521
1698 default:
1699 return nil, errors.New("ssh: unhandled elliptic curve " + name)
1700 }
1701
1702 pub := elliptic.Marshal(k.Curve, k.PublicKey.X, k.PublicKey.Y)
1703
1704 // Marshal public key.
1705 pubKey := struct {
1706 KeyType string
1707 Curve string
1708 Pub []byte
1709 }{
1710 keyType, curve, pub,
1711 }
1712 w.PubKey = Marshal(pubKey)
1713
1714 // Marshal private key.
1715 key := openSSHECDSAPrivateKey{
1716 Curve: curve,
1717 Pub: pub,
1718 D: k.D,
1719 Comment: comment,
1720 }
1721 pk1.Keytype = keyType
1722 pk1.Rest = Marshal(key)
1723 default:
1724 return nil, fmt.Errorf("ssh: unsupported key type %T", k)
1725 }
1726
1727 var err error
1728 // Add padding and encrypt the key if necessary.
1729 w.PrivKeyBlock, w.CipherName, w.KdfName, w.KdfOpts, err = encrypt(Marshal(pk1))
1730 if err != nil {
1731 return nil, err
1732 }
1733
1734 b := Marshal(w)
1735 block := &pem.Block{
1736 Type: "OPENSSH PRIVATE KEY",
1737 Bytes: append([]byte(privateKeyAuthMagic), b...),
1738 }
1739 return block, nil
1740}
1741
1742func checkOpenSSHKeyPadding(pad []byte) error {
1743 for i, b := range pad {
1744 if int(b) != i+1 {
1745 return errors.New("ssh: padding not as expected")
1746 }
1747 }
1748 return nil
1749}
1750
1751func generateOpenSSHPadding(block []byte, blockSize int) []byte {
1752 for i, l := 0, len(block); (l+i)%blockSize != 0; i++ {
1753 block = append(block, byte(i+1))
1754 }
1755 return block
1756}
1757
1758// FingerprintLegacyMD5 returns the user presentation of the key's
1759// fingerprint as described by RFC 4716 section 4.
1760func FingerprintLegacyMD5(pubKey PublicKey) string {
1761 md5sum := md5.Sum(pubKey.Marshal())
1762 hexarray := make([]string, len(md5sum))
1763 for i, c := range md5sum {
1764 hexarray[i] = hex.EncodeToString([]byte{c})
1765 }
1766 return strings.Join(hexarray, ":")
1767}
1768
1769// FingerprintSHA256 returns the user presentation of the key's
1770// fingerprint as unpadded base64 encoded sha256 hash.
1771// This format was introduced from OpenSSH 6.8.
1772// https://www.openssh.com/txt/release-6.8
1773// https://tools.ietf.org/html/rfc4648#section-3.2 (unpadded base64 encoding)
1774func FingerprintSHA256(pubKey PublicKey) string {
1775 sha256sum := sha256.Sum256(pubKey.Marshal())
1776 hash := base64.RawStdEncoding.EncodeToString(sha256sum[:])
1777 return "SHA256:" + hash
1778}