Commit a871db19 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

go.crypto/ssh: parse DSA private keys too.

R=golang-dev, agl
CC=golang-dev
https://codereview.appspot.com/13966043

Committer: Adam Langley <agl@golang.org>
parent 0d859f32
......@@ -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
}
......@@ -132,6 +132,37 @@ AwEHoUQDQgAEi9Hdw6KvZcWxfg2IDhA7UkpDtzzt6ZqJXSsFdLd+Kx4S3Sx4cVO+
}
}
// ssh-keygen -t dsa -f /tmp/idsa.pem
var dsaPEM = `-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQD6PDSEyXiI9jfNs97WuM46MSDCYlOqWw80ajN16AohtBncs1YB
lHk//dQOvCYOsYaE+gNix2jtoRjwXhDsc25/IqQbU1ahb7mB8/rsaILRGIbA5WH3
EgFtJmXFovDz3if6F6TzvhFpHgJRmLYVR8cqsezL3hEZOvvs2iH7MorkxwIVAJHD
nD82+lxh2fb4PMsIiaXudAsBAoGAQRf7Q/iaPRn43ZquUhd6WwvirqUj+tkIu6eV
2nZWYmXLlqFQKEy4Tejl7Wkyzr2OSYvbXLzo7TNxLKoWor6ips0phYPPMyXld14r
juhT24CrhOzuLMhDduMDi032wDIZG4Y+K7ElU8Oufn8Sj5Wge8r6ANmmVgmFfynr
FhdYCngCgYEA3ucGJ93/Mx4q4eKRDxcWD3QzWyqpbRVRRV1Vmih9Ha/qC994nJFz
DQIdjxDIT2Rk2AGzMqFEB68Zc3O+Wcsmz5eWWzEwFxaTwOGWTyDqsDRLm3fD+QYj
nOwuxb0Kce+gWI8voWcqC9cyRm09jGzu2Ab3Bhtpg8JJ8L7gS3MRZK4CFEx4UAfY
Fmsr0W6fHB9nhS4/UXM8
-----END DSA PRIVATE KEY-----`
func TestParseDSA(t *testing.T) {
s, err := ParsePrivateKey([]byte(dsaPEM))
if err != nil {
t.Fatalf("ParsePrivateKey returned error: %s", err)
}
data := []byte("sign me")
sig, err := s.Sign(rand.Reader, data)
if err != nil {
t.Fatalf("dsa.Sign: %v", err)
}
if !s.PublicKey().Verify(data, sig) {
t.Error("Verify failed.")
}
}
func init() {
raw, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
ecdsaKey, _ = NewSignerFromKey(raw)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment