diff options
| author | Han-Wen Nienhuys <hanwen@google.com> | 2013-09-26 11:17:52 -0400 |
|---|---|---|
| committer | Adam Langley <agl@golang.org> | 2013-09-26 11:17:52 -0400 |
| commit | 4e0581245c387292aaa4f50016fbf2c32ed9b954 (patch) | |
| tree | fea957691f2a0a51efe8f158e47e611bc7a1200c /ssh/keys.go | |
| parent | 73e99326fb280d3bfd0c28ed55d0a989bf70f8d8 (diff) | |
| download | go-x-crypto-4e0581245c387292aaa4f50016fbf2c32ed9b954.tar.xz | |
go.crypto/ssh: parse DSA private keys too.
R=golang-dev, agl
CC=golang-dev
https://golang.org/cl/13966043
Diffstat (limited to 'ssh/keys.go')
| -rw-r--r-- | ssh/keys.go | 47 |
1 files changed, 42 insertions, 5 deletions
diff --git a/ssh/keys.go b/ssh/keys.go index 9738694..0c6c6b3 100644 --- a/ssh/keys.go +++ b/ssh/keys.go @@ -12,6 +12,7 @@ import ( "crypto/elliptic" "crypto/rsa" "crypto/x509" + "encoding/asn1" "encoding/base64" "encoding/pem" "errors" @@ -557,8 +558,8 @@ func NewPublicKey(k interface{}) (PublicKey, error) { return sshKey, nil } -// ParsePublicKey parses a PEM encoded private key. Currently, only -// PKCS#1, RSA and ECDSA private keys are supported. +// ParsePublicKey parses a PEM encoded private key. It supports +// PKCS#1, RSA, DSA and ECDSA private keys. func ParsePrivateKey(pemBytes []byte) (Signer, error) { block, _ := pem.Decode(pemBytes) if block == nil { @@ -579,12 +580,48 @@ func ParsePrivateKey(pemBytes []byte) (Signer, error) { return nil, err } rawkey = ec - - // TODO(hanwen): find doc for format and implement PEM parsing - // for DSA keys. + case "DSA PRIVATE KEY": + ec, err := parseDSAPrivate(block.Bytes) + if err != nil { + return nil, err + } + rawkey = ec default: return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) } return NewSignerFromKey(rawkey) } + +// parseDSAPrivate parses a DSA key in ASN.1 DER encoding, as +// documented in the OpenSSL DSA manpage. +// TODO(hanwen): move this in to crypto/x509 after the Go 1.2 freeze. +func parseDSAPrivate(p []byte) (*dsa.PrivateKey, error) { + k := struct { + Version int + P *big.Int + Q *big.Int + G *big.Int + Priv *big.Int + Pub *big.Int + }{} + rest, err := asn1.Unmarshal(p, &k) + if err != nil { + return nil, errors.New("ssh: failed to parse DSA key: " + err.Error()) + } + if len(rest) > 0 { + return nil, errors.New("ssh: garbage after DSA key") + } + + return &dsa.PrivateKey{ + PublicKey: dsa.PublicKey{ + Parameters: dsa.Parameters{ + P: k.P, + Q: k.Q, + G: k.G, + }, + Y: k.Priv, + }, + X: k.Pub, + }, nil +} |
