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.
24
// These constants represent the algorithm names for key types supported by this
27
KeyAlgoRSA = "ssh-rsa"
28
KeyAlgoDSA = "ssh-dss"
29
KeyAlgoECDSA256 = "ecdsa-sha2-nistp256"
30
KeyAlgoECDSA384 = "ecdsa-sha2-nistp384"
31
KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
34
// parsePubKey parses a public key of the given algorithm.
35
// Use ParsePublicKey for keys with prepended algorithm.
36
func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err error) {
42
case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
44
case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01:
45
cert, err := parseCert(in, certToPrivAlgo(algo))
51
return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", err)
54
// parseAuthorizedKey parses a public key in OpenSSH authorized_keys format
55
// (see sshd(8) manual page) once the options and key type fields have been
57
func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) {
58
in = bytes.TrimSpace(in)
60
i := bytes.IndexAny(in, " \t")
66
key := make([]byte, base64.StdEncoding.DecodedLen(len(base64Key)))
67
n, err := base64.StdEncoding.Decode(key, base64Key)
72
out, err = ParsePublicKey(key)
76
comment = string(bytes.TrimSpace(in[i:]))
77
return out, comment, nil
80
// ParseAuthorizedKeys parses a public key from an authorized_keys
81
// file used in OpenSSH according to the sshd(8) manual page.
82
func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) {
84
end := bytes.IndexByte(in, '\n')
92
end = bytes.IndexByte(in, '\r')
97
in = bytes.TrimSpace(in)
98
if len(in) == 0 || in[0] == '#' {
103
i := bytes.IndexAny(in, " \t")
109
if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
110
return out, comment, options, rest, nil
113
// No key type recognised. Maybe there's an options field at
117
var candidateOptions []string
119
for i, b = range in {
120
isEnd := !inQuote && (b == ' ' || b == '\t')
121
if (b == ',' && !inQuote) || isEnd {
122
if i-optionStart > 0 {
123
candidateOptions = append(candidateOptions, string(in[optionStart:i]))
130
if b == '"' && (i == 0 || (i > 0 && in[i-1] != '\\')) {
134
for i < len(in) && (in[i] == ' ' || in[i] == '\t') {
138
// Invalid line: unmatched quote
144
i = bytes.IndexAny(in, " \t")
150
if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
151
options = candidateOptions
152
return out, comment, options, rest, nil
159
return nil, "", nil, nil, errors.New("ssh: no key found")
162
// ParsePublicKey parses an SSH public key formatted for use in
163
// the SSH wire protocol according to RFC 4253, section 6.6.
164
func ParsePublicKey(in []byte) (out PublicKey, err error) {
165
algo, in, ok := parseString(in)
167
return nil, errShortRead
170
out, rest, err = parsePubKey(in, string(algo))
172
return nil, errors.New("ssh: trailing junk in public key")
178
// MarshalAuthorizedKey serializes key for inclusion in an OpenSSH
179
// authorized_keys file. The return value ends with newline.
180
func MarshalAuthorizedKey(key PublicKey) []byte {
182
b.WriteString(key.Type())
184
e := base64.NewEncoder(base64.StdEncoding, b)
185
e.Write(key.Marshal())
191
// PublicKey is an abstraction of different types of public keys.
192
type PublicKey interface {
193
// Type returns the key's type, e.g. "ssh-rsa".
196
// Marshal returns the serialized key data in SSH wire format,
197
// with the name prefix.
200
// Verify that sig is a signature on the given data using this
201
// key. This function will hash the data appropriately first.
202
Verify(data []byte, sig *Signature) error
205
// A Signer can create signatures that verify against a public key.
206
type Signer interface {
207
// PublicKey returns an associated PublicKey instance.
208
PublicKey() PublicKey
210
// Sign returns raw signature for the given data. This method
211
// will apply the hash specified for the keytype to the data.
212
Sign(rand io.Reader, data []byte) (*Signature, error)
215
type rsaPublicKey rsa.PublicKey
217
func (r *rsaPublicKey) Type() string {
221
// parseRSA parses an RSA key according to RFC 4253, section 6.6.
222
func parseRSA(in []byte) (out PublicKey, rest []byte, err error) {
226
Rest []byte `ssh:"rest"`
228
if err := Unmarshal(in, &w); err != nil {
232
if w.E.BitLen() > 24 {
233
return nil, nil, errors.New("ssh: exponent too large")
236
if e < 3 || e&1 == 0 {
237
return nil, nil, errors.New("ssh: incorrect exponent")
240
var key rsa.PublicKey
243
return (*rsaPublicKey)(&key), w.Rest, nil
246
func (r *rsaPublicKey) Marshal() []byte {
247
e := new(big.Int).SetInt64(int64(r.E))
257
return Marshal(&wirekey)
260
func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error {
261
if sig.Format != r.Type() {
262
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type())
264
h := crypto.SHA1.New()
267
return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), crypto.SHA1, digest, sig.Blob)
270
type rsaPrivateKey struct {
274
func (r *rsaPrivateKey) PublicKey() PublicKey {
275
return (*rsaPublicKey)(&r.PrivateKey.PublicKey)
278
func (r *rsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
279
h := crypto.SHA1.New()
282
blob, err := rsa.SignPKCS1v15(rand, r.PrivateKey, crypto.SHA1, digest)
287
Format: r.PublicKey().Type(),
292
type dsaPublicKey dsa.PublicKey
294
func (r *dsaPublicKey) Type() string {
298
// parseDSA parses an DSA key according to RFC 4253, section 6.6.
299
func parseDSA(in []byte) (out PublicKey, rest []byte, err error) {
302
Rest []byte `ssh:"rest"`
304
if err := Unmarshal(in, &w); err != nil {
308
key := &dsaPublicKey{
309
Parameters: dsa.Parameters{
316
return key, w.Rest, nil
319
func (k *dsaPublicKey) Marshal() []byte {
334
func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error {
335
if sig.Format != k.Type() {
336
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
338
h := crypto.SHA1.New()
342
// Per RFC 4253, section 6.6,
343
// The value for 'dss_signature_blob' is encoded as a string containing
344
// r, followed by s (which are 160-bit integers, without lengths or
345
// padding, unsigned, and in network byte order).
346
// For DSS purposes, sig.Blob should be exactly 40 bytes in length.
347
if len(sig.Blob) != 40 {
348
return errors.New("ssh: DSA signature parse error")
350
r := new(big.Int).SetBytes(sig.Blob[:20])
351
s := new(big.Int).SetBytes(sig.Blob[20:])
352
if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) {
355
return errors.New("ssh: signature did not verify")
358
type dsaPrivateKey struct {
362
func (k *dsaPrivateKey) PublicKey() PublicKey {
363
return (*dsaPublicKey)(&k.PrivateKey.PublicKey)
366
func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
367
h := crypto.SHA1.New()
370
r, s, err := dsa.Sign(rand, k.PrivateKey, digest)
375
sig := make([]byte, 40)
379
copy(sig[20-len(rb):20], rb)
380
copy(sig[40-len(sb):], sb)
383
Format: k.PublicKey().Type(),
388
type ecdsaPublicKey ecdsa.PublicKey
390
func (key *ecdsaPublicKey) Type() string {
391
return "ecdsa-sha2-" + key.nistID()
394
func (key *ecdsaPublicKey) nistID() string {
395
switch key.Params().BitSize {
403
panic("ssh: unsupported ecdsa key size")
406
func supportedEllipticCurve(curve elliptic.Curve) bool {
407
return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
410
// ecHash returns the hash to match the given elliptic curve, see RFC
411
// 5656, section 6.2.1
412
func ecHash(curve elliptic.Curve) crypto.Hash {
413
bitSize := curve.Params().BitSize
423
// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1.
424
func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
428
Rest []byte `ssh:"rest"`
431
if err := Unmarshal(in, &w); err != nil {
435
key := new(ecdsa.PublicKey)
439
key.Curve = elliptic.P256()
441
key.Curve = elliptic.P384()
443
key.Curve = elliptic.P521()
445
return nil, nil, errors.New("ssh: unsupported curve")
448
key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes)
449
if key.X == nil || key.Y == nil {
450
return nil, nil, errors.New("ssh: invalid curve point")
452
return (*ecdsaPublicKey)(key), w.Rest, nil
455
func (key *ecdsaPublicKey) Marshal() []byte {
456
// See RFC 5656, section 3.1.
457
keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y)
471
func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
472
if sig.Format != key.Type() {
473
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type())
476
h := ecHash(key.Curve).New()
480
// Per RFC 5656, section 3.1.2,
481
// The ecdsa_signature_blob value has the following specific encoding:
489
if err := Unmarshal(sig.Blob, &ecSig); err != nil {
493
if ecdsa.Verify((*ecdsa.PublicKey)(key), digest, ecSig.R, ecSig.S) {
496
return errors.New("ssh: signature did not verify")
499
type ecdsaPrivateKey struct {
503
func (k *ecdsaPrivateKey) PublicKey() PublicKey {
504
return (*ecdsaPublicKey)(&k.PrivateKey.PublicKey)
507
func (k *ecdsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
508
h := ecHash(k.PrivateKey.PublicKey.Curve).New()
511
r, s, err := ecdsa.Sign(rand, k.PrivateKey, digest)
516
sig := make([]byte, intLength(r)+intLength(s))
517
rest := marshalInt(sig, r)
520
Format: k.PublicKey().Type(),
525
// NewSignerFromKey takes a pointer to rsa, dsa or ecdsa PrivateKey
526
// returns a corresponding Signer instance. EC keys should use P256,
528
func NewSignerFromKey(k interface{}) (Signer, error) {
530
switch t := k.(type) {
531
case *rsa.PrivateKey:
532
sshKey = &rsaPrivateKey{t}
533
case *dsa.PrivateKey:
534
sshKey = &dsaPrivateKey{t}
535
case *ecdsa.PrivateKey:
536
if !supportedEllipticCurve(t.Curve) {
537
return nil, errors.New("ssh: only P256, P384 and P521 EC keys are supported.")
540
sshKey = &ecdsaPrivateKey{t}
542
return nil, fmt.Errorf("ssh: unsupported key type %T", k)
547
// NewPublicKey takes a pointer to rsa, dsa or ecdsa PublicKey
548
// and returns a corresponding ssh PublicKey instance. EC keys should use P256, P384 or P521.
549
func NewPublicKey(k interface{}) (PublicKey, error) {
551
switch t := k.(type) {
553
sshKey = (*rsaPublicKey)(t)
554
case *ecdsa.PublicKey:
555
if !supportedEllipticCurve(t.Curve) {
556
return nil, errors.New("ssh: only P256, P384 and P521 EC keys are supported.")
558
sshKey = (*ecdsaPublicKey)(t)
560
sshKey = (*dsaPublicKey)(t)
562
return nil, fmt.Errorf("ssh: unsupported key type %T", k)
567
// ParsePrivateKey returns a Signer from a PEM encoded private key. It supports
568
// the same keys as ParseRawPrivateKey.
569
func ParsePrivateKey(pemBytes []byte) (Signer, error) {
570
key, err := ParseRawPrivateKey(pemBytes)
575
return NewSignerFromKey(key)
578
// ParseRawPrivateKey returns a private key from a PEM encoded private key. It
579
// supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys.
580
func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
581
block, _ := pem.Decode(pemBytes)
583
return nil, errors.New("ssh: no key found")
587
case "RSA PRIVATE KEY":
588
return x509.ParsePKCS1PrivateKey(block.Bytes)
589
case "EC PRIVATE KEY":
590
return x509.ParseECPrivateKey(block.Bytes)
591
case "DSA PRIVATE KEY":
592
return ParseDSAPrivateKey(block.Bytes)
594
return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
598
// ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as
599
// specified by the OpenSSL DSA man page.
600
func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
609
rest, err := asn1.Unmarshal(der, &k)
611
return nil, errors.New("ssh: failed to parse DSA key: " + err.Error())
614
return nil, errors.New("ssh: garbage after DSA key")
617
return &dsa.PrivateKey{
618
PublicKey: dsa.PublicKey{
619
Parameters: dsa.Parameters{