aboutsummaryrefslogtreecommitdiff
path: root/ssh/keys.go
diff options
context:
space:
mode:
authorHan-Wen Nienhuys <hanwen@google.com>2013-09-26 11:17:52 -0400
committerAdam Langley <agl@golang.org>2013-09-26 11:17:52 -0400
commit4e0581245c387292aaa4f50016fbf2c32ed9b954 (patch)
treefea957691f2a0a51efe8f158e47e611bc7a1200c /ssh/keys.go
parent73e99326fb280d3bfd0c28ed55d0a989bf70f8d8 (diff)
downloadgo-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.go47
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
+}