1
2
3
4
5 package ssh
6
7 import (
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
36
37
38 const (
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
49
50
51 KeyAlgoRSASHA256 = "rsa-sha2-256"
52 KeyAlgoRSASHA512 = "rsa-sha2-512"
53 )
54
55 const (
56
57 SigAlgoRSA = KeyAlgoRSA
58
59 SigAlgoRSASHA2256 = KeyAlgoRSASHA256
60
61 SigAlgoRSASHA2512 = KeyAlgoRSASHA512
62 )
63
64
65
66 func 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
91
92
93 func 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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131 func 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
159
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
166
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
175
176
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
190
191 func 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
223
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
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
272
273 func 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
288
289 func 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
301
302 func MarshalPrivateKey(key crypto.PrivateKey, comment string) (*pem.Block, error) {
303 return marshalOpenSSHPrivateKey(key, comment, unencryptedOpenSSHMarshaler)
304 }
305
306
307
308 func MarshalPrivateKeyWithPassphrase(key crypto.PrivateKey, comment string, passphrase []byte) (*pem.Block, error) {
309 return marshalOpenSSHPrivateKey(key, comment, passphraseProtectedOpenSSHMarshaler(passphrase))
310 }
311
312
313
314
315 type PublicKey interface {
316
317 Type() string
318
319
320
321 Marshal() []byte
322
323
324
325
326
327 Verify(data []byte, sig *Signature) error
328 }
329
330
331
332 type CryptoPublicKey interface {
333 CryptoPublicKey() crypto.PublicKey
334 }
335
336
337
338
339 type Signer interface {
340
341 PublicKey() PublicKey
342
343
344
345
346
347 Sign(rand io.Reader, data []byte) (*Signature, error)
348 }
349
350
351
352
353
354
355
356 type AlgorithmSigner interface {
357 Signer
358
359
360
361
362
363 SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error)
364 }
365
366
367
368 type MultiAlgorithmSigner interface {
369 AlgorithmSigner
370
371
372
373 Algorithms() []string
374 }
375
376
377
378
379
380 func 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
407 type multiAlgorithmSigner struct {
408 AlgorithmSigner
409 supportedAlgorithms []string
410 }
411
412 func (s *multiAlgorithmSigner) Algorithms() []string {
413 return s.supportedAlgorithms
414 }
415
416 func (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
428 func (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
435 type rsaPublicKey rsa.PublicKey
436
437 func (r *rsaPublicKey) Type() string {
438 return "ssh-rsa"
439 }
440
441
442 func 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
466 func (r *rsaPublicKey) Marshal() []byte {
467 e := new(big.Int).SetInt64(int64(r.E))
468
469
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
482 func (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
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
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
536 func (r *rsaPublicKey) CryptoPublicKey() crypto.PublicKey {
537 return (*rsa.PublicKey)(r)
538 }
539
540 type dsaPublicKey dsa.PublicKey
541
542 func (k *dsaPublicKey) Type() string {
543 return "ssh-dss"
544 }
545
546 func checkDSAParams(param *dsa.Parameters) error {
547
548
549
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
558 func 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
583 func (k *dsaPublicKey) Marshal() []byte {
584
585
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
600 func (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
609
610
611
612
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
624 func (k *dsaPublicKey) CryptoPublicKey() crypto.PublicKey {
625 return (*dsa.PublicKey)(k)
626 }
627
628 type dsaPrivateKey struct {
629 *dsa.PrivateKey
630 }
631
632 func (k *dsaPrivateKey) PublicKey() PublicKey {
633 return (*dsaPublicKey)(&k.PrivateKey.PublicKey)
634 }
635
636 func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
637 return k.SignWithAlgorithm(rand, data, k.PublicKey().Type())
638 }
639
640 func (k *dsaPrivateKey) Algorithms() []string {
641 return []string{k.PublicKey().Type()}
642 }
643
644 func (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
670 type ecdsaPublicKey ecdsa.PublicKey
671
672 func (k *ecdsaPublicKey) Type() string {
673 return "ecdsa-sha2-" + k.nistID()
674 }
675
676 func (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
688 type ed25519PublicKey ed25519.PublicKey
689
690 func (k ed25519PublicKey) Type() string {
691 return KeyAlgoED25519
692 }
693
694 func 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
711 func (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
722 func (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
737 func (k ed25519PublicKey) CryptoPublicKey() crypto.PublicKey {
738 return ed25519.PublicKey(k)
739 }
740
741 func supportedEllipticCurve(curve elliptic.Curve) bool {
742 return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
743 }
744
745
746 func 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
777 func (k *ecdsaPublicKey) Marshal() []byte {
778
779 keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y)
780
781
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
795 func (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
805
806
807
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
823 func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey {
824 return (*ecdsa.PublicKey)(k)
825 }
826
827
828
829 type skFields struct {
830
831 Flags byte
832
833
834
835 Counter uint32
836 }
837
838 type skECDSAPublicKey struct {
839
840
841 application string
842 ecdsa.PublicKey
843 }
844
845 func (k *skECDSAPublicKey) Type() string {
846 return KeyAlgoSKECDSA256
847 }
848
849 func (k *skECDSAPublicKey) nistID() string {
850 return "nistp256"
851 }
852
853 func 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
881 func (k *skECDSAPublicKey) Marshal() []byte {
882
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
899 func (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
949 func (k *skECDSAPublicKey) CryptoPublicKey() crypto.PublicKey {
950 return &k.PublicKey
951 }
952
953 type skEd25519PublicKey struct {
954
955
956 application string
957 ed25519.PublicKey
958 }
959
960 func (k *skEd25519PublicKey) Type() string {
961 return KeyAlgoSKED25519
962 }
963
964 func 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
986 func (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
999 func (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
1049 func (k *skEd25519PublicKey) CryptoPublicKey() crypto.PublicKey {
1050 return k.PublicKey
1051 }
1052
1053
1054
1055
1056
1057 func 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
1068 func 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
1076 type wrappedSigner struct {
1077 signer crypto.Signer
1078 pubKey PublicKey
1079 }
1080
1081
1082
1083
1084 func 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
1093 func (s *wrappedSigner) PublicKey() PublicKey {
1094 return s.pubKey
1095 }
1096
1097 func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
1098 return s.SignWithAlgorithm(rand, data, s.pubKey.Type())
1099 }
1100
1101 func (s *wrappedSigner) Algorithms() []string {
1102 return algorithmsForKeyFormat(s.pubKey.Type())
1103 }
1104
1105 func (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
1130
1131
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
1163
1164
1165 func 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
1187
1188
1189 func 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
1199
1200
1201 func 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
1211
1212
1213
1214 func encryptedBlock(block *pem.Block) bool {
1215 return strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED")
1216 }
1217
1218
1219
1220 type PassphraseMissingError struct {
1221
1222
1223 PublicKey PublicKey
1224 }
1225
1226 func (*PassphraseMissingError) Error() string {
1227 return "ssh: this private key is passphrase protected"
1228 }
1229
1230
1231
1232
1233 func 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
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
1261
1262
1263 func 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
1298
1299
1300
1301 if _, ok := err.(asn1.StructuralError); ok {
1302 return nil, x509.IncorrectPasswordError
1303 }
1304
1305 return result, err
1306 }
1307
1308
1309
1310 func 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
1340 func 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
1350 func 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
1395 func unencryptedOpenSSHMarshaler(privKeyBlock []byte) ([]byte, string, string, string, error) {
1396 key := generateOpenSSHPadding(privKeyBlock, 8)
1397 return key, "none", "none", "", nil
1398 }
1399
1400 func 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
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
1419 keyBlock := generateOpenSSHPadding(privKeyBlock, aes.BlockSize)
1420
1421
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
1437 const privateKeyAuthMagic = "openssh-key-v1\x00"
1438
1439 type openSSHDecryptFunc func(CipherName, KdfName, KdfOpts string, PrivKeyBlock []byte) ([]byte, error)
1440 type openSSHEncryptFunc func(PrivKeyBlock []byte) (ProtectedKeyBlock []byte, cipherName, kdfName, kdfOptions string, err error)
1441
1442 type openSSHEncryptedPrivateKey struct {
1443 CipherName string
1444 KdfName string
1445 KdfOpts string
1446 NumKeys uint32
1447 PubKey []byte
1448 PrivKeyBlock []byte
1449 }
1450
1451 type openSSHPrivateKey struct {
1452 Check1 uint32
1453 Check2 uint32
1454 Keytype string
1455 Rest []byte `ssh:"rest"`
1456 }
1457
1458 type 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
1469 type openSSHEd25519PrivateKey struct {
1470 Pub []byte
1471 Priv []byte
1472 Comment string
1473 Pad []byte `ssh:"rest"`
1474 }
1475
1476 type openSSHECDSAPrivateKey struct {
1477 Curve string
1478 Pub []byte
1479 D *big.Int
1480 Comment string
1481 Pad []byte `ssh:"rest"`
1482 }
1483
1484
1485
1486
1487
1488 func 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
1500
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
1617 func marshalOpenSSHPrivateKey(key crypto.PrivateKey, comment string, encrypt openSSHEncryptFunc) (*pem.Block, error) {
1618 var w openSSHEncryptedPrivateKey
1619 var pk1 openSSHPrivateKey
1620
1621
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
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
1640
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
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
1670 pubKey := struct {
1671 KeyType string
1672 Pub []byte
1673 }{
1674 KeyAlgoED25519, pub,
1675 }
1676 w.PubKey = Marshal(pubKey)
1677
1678
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
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
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
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
1742 func 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
1751 func 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
1759
1760 func 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
1770
1771
1772
1773
1774 func FingerprintSHA256(pubKey PublicKey) string {
1775 sha256sum := sha256.Sum256(pubKey.Marshal())
1776 hash := base64.RawStdEncoding.EncodeToString(sha256sum[:])
1777 return "SHA256:" + hash
1778 }
1779
View as plain text